popular DNS server
read mailing list for security announcements: bind-announce@lists.isc.org
@todo should run bind in two instances for recursive and authoritative
see https://serverfault.com/questions/204159/multiple-instances-of-bind-on-debian#comment181124_204159
Open DNSSEC-enabled recursive resolver with rate-limiting that listens on 53 UDP/TCP and 443 with DoH.
Also open port 80 for certbot HTTP challenge.
Get certificates with certbot certonly --standalone --preferred-challenges http --agree-tos --email changeme@example.com -d ns.example.com
/etc/named.conf.options
// RNDC key
key "rndc-key" {
algorithm hmac-sha256;
secret "secretkey=";
};
// TLS certs for DoH and DoT
// requires open ports 80 and 443 for auto renewal with certbot
tls letsencryptctq {
cert-file "/etc/letsencrypt/live/orion.ctq.ro/fullchain.pem";
key-file "/etc/letsencrypt/live/orion.ctq.ro/privkey.pem";
};
options {
directory "/var/cache/bind";
// hide version
version "1337.69.420";
// serve DNS over UDP/TCP standard port 53
listen-on { any; };
listen-on-v6 { any; };
// serve DNS over HTTPS
listen-on port 443 tls letsencryptctq http default { any; };
listen-on-v6 port 443 tls letsencryptctq http default { any; };
// serve DNS over TLS
// DoH is used instead to avoid opening up yet another port
// listen-on tls mycert { any; };
// listen-on-v6 tls mycert { any; };
// allow authoritative, recursive and cached lookups from anyone
allow-query { any; };
allow-recursion { any; };
allow-query-cache { any; };
// DNSSEC for all zones
dnssec-policy default;
// various rate limiting
rate-limit {
// valid response rate limit
responses-per-second 1;
all-per-second 1;
// answer(small) every 3rd request w/o valid cookie
slip 3;
// reduce limits in case of high number of queries
qps-scale 200;
// exempt localhost
exempt-clients { 127.0.0.1; };
};
};
// rndc from localhost only
controls {
inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; };
};
/etc/bind/named.conf.local
// loopback address zone
zone "0.0.127.in-addr.arpa" {
type primary;
file "/etc/bind/localhost.rev";
notify no;
};
// ctq.ro zone
zone "ctq.ro" IN {
type primary;
file "/etc/bind/ctq.ro.zone";
allow-update { none; };
};
Under debian, some apparmor rules have to be modified for bind to access /etc/bind/ and /etc/letsencrypt/ for DNSSEC TLS certificates…
Edit /etc/apparmor.d/local/usr.sbin.named and add the following rules:
/etc/bind/** rw, /etc/letsencrypt/** r,
Afterwards reparse the rules with apparmor_parser -r /etc/apparmor.d/usr.sbin.named
See also ISC's article on setting up DoH in bind at https://www.isc.org/blogs/doh-talkdns/
/etc/bind/rndc.conf
key "rndc-key" {
algorithm hmac-sha256;
secret "secretkey=";
};
options {
default-key "rndc-key";
default-server 127.0.0.1;
default-port 953;
};
/etc/bind/rndc.key
key "rndc-key" {
algorithm hmac-sha256;
secret "secretkey=";
};
/etc/bind/localhost.rev
$TTL 1D
@ IN SOA localhost. root.localhost. (
2007091701 ; serial
30800 ; refresh
7200 ; retry
604800 ; expire
300 ) ; minimum
IN NS localhost.
1 IN PTR localhost.
/etc/bind/ctq.ro.zone
$ORIGIN ctq.ro.
$TTL 3600
@ SOA orion postmaster (
2026041002 ; Serial
8h ; Refresh
30m ; Retry
1w ; Expire
1h ) ; Negative Cache TTL
; name servers for this domain
@ NS orion
; sundown hosting root ctq.ro
@ A 140.238.223.96
AAAA 2603:c022:5:faba:0:458e:65d:5dd0
; mail handled by irix
@ MX 10 irix
; mailtrap relay
@ TXT "v=spf1 include:_spf.smtp.mailtrap.live -all"
_dmarc TXT "v=DMARC1; p=reject; rua=mailto:dmarc@smtp-staging.mailtrap.net; ruf=mailto:dmarc@smtp-staging.mailtrap.net; rf=afrf; pct=100"
rwmt2._domainkey CNAME rwmt2.dkim.smtp.mailtrap.live.
rwmt1._domainkey CNAME rwmt1.dkim.smtp.mailtrap.live.
mt96 CNAME smtp.mailtrap.live.
; orion (this machine)
orion A 144.24.233.192
orion AAAA 2603:c022:5:f3cc:46ff:176e:6697:869c
; irix
irix A 140.238.170.217
irix AAAA 2603:c022:5:f3cc:ae9:78e1:78a5:5c3d
; sundown
sundown A 140.238.223.96
sundown AAAA 2603:c022:5:faba:0:458e:65d:5dd0
; carddav caldav on irix
dav CNAME irix
; wildcards
* CNAME sundown
*.irix CNAME irix
Running a recursive open resolver means anyone can ask you for anything.
In general this comes with some risks: cache poisoning and amplification attacks.
See Google's articles on how to mitigate these risks at https://developers.google.com/speed/public-dns/docs/security
See the ISC's best practices for recursive resolvers using BIND at https://kb.isc.org/docs/bind-best-practices-recursive?highlight=best%20practice
Attacker requests (hopefully) uncached domain, flood with forged responses with attacker IPs, etc
DNSSEC can solve these problems IF it is widely implemented.
Other stopgap measures exist to help prevent cache poisoning. Most of these are to increase the entropy of a resolver's DNS requests: query port randomization, name server choice randomization, DNS cookies, query name case randomization…
Test if query port randomization is enabled with DNS OARC's tool at https://www.dns-oarc.net/oarc/services/porttest
@todo how does DNSSEC work?
Most recent versions of bind9 ship with DNSSEC validation (for other domains) enabled by default.
Check if DNSSEC is working with https://internet.nl/connection
Or use dig: dig @your.dns.server.here ftp.isc.org. A +dnssec +multiline
To enable DNSSEC for your own domains, include dnssec-policy default in the options clause to enable it for all zones.
Attackers send small requests with forged source IPs, you send much larger requests back, chaos ensues.
bind9 can ratelimit source IPs with the following config:
options {
...
rate-limit {
responses-per-second 10;
};
};
https://bind9.readthedocs.io/en/latest/reference.html Official documentation
https://wiki.archlinux.org/title/BIND Arch wiki article with examples