最後更新: 2018-03-28
目錄
- 安裝
- Testing install
- 設定
- 用 Mysql 做 backend
- Authoritative Server Statistic
- 以 IP 來認證
- pdns-recursor
- DNS record 的格式
- Master & Slaves Server
- pdns_control
- MySetting
- Update Slave DNS record By Script
- domainmetadata
- Troubleshoot
- Doc
介紹
pdns 一共分兩部份, 分別是
- Authoritative Server (no way to pollute the cache): 負責本地的 Domain
- Recursor (consult other authoritative servers): 它用來解釋其他不是本地的 Domain
由它的結構及 Source code 的行數(10,000) 可知, 它比 Bind 更為安全
GUI 介面
poweradmin(https://www.poweradmin.org)
安裝
Debian 6
apt-get install pdns-server pdns-backend-mysql mysql-server
主設定檔
- /etc/powerdns/pdns.conf
- /etc/powerdns/recursor.conf
Testing install
在 /etc/powerdns/pdns.conf 加入以下設定
launch=bind bind-example-zones
執行:
/etc/init.d/pdns restart
/etc/init.d/pdns monitor
already running
測試:
netstat -nl
tcp 0 0 0.0.0.0:53 udp 0 0 0.0.0.0:53
dig www.example.com @127.0.0.1
用 Mysql 做 backend
/etc/powerdns/pdns.conf
#launch=gmysql
/etc/powerdns/pdns.d/pdns.local
gmysql-host=127.0.0.1 gmysql-port=3306 # gmysql-socket=/var/run/mysqld/mysqld.sock gmysql-user=<mysql user> gmysql-password=<mysql password> gmysql-dbname=<powerdns database>
# 建立所需的 table
CREATE DATABASE powerdns;
mysql -u root -p <database> < mysql.sql
# Add a new zone
INSERT INTO domains (name, type) VALUES ('example.org', 'MASTER'); INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.org', 'ns1.example.org hostmaster.example.org 1', 'SOA', 86400, NULL); INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.org', 'ns1.example.org', 'NS', 86400, NULL); INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'example.org', 'ns2.example.org', 'NS', 86400, NULL); INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'ns1.example.org', '10.0.0.1', 'A', 86400, NULL); INSERT INTO records (domain_id, name, content, type, ttl, prio) VALUES (1, 'ns2.example.org', '10.0.0.2', 'A', 86400, NULL);
設定
/etc/powerdns/pdns.conf
# default: 0.0.0.0 allow-recursion=192.168.0.0/24 # Only recurse if question cannot be answered locally lazy-recursion=yes # nameserver(pdns-recursor) to handle recursive queries recursor=127.0.0.1:5353 daemon=yes guardian=yes setgid=pdns setuid=pdns master=no slave=no ### DB # backend threads to start distributor-threads=3 # backends to launch launch=gmysql ### Network local-address=0.0.0.0 local-port=53 disable-tcp=no max-tcp-connections=10 # Maximum number of milliseconds to queue a query queue-limit=1500 chroot=/var/spool/powerdns logfile=/var/log/pdns.log loglevel=4 # Packet Cache (without any further processing) cache-ttl=20 # cache individual backend queries # CNAME 時最有用 query-cache-ttl=20 # caching negative entries, ie, queries that have no answer. negquery-cache-ttl=60 include=/etc/powerdns/pdns.d
說明
default-ttl
Seconds a result is valid if not set otherwise
guardian
Run within a guardian process
This guardian monitors the performance of the inner pdns_server instance.
CLI 'pdns_control' 是透過 guardian 實現某些功能 (ping, status, cycle)
Authoritative Server Statistic
/etc/init.d/pdns dump | tr ',' '\n'
corrupt-packets=0 deferred-cache-inserts=0 deferred-cache-lookup=0 latency=0 packetcache-hit=3 packetcache-miss=6 packetcache-size=0 qsize-q=1 query-cache-hit=4 query-cache-miss=19 recursing-answers=0 recursing-questions=0 servfail-packets=0 tcp-answers=0 tcp-queries=0 timedout-packets=0 udp-answers=9 udp-queries=9 udp4-answers=9 udp4-queries=9 udp6-answers=0 udp6-queries=0
以 IP 來認證
allow-2136-from=127.0.0.1
OR
INSERT INTO domainmetadata (domain_id, kind, content) VALUES (3, 'ALLOW-2136-FROM', '127.0.0.1');
以 KEY 來認證: authorizing updates with TSIG keys
tsigkeys table:
INSERT INTO tsigkeys (name, algorithm, secret) VALUES ('rk01', 'hmac-md5', '??????????????'); INSERT INTO domainmetadata (domain_id, kind, content) VALUES (3, 'TSIG-ALLOW-2136', 'rk01');
pdns-recursor
# Start Service
/etc/init.d/pdns-recursor start # 它 Default 是用 port 53 的, 所以必須更改
# Setting
/etc/powerdns/recursor.conf
# Support IPv6 records
aaaa-additional-processing=off
allow-from=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12
# local-address IP addresses to listen on,
# separated by spaces or commas.
# Also accepts ports.
local-address=127.0.0.1
local-port=5353
# default: yes
daemon=yes
# does not query private space IP addresses
dont-query=127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10
# /etc/hosts
export-etc-hosts=on
# Don't log queries. (default)
quiet=yes
# no matter what the original TTL specified
# max-cache-ttl
# defaults to 3600 seconds
# max-negative-ttl
# max-tcp-clients
# max-tcp-per-client
# network-timeout
# packetcache-ttl
# packetcache-servfail-ttl
# 查看 rec_control top-remotes 用, default:0
remotes-ringbuffer-entries=300
PowerDNS recursor 3.0 uses a fresh UDP source port for each outgoing query
(making spoofing around 64000 times harder)
# PowerDNS detects when it is being sent too many unexpected answers
spoof-nearmiss-max
Recursor Statistic
rec_control 讀取 socket /var/run/pdns_recursor.controlsocket 拿資料
i.e.
rec_control get-all
all-outqueries 9 # UDP queries ........................... answers-slow 1 # after 1 second noerror-answers 5 questions 2 cache-entries 76 cache-entries 10 cache-hits 0 cache-misses 1 unexpected-packets 0 # spoofing
pdns support recursive queries
DNS has two type of server operations:
- Authoritative: information can be stored in it
- Recursive: it directs the query to each individual server in the list (+cached results)
Setting
Authoritative(pdns.conf)
recursor=127.0.0.1
Recursive(recursor.conf)
forward-zones=.=8.8.4.4;8.8.8.8
DNS record 的格式
SOA
The SOA record format is "master_server hostmaster_email serial refresh retry expire default_ttl"
Example:
ns1.datahunter.org datahunter.datahunter.org 1 10800 3600 604800 3600
Setting
# New in version 4.4.0
default-soa-content
Default: a.misconfigured.dns.server.invalid hostmaster.@ 0 10800 3600 604800 3600
# Old Version
# The setting has been removed in 4.4.0
default-soa-name # ns1.your.domain default-soa-mail # admin.your.domain soa-expire-default 604800 # 7 days soa-minimum-ttl 3600 soa-refresh-default 10800 soa-retry-default 3600
Master & Slaves Server
Diagram:
ns1: 10.0.0.1 (Master)
ns2: 10.0.0.2 (Slave)
On The Master Server:
# SLAVE_IP. Format: IP OR IP/N allow-axfr-ips=10.0.0.2 # yes => Do not allow zone transfers ( Default: no ) disable-axfr=no # yes => Turn on master support ( Default: no ) master=yes # Allow AXFR NOTIFY from these IP ranges.( Default: 0.0.0.0/0 ) # Setting this to an empty string will drop all incoming notifies allow-notify-from=
On The Slaves Server:
slave=yes
# Master IP
allow-notify-from=10.0.0.1
Domain 所需的 record:
INSERT INTO supermasters (ip, nameserver, account) VALUES ('10.0.0.1', 'ns2.example.org', '');
P.S.
BIND:
allow-transfer {SLAVE_IP;}
More Info.
master=yes
When operating as a master, PowerDNS sends out notifications of changes to slaves.
Notifications are only sent for domains with type MASTER in your backend. (Table: domains)
Useful CMD
# This instructs PowerDNS to notify all IP addresses it considers to be slaves of this domain.
pdns_control notify <domain>
# This is truly an override and sends a notification to an arbitrary IP address.
# Can be used in also-notify situations
pdns_control notify-host <domain> <ip-address>
also-notify
# IP addresses, separated by commas
# always receive a notification. Even if they do not match the list in only-notify
Log
Slave 沒有 Permission (IP ACL) 時的 Server log
Mar 28 08:50:45 localhost pdns[7441]: AXFR of domain 'a.com' denied to s.s.s.s
成功 Server log
Mar 28 03:16:29 localhost pdns[7441]: AXFR of domain 'a.com' initiated by s.s.s.s ... Mar 28 03:16:29 localhost pdns[7441]: AXFR of domain 'a.com' to s.s.s.s finished
Slave Log:
Master 沒有轉 SN (Slave 不用更新)
28-Mar-2018 15:06:17.556 notify: client MasterIP#37883: received notify for zone 'a.com'
Slave 成功 (SN 有更新)
28-Mar-2018 15:19:31.738 notify: client MasterIP#37883: received notify for zone 'a.com' 28-Mar-2018 15:19:31.739 general: zone a.com/IN: Transfer started. 28-Mar-2018 15:19:31.740 xfer-in: transfer of 'a.com/IN' from MasterIP#53: connected using SlaveIP#54856 28-Mar-2018 15:19:31.745 general: zone a.com/IN: transferred serial 2018032802 28-Mar-2018 15:19:31.745 xfer-in: transfer of 'a.com/IN' from MasterIP#53: Transfer completed: 3 messages, 46 records, 1187 bytes, 0.004 secs (296750 bytes/sec) 28-Mar-2018 15:19:31.745 notify: zone a.com/IN: sending notifies (serial 2018032802)
Master notify Slave, 但 Slave 沒有 set zone 或 IP 不對
28-Mar-2018 15:11:41.618 notify: client MasterIP#37883: received notify for zone 'a.com': not authoritative
Master 的 Data 有問題
28-Mar-2018 11:24:00.613 notify: client MasterIP#37883: received notify for zone 'a.com' 28-Mar-2018 11:24:00.861 general: zone a.com/IN: Transfer started. 28-Mar-2018 11:24:00.871 xfer-in: transfer of 'a.com/IN' from MasterIP#53: connected using SlaveIP#37080 28-Mar-2018 11:24:00.877 xfer-in: transfer of 'a.com/IN' from MasterIP#53: failed while receiving responses: CNAME and other data 28-Mar-2018 11:24:00.877 xfer-in: transfer of 'a.com/IN' from MasterIP#53: Transfer completed: 2 messages, 52 records, 1221 bytes, 0.006 secs (203500 bytes/sec)
A CNAME record is not allowed to coexist with any other data.
In other words, if a.com is an alias for a.com, you can't also have an MX record for a.com, or an A record, or even a TXT record.
DOC
http://doc.powerdns.com/html/slave.html
pdns_control
pdns_control version
3.3
pdns_control ping
PONG
pdns_control status
1010: Child running on pid 2258
pdns_control uptime
1.3 minutes
pdns_control reload # reload all zones
Ok
pdns_control ccounts
negative queries: 10, queries: 7, non-recursive packets: 8, recursive packets: 0
pdns_control cycle # restart instance
ok
MySetting
# Version 3.3
/etc/powerdns/pdns.conf
master=yes
# Cache Setting
cache-ttl=20 # entire packets cache
negquery-cache-ttl=60 # cache individual backend queries
query-cache-ttl=20 # cache individual backend queries
disable-tcp=no
# LOG Setting
# 在新版裡, 已唔支援 use-logfile=yes, 如果仍想獨立 log file, 就要
# logging to local0
logging-facility=0
loglevel=4
query-logging=no
service pdns restart
/etc/rsyslog.d/40-pdns.conf
local0.info -/var/log/pdns.log
service rsyslog restart
Update Slave DNS record By Script
update-sn.sh
#!/bin/bash # # sync dns record to slave(i.e. ns2) by update SOA record SN # # mysql login user=powerdns pass=???? MyDoamin=???? Admin=tim@???? MySN=$(date +%y%m%d%H%M) MyContent="ns1.$MyDoamin $Admin $MySN 1800 300 604800 600" MySQL="update records set content=\"$MyContent\" where type=\"SOA\" and name=\"$MyDoamin\"" # run sql echo $MySQL | mysql -u $user $user -p$pass echo "Done"
其他工具
zone2sql
Web Pannel
- Poweradmin ( https://www.poweradmin.org/ )
Install from PowerDNS repos
yum install epel-release yum-plugin-priorities
curl -o /etc/yum.repos.d/powerdns-rec-43.repo https://repo.powerdns.com/repo-files/centos-rec-43.repo
yum install pdns # PowerDNS Authoritative Server - version 4.3.X
yum install pdns-recursor # PowerDNS Recursor - version 4.3.X
Web API
The PowerDNS Authoritative Server features a built-in webserver that exposes a JSON/REST API
Port: 8081/TCP
Setting
# a webserver is launched webserver=yes # Defaut: 8081 webserver-port=8081 # Defaults to 127.0.0.1 webserver-address=0.0.0.0 # only allowed from these subnets webserver-allow-from=127.0.0.1,192.168.200.0/24 # none, normal, detailed webserver-loglevel=normal # plaintext password # webserver-password=123456 # API api=yes api-key=changeme
# Checking
curl -H 'X-API-Key: ????' http://pdns:8081/api/v1/servers/localhost | jq .
{ "config_url": "/api/v1/servers/localhost/config{/config_setting}", "daemon_type": "authoritative", "id": "localhost", "type": "Server", "url": "/api/v1/servers/localhost", "version": "4.3.1", "zones_url": "/api/v1/servers/localhost/zones{/zone}" }
# Add / Replace record to the zone
URL='http://pdns:8081/api/v1/servers/localhost/zones/dnslink.hk.' ApiKey=???? MyrRecord='{ "rrsets": [ { "name": "dnslink.hk.", "ttl": 600, "type": "A", "changetype": "REPLACE", "records": [ { "content": "127.0.0.1", "disabled": false, "type": "A" }, { "content": "127.0.0.2", "disabled": false, "type": "A" } ] } ] }' echo $MyrRecord curl -X PATCH --data "$MyrRecord" -H "X-API-Key: $ApiKey" $URL | jq .
domainmetadata
mysql> select * from domainmetadata;
+----+-----------+--------------+---------------------+ | id | domain_id | kind | content | +----+-----------+--------------+---------------------+ | 70 | 20 | SOA-EDIT-API | DEFAULT | | 71 | 20 | SOA-EDIT | INCEPTION-INCREMENT | | 72 | 20 | API-RECTIFY | 1 | +----+-----------+--------------+---------------------+
SOA-EDIT
Powerdns will always use SOA-EDIT when serving SOA records,
thus a query for the SOA record of the recently update domain,
might have an unexpected result due to a SOA-EDIT setting.
DEFAULT:
Generate a soa serial of YYYYMMDD01.
If the current serial is lower than the generated serial, use the generated serial.
If the current serial is higher or equal to the generated serial, increase the current serial by 1.
INCEPTION
sets the SOA Serial to the current two-week signing period start in YYYYMMDD01 format,
EPOCH
is the number of seconds since the epoch
SOA-EDIT-API
On changes to the contents of a zone made through the API,
the SOA record will be edited according to the SOA-EDIT-API rules.
These rules are the same as the SOA-EDIT-DNSUPDATE rules.
If not set during zone creation, a SOA-EDIT-API metadata record is created and set to DEFAULT
If this record is removed from the backend,
the default behaviour is to not do any SOA editing based on this setting.
Troubleshoot
log
Feb 16 15:55:48 ns1 pdns[2705]: Should not get here (x.x|2): please run pdnssec rectify-zone x.x
pdns.local.gmysql.conf
gmysql-dnssec=no
Doc