最後更新: 2017-02-21


BIND (Berkeley Internet Name Daemon) also known as NAMED






yum install bind-utils bind


yum install bind-utils bind bind-chroot

# bind-chroot: A chroot runtime environment for the ISC BIND DNS server


Those files are mounted



Check Version


named -v

BIND 9.8.2rc1-RedHat-9.8.2-0.17.rc1.el6_4.4


Run it by command


/usr/local/bind/sbin/named -c /usr/local/bind/etc/named.conf

  • -4                         IPv4 only
  • -c config-file          Default: /etc/named.conf
  • -f                          foreground
  • -u user
  • -v                         version number
  • -V                         version number and build options

# Disable the IPv6 lookups




ps aux | grep named

Chroot 設定


Chroot Environment initialization script will mount the configuration files using the mount –bind command,

There is no need to copy anything into the /var/named/chroot/ directory




Config Service

systemctl disable named

systemctl enable named-chroot

systemctl start named-chroot

# start service 後, 會有特別的 mount point

mount | grep chroot

Those directories are automatically mounted to chroot


Package: bind-chroot

This package contains a tree of files which can be used as a chroot(2) jail for the named(8) program from the BIND package.

  • /usr/lib/systemd/system/named-chroot-setup.service
  • /var/named/chroot/*
  • ...






Listen setting


# 設定 listen 什麼 port

port 53;


# 選擇 listen 那個 interface.

# Multiple listen-on statements are allowed.

listen-on [ port ip_port ] { address_match_list };


listen-on port 53 {; };


# x.x.x.x 係 WAN Interface 的 IP

listen-on port 53 {; x.x.x.x; };


listen-on port 53 { any;};


# turns on BIND to listen for IPv6 queries.
# Multiple listen-on-v6 statements are allowed.


listen-on-v6 {any;};
listen-on-v6 {none;};




SIGHUP(1)                    # Force a reload of the server.
SIGINT, SIGTERM(15)    # Shut down the server.

ps aux

root     26436  0.0  2.0  13928 10352 ?        Ss   Oct22   0:00 /usr/local/bind/sbin/named -c /usr/local/bind/etc/named.conf
root     26444  0.0  2.0  13912 10340 ?        Ss   Oct22   0:08 /usr/local/bind/sbin/named

要兩個 process 都要 kill -1 一次才 reload 到 !!


Log setting


log 一共要設定兩樣東西, 分別是

  • channel            # 設定 log 到那裡去 (file | rsyslog)
  • category          # log 什麼


channel channel_name ; [ channel_name ; ... ]

Standard (pre-defined) values:

  • "default_debug"
  • "default_stderr"      output to stderr (normally the console)
  • "default_syslog"      log everything to syslog (default logging destination)
  • "null"                      discard all log entries

channel 的設定:


# lower levels will not be logged

ritical         # only critical errors.
error         # error and above.
warning     # warning and above.
notice        # notice and above.
info           # info and above - log starting to get chatty.
debug        # debug and above. Various debug levels can be defined with 'debug 0' meaning no debugging.
dynamic     # debug and above.


syslog syslog_facility     

'syslog' indicates that this channel will use syslogd logging features


'null' writes to /dev/null

# From the grammar above 'file', 'syslog', 'stderr' and 'null' are mutually exclusive for a 'channel'.


# The default is 'no'.
print-time yes
print-severity yes
print-category yes

size 與 versions:

# limit to the file size created
size size_spec
size 25m

# Version files are created by BIND by appending .0, .1 etc
# .0 will always contain the last log information


size AND versions => rolled
NO size AND a versions =>  rolled (BIND is restarted)
size AND NO versions => size limit is reached BIND will stop logging


有 default, general, queries, update, resolver, security, xfer-in, xfer-out ...


Logs all query transactions.


Logs all values which are not explicitly defined in category statements


Anything that is not classified as any other item in this list defaults to this category.

general: zone expired
connect(fe80::#53) 22/Invalid argument
socket.c:5268: unexpected error:


Logs all network operations.


Processing of client requests.


notify                     # Logs all NOTIFY operations.

update                   # Logging of all dynamic update (DDNS) transactions

update-security     # Approval and denial of update requests used with DDNS.


Approval and denial of requests.

security: client x.x.x.x#59586: query (cache) '' denied

zone transfers




Lame servers. Mis-configuration in the delegation of domains discovered by BIND 9 when trying to authoritative answers.

If the volume of these messages is high many users elect to send them to the null channel

e.g. category lame-servers {null;};



No matching view clause or unrecognized class value. (default: null )


Default Setting:

logging {
     category default { default_syslog; default_debug; };
     category unmatched { null; };

設定 Example:

options {

logging {
        channel my_default_log {
                print-time yes;
                print-category yes;
                file "data/named.log" versions 4 size 256m;
                severity info;
        category default{

        channel my_security_log {
                print-time yes;
                file "data/security.log" versions 4 size 128m;
                severity info;
        category security{

        category lame-servers {null;};
        category queries{null;};


BIND uses syslogd before a valid logging clause is available
( named.conf parse errors => /var/log/messages )




options {
    recursion yes;
    allow-recursion {;; };




以下設定將 每個 zone 的 設定放在 "/etc/named/named.zones" 裡

在 /etc/named.conf 內加入

include "/etc/named/named.zones";

# 每個 zone 的設定

/etc/named.zones 的內容:

zone "" IN { type master; file "zones/"; allow-update { none; };};

# zone 的 records ( NS, MX, A, CNAME ... )



被攻擊的 DNS 可能


  • Open DNS: is a DNS that will accept recursive queries from external locations.
  • Closed DNS: is a DNS that will accept recursive queries only from an identified (and hopefully trusted) set of clients.
  • DoS attacks: by sending random domain queries
  • DoS amplification attacks: by sending domain specific queries the bad guys can cause your DNS to become part of (amplify the effect of) a wider DoS attack on a particular site.
  • Cache Poisoning: by sending specific queries the bad guys can dictate or control the traffic that leaves your site and thus attempt to spoof responses with nasty and pernicious stuff.

DoS amplification attacks

Feb  5 19:01:27 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53
Feb  5 19:01:28 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53
Feb  5 19:01:28 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53
Feb  5 19:01:28 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53
Feb  5 19:01:28 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53
Feb  5 19:01:28 ns1 named[4819]: error (network unreachable) resolving '': 2400:cb00:2049:1::adf5:3b93#53



1. 用 iptable 去限制 responses

2. 用 "credit" or "token bucket" 去限制 UDP responses (TCP 可以照用)
    (Short truncated (TC=1) responses can be sent to provide rate-limited responses to legitimate clients within a range of forged)
    (Legitimate clients react to dropped or truncated response by retrying with UDP or with TCP respectively.)


iptables -A INPUT -p udp -m udp --dport 53 -m recent --set --name dnslimit --rsource
iptables -A INPUT -p udp -m udp --dport 53 -m recent --name dnslimit --update --seconds 60 --hitcount 11 -j DROP


options {
    rate-limit {
        responses-per-second 5;                  # 0: no limits
        # nodata-per-second N;
        # nxdomain-per-second N;
        # all-per-second N;                      # simply counts all the responses sent to a particular client IP
        window 5;                                # Defaykt: 15s
        ipv4-prefix-length 24;                   # Default is 24
        log-only no;                             # yes: For testing; Default is no
        exempt-clients {address_match_list} ;

Over 了 limit 會有如下的 log

Server log:

limit responses to x.x.x.0/24 for IN A  (001208c4)

Client dig:

;; connection timed out; no servers could be reached


The window adds a longer-term dimension to rate limiting.

 * Responses are tracked within a rolling window of time which defaults to 15 seconds

    responses-per-second=5 AND window=5

    => no more that 25 ( 5 x 5 ) responses within any 5 second window period AND responses/second

 * Rate limiting of individual requests is logged in the query-errors category.

 * All responses to an address block are counted as if to a single client. (Default 24)

 * max-table-size: The maximum size of the table used to track requests and rate limit responses
                               (Each entry in the table is between 40 and 80 bytes), The default is 20,000

 * Use log-only yes to test rate limiting parameters without actually dropping any requests.


Record Format


@               IN NS           Domain.
@               IN TXT          "testing"
@               IN MX 10        mail
@               IN A            IP
mail            IN A            IP
mail        300 IN A            IP2
ftp             IN CNAME        another.domain.


Subdomain setting:

用了 $ORIGIN 後, 下文的 @ 及相對的 domain 將會不同

; sub-domain definitions
$ORIGIN  sub.your.domain
@               IN A            ?.?.?.?
@               IN MX 10        domain.


SOA(Start Of Authority)

作用: 給 Slave Server 在做備份這個 zone 時用到的一些參數


# primary name server: ns0      <-- MNAME field

respond authoritatively for the domain

# admin e-mail:    <-- 建議是用 hostmaster 的

# zone is considered no longer authoritative: 7 天
# (slaves stop responding to queries for the zone)

# NX(negative caching time): the time a NAME ERROR = NXDOMAIN result may be cached by any resolver.

$TTL 2d ;                            ; SOA record 的 TTL, Default = 2 days
@    IN      SOA  (
                     20140101        ; Serial       <-- 多數是日期來.
                     1800            ; Refresh      <-- Slave 隔幾耐 check master Serial number
                     300             ; Retry        <-- 當 refresh 時 contact 唔到 master, 那隔多少秒再試.
                     604800          ; Expire       <-- 7 天 (slaves stop responding to queries for the zone when this time has expired )
                     1800 )          ; NX           <-- 最多是 3h (negative caching time - the time a NAME ERROR = NXDOMAIN)


  • only one SOA record allowed in a zone file


CNAME (Canonical name)  <-- nickname

  • CNAME RRs cannot have any other RRs with the same name, for example, a TXT !! [theoretically not permitted (RFC 1034 section 3.6.2)]
  • CNAME 不能在 root domain [theoretically]


Record TTL


domain.             3600    IN      TXT     "string"



acl "trusted" {;



blackhole defines a address_match_list of hosts that the server will NOT respond to, or answer queries for.

blackhole { address_match_list };





allow-query      { localhost; };  // defaults to allow-query {any;};
                                  // i.e. allow-query {10.0/16;};
recursion no;

(If recursion no; present, defaults to allow-query-cache {none;};)
(If recursion yes; (default) then, if allow-recursion is NOT present, defaults to allow-query-cache {localnets; localhost;};)

recursive-clients 25;
(Defines the number of simultaneous recursive lookups the server will perform on behalf of its clients. )

allow-recursion { trusted; };

acl "trusted" {;

# defines the server interface(s) from which queries are accepted



// allow-query-on defines the server interface(s) from which queries are accepted

Defaults to allow-query-on {any;};



* BIND 9.4 後才有的功能

This was done to limit the number of, possibly inadvertant, OPEN DNS resolvers.


allow-query-cache { address_match_list };
allow-query-cache { 10/8; };


Returned order


Defines that all equal records for all domains will be returned in random order.

rrset-order {order random;};
  • fixed - records are returned in the order they are defined in the zone file
  • random - records are returned in a random order
  • cyclic - records are returned in a round-robin fashion




minimal-responses yes ;      <--- BIND default is no

(server will only add records to the authority and additional data sections when they are required)




forward ( only | first );     <--  "first"(default)  if forwarders not answered will attempt to answer the query.
forwarders {;; };



allow-update - update by key


allow-update { address_match_list };

* hosts that are allowed to submit dynamic updates for master zones
* The default in BIND 9 is to disallow updates from all hosts

# 設定一條 update key
   algorithm HMAC-MD5;
   secret "YOUR_BASE64_KEY";

# disables DDNS explicitly
zone "YOUR_DOMAIN" in{
    type master;
    file "data/YOUR_DOMAIN";
    allow-update {none;}; // no DDNS by default

// DDNS by key
    type master;
    file "data/YOUR_DOMAIN";
    allow-update {
        key "YOUR_KEYNAME";

// DDNS this host only
zone "" in{
....type master;
    allow-update {;}; 

key setting:

    update-policy {
        grant "USER-KEY" subdomain DOMAIN   A;
        // grant [key_name] <name> [hostname]


notify (DNS BIND Zone Transfers and Updates)



# Applicable to both master zones (with 'type master;') and slave zones ('type slave;')(亦可以設定在 global 的 // all zones)
# "NOTIFY" messages are sent to the name servers defined in the NS records for the zone

# 'no': NOTIFY messages are not sent.

# 'yes'(default): when a zone is loaded or changed, NOTIFY messages are sent to the name servers defined in the NS records for the zone

# If set to 'explicit' NOTIFY is only sent to those IP(s) listed in an also-notify statement.

# The receiver of the NOTIFY message should query the zone SOA directly from the IP(s) defined in the zone's masters statement.

notify yes(default) | no | explicit;

options {
    also-notify {;;}; // for all zones
zone " in{
    // NS RRs and global also-notify
    notify yes;

!!! By default, after a slave has transferred a zone it will also send out NOTIFY messages to all the zone's NS RRs (except itself obviously).

    This behavior can be inhibited by using a 'notify no;' statement in the slave's zone clause.

Dec  5 21:07:07 localhost named[1833]: zone x.x.x.x/IN: sending notifies (serial 117)

!!! NOTIFY does not indicate that the zone data has changed, but rather that the zone data may have changed.

    The receiver of the NOTIFY message should query the zone SOA directly from the IP(s) defined in the zone's masters statement.



# Applies to slave zones only

# IP address(es) that are allowed to NOTIFY this server

# The default behaviour is to allow zone updates only from the masters IP(s).

allow-notify { address_match_list };

# allows notify from the defined IPs

allow-notify {;;;};

# allows no notifies

allow-notify {none;};



# 在 master server 設定的

# sent a NOTIFY when the master zone file is reloaded

# servers that will be sent a NOTIFY when the master zone file is reloaded.

# By default BIND9 will send NOTIFY messages to all the target names (right-hand names) that appear in NS RRs for the zone

also-notify { ip_addr [port ip_port] ; [... ;  ] };


master: also-notify   ->> slave: allow-notify


在收到 notity 時

Dec  5 21:22:51 localhost named[2586]: client received notify for zone ''
Dec  5 21:22:51 localhost named[2586]: zone your.domain/IN: Transfer started.
Dec  5 21:22:51 localhost named[2586]: transfer of 'your.domain/IN' from connected using
Dec  5 21:22:51 localhost named[2586]: zone your.domain/IN: transferred serial 191
Dec  5 21:22:51 localhost named[2586]: transfer of 'your.domain/IN' from 
 Transfer completed: 1 messages, 5 records, 225 bytes, 0.198 secs (1136 bytes/sec)
Dec  5 21:22:51 localhost named[2586]: zone your.domain/IN: sending notifies (serial 191)


slave zone



# Slave Zones 的設定放在另外一個設定檔
include "/etc/named/slavezones.conf";


zone "" IN {
    type slave;
    allow-transfer { none; };
    allow-query { any; };
    notify no;
    masters { ip.address.of.master; };
    file "slaves/";

* data folder = /var/named/data

* master => only with slave zones  | defines one or more IP addresses | optional port

masters port 1127 {; key zt-key;};

key-name field defines the key to be used to authenticate the zone transfers when using TSIG and references the name of a key clause;

a corresponding key clause with the same key-name must be present in the master server(s)

zone transfer log ( /var/log/messages )

# master: x.x.x.x
# slave: y.y.y.y (local ip)

Sep  5 16:51:27 ns2 named[11420]: zone Transfer started.
Sep  5 16:51:27 ns2 named[11420]: transfer of '' from x.x.x.x#53: connected using y.y.y.y#52562
Sep  5 16:51:27 ns2 named[11420]: zone transferred serial 2
Sep  5 16:51:27 ns2 named[11420]: transfer of '' from x.x.x.x#53: Transfer completed: 1 messages,
                13 records, 332 bytes, 0.049 secs (6775 bytes/sec)


Compile bind9



[1] 到 找最新的下載檔

wget -O bind-9-10-0b1-2.tar.gz

[2] Install Tools

yum groupinstall "Development tools"

yum install GeoIP GeoIP-devel <-- epel

GeoIP header

GeoIP Package


[3] Compile

tar -zxf bind-9-10-0b1-2.tar.gz

cd bind-9.10.0-P2/


--enable-threads    # enable multithreading

./configure --enable-threads  --with-geoip


Configuration summary:
Optional features enabled:
    Multiprocessing support (--enable-threads)
    GeoIP access control (--with-geoip)
    GSS-API (--with-gssapi)
    ECDSA algorithm support (--with-ecdsa)
    Print backtrace on crash (--enable-backtrace)
    Use symbol table for backtrace, named only (--enable-symtable)
    Dynamically loadable zone (DLZ) drivers:




groupadd -g 20 named

useradd -u 20 -g named -s /bin/false named




# BIND 9.10 built-in

# load geoip

options {
    # "geoip-directory" option
    geoip-directory "/path/to/geoip/database";

# geoip ACLs

acl "example" {
  geoip country US;
  geoip region CA;
  geoip city "Redwood City";


# Any IP which matches will use the defined view clause
# for the source IP address, default to any
# match-clients { address_match_element; ... };
# match-clients {;;!; };

view "example" {
  match-clients { example; };
  zone "" {
    type master;
    file "locals/";
view "default" {
  zone "" {
    type master;
    file "nonlocals/";

file 與 type

  • file                         # Defines the file used by the zone in quoted string format
  • type zone_type


  • master
  • slave
  • in-view
  • hint:              # The initial set of root-servers
                         # When the server starts up it uses the hints zone file to find a root name server and
                         # get the most recent list of root name servers.
  • redirect
  • delegation-only
  • forward          # forwarding on a per-domain or per zone basis.
  • stub:             # similar to a slave zone except that it replicates only the NS records
  • static-stub:

View 'split' DNS using views (internal | external)

view "internal-view" {
  match-clients { internal; };
  zone "." IN {
    type hint;
    file "db.cache";
  zone " " IN {
    type master;
    file "zones/";
    allow-transfer { key TRANSFER; };

view "external-view" {
  match-clients { any; };
  recursion no;
  zone " " IN {
    type master;
    file "zones/";
    allow-transfer { key TRANSFER; };





indicates that a secure DNS service is being used which may be one, or more, of TSIG (for securing zone transfers or DDNS updates), SIG(0) (for securing DDNS updates) or DNSSEC. Since BIND9.5 the default value is dnssec-enable yes;. This statement may be used in a view or global options clause.


indicates that a resolver (a caching or caching-only name server) will attempt to validate replies from DNSSEC enabled (signed) zones. To perform this task the server also needs either a valid trusted-keys clause (containing one or more trusted-anchors or a managed-keys clause. Since 9.5 the default value is dnssec-validation yes;. This statement may be used in a view or global options clause.




rndc - name server control utility

          communicates with the name server over a TCP connection, sending commands authenticated with digital signatures



# bind9 reload zone file:

rndc reload

# toggle query logging

rndc querylog

# Disable rndc

# These control channels are used by the rndc utility to send commands to and
# retrieve non-DNS results from a name server.

controls { };

CLI Usage

rndc <options> <command> <command-options>

    halt — Stops the named service immediately.

    querylog — Logs all queries made to this nameserver.

    refresh — Refreshes the nameserver's database.

    reload — Reloads the zone files but keeps all other previously cached responses.
             If changes only affected a specific zone,
             reload only that specific zone by adding the name of the zone after the reload command.

    stats — Dumps the current named statistics to the "/var/named/named.stats" file.

    stop — Stops the server gracefully

-s <server> — Specifies a server other than the default-server listed in /etc/rndc.conf.

options {
    default-server  localhost;
    default-key     "<key-name>";

-y <key-name> — Specifies a key other than the default-key option in the /etc/rndc.conf file.

-p <port-number> — Specifies a port number to use for the rndc connection other than port 953, the default.

You want a slave name server to initiate a zone transfer immediately.

will cause a zone transfer if the master name server has an equal or lower serial number for the zone

rndc refresh bar.example

rndc: connect failed: connection refused

rndc-confgen > /etc/bind/rndc.key

Debug with log

Enable Log

# To view what the server is doing live, if you have rndc configured run

# where x is the debugging level you want to view

rndc trace x

Disable log

# notrace = Sets the server's debugging level to 0

rndc notrace

Flush cache

# all entries

rndc flush

# all entries for supported from bind 9.3

rndc flushname

# Centos 設定

chown root:named rndc.key

chmod 640 rndc.key


 * 因為 /etc/named.conf 係 world-readable, 所以 key file 放在另一個 file

include "/etc/rndc.key";

controls {
    # default TCP port 953 of the loopback address
    inet port 953
    allow {;} keys { <key-name>; };


key "<key-name>" {
  algorithm hmac-md5;
  secret "<key-value>";





Dec  5 11:55:37 mail named[22289]: error (FORMERR) resolving '':

When acting as a recursive resolver, BIND 9 follows the chain of
delegation from the root, contacting name servers identified for each
domain on the way.

In this case, one of those name servers returned a packet that BIND 9
did not like for some reason - a FORMat ERRor. The offending server is
marked as "lame" since it cannot answer queries for the domain in


block-dns-ddos script



logging {
    channel security_file {
        file "data/security.log" versions 3 size 30m;
    category queries {


-N Block53
-A INPUT -p udp --dport 53 -m state --state NEW -j Block53
-A INPUT -p tcp --dport 53 -m state --state NEW -j Block53
-A Block53 -j ACCEPT


grep $1 /var/named/data/security.log | cut -d' ' -f 2 | cut -d'#' -f 1 | sort | uniq >> /tmp/ip.tmp

sort -u /tmp/ip.tmp > /tmp/ip.txt

wc -l /tmp/ip.txt


iptables -F Block53

while read ip
        echo $ip
        iptables -I Block53 -s $ip -j DROP
done < "/tmp/ip.txt"

echo "Done"


multiple ptr records same ip


It all comes down to unpredictable behavior since the RFC does not impose a limit or a way to handle these PTR records.

Most implementations will choose round-robin and you will not achieve your desired result

(perfect matching between many names to a single IP).