Hi,

I would like to look at restricting our external DNS servers to only respond for the domains that we own. Firstly, I would like to ask if this is the convention, or does everybody set their DNS to answer all queries for everyone?

Assuming not, we will still want our externals to do recursive lookups for our internal traffic so we will need an ACL to identify internal networks and allow recursion.

Would I also need a 'zone "." recursion no' stanza, so that all other traffic will be denied or would the ACL be enough?

Looking at my named.conf, it looks like it has been set up like this in the past, but this has been commented out.

named.conf: (truncated)

acl dns_servers { internal_dns_ip; internal_dns_ip; };

options {
  directory "/var/named" ;
  allow-query { any; };
#  allow-query { dns_servers; 127.0.0.1; };
#  allow-recursion { dns_servers; 127.0.0.1; };
  allow-recursion { any; };
  allow-transfer { none; };
  allow-notify {master_dns_ip; };
  listen-on-v6 { none; };
  recursive-clients 3500;
  version none;
  zone-statistics yes;
  notify no;
  auth-nxdomain no;
  };

view external {
  match-clients { any; };

  zone "orgname.com" {
    type slave;
    file "/var/named/slave/external/orgname.com";
    masters { master_dns_ip; };
  allow-notify { master_dns_ip; };
    allow-query { any; };
  };

  ... more zones ...
};

Dani AI

Generated

Short answer: do not run an open resolver on your externally-facing authoritative servers. Best practice is to separate authoritative and recursive roles (physically or by BIND views). Authoritative servers should only answer for zones they host; recursion should be allowed only for your internal resolvers.

Clarification on the OP question: recursion is an option, not a per-zone setting, so a zone "." recursion no stanza is not the right approach. Use an ACL for your internal networks and either (a) set allow-recursion/allow-query-cache to that ACL in options, or (b) use two views — an internal view with recursion enabled for the ACL and an external view with recursion disabled. allow-query controls who can query authoritative data; allow-recursion / allow-query-cache control who can trigger/use recursion/cached answers.

Operational hardening and tests (gaps to watch for in the thread): restrict AXFR with allow-transfer and TSIG and use also-notify for slaves; hide or replace the BIND version string as suggested to reduce fingerprinting; run named-checkconf and named-checkzone after changes. Validate behavior from both inside and outside your network (use dig from an external host to confirm the server will not recurse for arbitrary domains). Use firewall rules to block port 53 UDP/TCP from untrusted sources and monitor with tcpdump/logs for unexpected query volume (DNS amplification risk).

Minimal example pattern (illustrative only):

acl "internal" { 10.0.0.0/8; 192.168.0.0/16; 127.0.0.1; };

view "internal" {
  match-clients { internal; };
  recursion yes;
  allow-recursion { internal; };
  # internal zones / forwarders
};

view "external" {
  match-clients { any; };
  recursion no;
  # authoritative zones only
};

Avoid leaving allow-recursion { any; }; in options (that makes an open resolver). Stage changes, test from representative hosts, and separate roles where feasible.

>>I would like to look at restricting our external DNS servers to only respond for the domains that we own. Firstly, I would like to ask if this is the convention, or does everybody set their DNS to answer all queries for everyone?

Typically you allow all queries for domain you are the authority over and block all other external traffic. If this server is located inside a LAN it is common to allow internal traffic to do recursive lookups on any domain.

A domain I own (or used to, it lapsed and someone bought it :P). I allow transfer and set also-notify for my other nameservers

zone "wombatcs.com" {
        type master;
        file "/etc/bind/zones/wombatcs.com";
        allow-transfer { 72.16.x.x; 72.x.17x.x; localhost; 20x.x.2x8.x; };
        allow-query { any; };
        also-notify { 72.16.x.x; x.42.x.219; };
};

For my options configuration to deny queries:

options {
        directory "/var/cache/bind";
        version "NO INFORMATION";

        allow-query { 10.2.1.0/24; localhost; 64.25.1.0/24; 64.x.131.0/24; x.16.141.0/24; x.x.20.228; 72.x.178.0/24; x.196.x.0/24; };
        allow-recursion { 10.2.1.0/24; localhost; 64.x.1.0/24; 64.x.131.0/24; x.16.141.0/24; x.x.20.228; 72.x.178.0/24; x.196.35.0/24; };
        allow-transfer { none; };
        zone-statistics no;
        statistics-file "/var/cache/bind/stats";
        auth-nxdomain no;    # conform to RFC1035

};

You can see I also set a version in my options. I do this to hide the version of BIND because in the past there have been numerous bind exploits that would allow a remote user to become root. You can test this:

sk@sk:/tmp$ dig @localhost version.bind chaos txt

; <<>> DiG 9.4.0 <<>> @localhost version.bind chaos txt
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62932
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;version.bind.                  CH      TXT

;; ANSWER SECTION:
version.bind.           0       CH      TXT     "NO INFORMATION"

;; AUTHORITY SECTION:
version.bind.           0       CH      NS      version.bind.

;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Oct  7 06:44:29 2009
;; MSG SIZE  rcvd: 71
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.