This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:bind9dns [2025/12/28 04:52] – oemb1905 | computing:bind9dns [2026/10/25 19:41] (current) – oemb1905 | ||
|---|---|---|---|
| Line 29: | Line 29: | ||
| * Configuring your Registrar' | * Configuring your Registrar' | ||
| - | This tutorial presumes you already have a working and sufficiently hardened | + | This tutorial presumes you already have three working and sufficiently hardened |
| ------------------------------------------- | ------------------------------------------- | ||
| Line 37: | Line 37: | ||
| Make sure that you set your full hostname with '' | Make sure that you set your full hostname with '' | ||
| - | < | + | < |
| 127.0.0.1 | 127.0.0.1 | ||
| 127.0.1.1 | 127.0.1.1 | ||
| Line 58: | Line 58: | ||
| Here is [[http:// | Here is [[http:// | ||
| - | < | + | < |
| ufw reset | ufw reset | ||
| ufw default deny incoming | ufw default deny incoming | ||
| Line 71: | Line 71: | ||
| Here is [[http:// | Here is [[http:// | ||
| - | < | + | < |
| ufw reset | ufw reset | ||
| ufw default deny incoming | ufw default deny incoming | ||
| Line 88: | Line 88: | ||
| Here is [[http:// | Here is [[http:// | ||
| - | < | + | < |
| ufw reset | ufw reset | ||
| ufw default deny incoming | ufw default deny incoming | ||
| Line 114: | Line 114: | ||
| We can now establish the root zone on the master (ns1) and then tie the two slaves to it. Let's open ''/ | We can now establish the root zone on the master (ns1) and then tie the two slaves to it. Let's open ''/ | ||
| - | < | + | < |
| options { | options { | ||
| directory "/ | directory "/ | ||
| Line 137: | Line 137: | ||
| Now, let's establish the haacksnetworking.com zone, required for the GLUE records and proper functioning of the authoritative part of the authoritative DNS server. Let's open ''/ | Now, let's establish the haacksnetworking.com zone, required for the GLUE records and proper functioning of the authoritative part of the authoritative DNS server. Let's open ''/ | ||
| - | < | + | < |
| zone " | zone " | ||
| type master; | type master; | ||
| Line 148: | Line 148: | ||
| Now that we've created the base server entry and created the master zone, we should restart the service and add a few items to the zone record file it creates for us. Let's do '' | Now that we've created the base server entry and created the master zone, we should restart the service and add a few items to the zone record file it creates for us. Let's do '' | ||
| - | < | + | < |
| $TTL 86400 | $TTL 86400 | ||
| @ | @ | ||
| Line 177: | Line 177: | ||
| In my case, I had previously been using ISP Config for another hobbyist domain (for the kids and cats). So, I also configured that zone at the CLI, also in ''/ | In my case, I had previously been using ISP Config for another hobbyist domain (for the kids and cats). So, I also configured that zone at the CLI, also in ''/ | ||
| - | < | + | < |
| zone " | zone " | ||
| type master; | type master; | ||
| Line 186: | Line 186: | ||
| </ | </ | ||
| - | Now that the family and cat website zone is created, we need to establish its DNS records | + | Now that the family and cat website zone is re-created, we can now establish its DNS records |
| - | < | + | < |
| + | $TTL 86400 | ||
| @ IN SOA ns1.haacksnetworking.com. hostmaster.haacksnetworking.com. ( | @ IN SOA ns1.haacksnetworking.com. hostmaster.haacksnetworking.com. ( | ||
| 2025122311 | 2025122311 | ||
| Line 211: | Line 212: | ||
| Now that we've created our base server and two zones, we can configure ns2 and ns3 as slaves. This is a one-time manual change that's required when doing all of this via the CLI. Eventually, we will cluster our instances using webmin which will create the zone file on the slaves upon creation on the master. At present, however, we are still covering how to do this manually using the CLI. Accordingly, | Now that we've created our base server and two zones, we can configure ns2 and ns3 as slaves. This is a one-time manual change that's required when doing all of this via the CLI. Eventually, we will cluster our instances using webmin which will create the zone file on the slaves upon creation on the master. At present, however, we are still covering how to do this manually using the CLI. Accordingly, | ||
| - | < | + | < |
| zone " | zone " | ||
| type slave; | type slave; | ||
| Line 240: | Line 241: | ||
| At this point, we're still dealing strictly with bind9 and have not setup webmin or the automated clustering features. We will do that soon, but there' | At this point, we're still dealing strictly with bind9 and have not setup webmin or the automated clustering features. We will do that soon, but there' | ||
| + | < | ||
| cd / | cd / | ||
| dnssec-keygen -a ED25519 -b 256 -n ZONE haacksnetworking.com | dnssec-keygen -a ED25519 -b 256 -n ZONE haacksnetworking.com | ||
| Line 245: | Line 247: | ||
| SALT=$(openssl rand -hex 8) | SALT=$(openssl rand -hex 8) | ||
| dnssec-signzone -S -K / | dnssec-signzone -S -K / | ||
| + | </ | ||
| You can of course just run the '' | You can of course just run the '' | ||
| - | < | + | < |
| zone " | zone " | ||
| type master; | type master; | ||
| Line 254: | Line 257: | ||
| allow-transfer { 8.28.86.114; | allow-transfer { 8.28.86.114; | ||
| also-notify { 8.28.86.114; | also-notify { 8.28.86.114; | ||
| + | }; | ||
| </ | </ | ||
| Line 271: | Line 275: | ||
| Enter all of these values, adjusting as needed, into your registrar' | Enter all of these values, adjusting as needed, into your registrar' | ||
| - | < | + | < |
| ; <<>> | ; <<>> | ||
| ;; global options: +cmd | ;; global options: +cmd | ||
| Line 333: | Line 337: | ||
| At this point, you should now have a cert for nsX.haacksnetworking.com. We can now swap the vhosts with our reverse proxy configurations and they will just work like magic when we restart the service. First, let's change our http vhost in ''/ | At this point, you should now have a cert for nsX.haacksnetworking.com. We can now swap the vhosts with our reverse proxy configurations and they will just work like magic when we restart the service. First, let's change our http vhost in ''/ | ||
| - | < | + | < |
| < | < | ||
| ServerName ns1.haacksnetworking.com | ServerName ns1.haacksnetworking.com | ||
| Line 347: | Line 351: | ||
| And, for https vhost in ''/ | And, for https vhost in ''/ | ||
| - | < | + | < |
| < | < | ||
| Line 399: | Line 403: | ||
| {{ : | {{ : | ||
| - | Once you do that, we can create | + | Before |
| - | image of that | + | {{ : |
| - | Later on, once zone is created, it should be noted that the webmin tooling creates a redundant transfer to rule on the slaves. It can be left and is harmless, but here' | + | Once you do that, we can now create a new master |
| - | {{ : | + | {{ : |
| - | Set up rndc in webmin gui | + | Doing this creates the zone on ns1. It looks a little different structurally than what I created on the CLI, but syntactically, |
| - | image of that | + | < |
| + | zone " | ||
| + | type master; | ||
| + | file "/ | ||
| + | allow-transfer { | ||
| + | 8.28.86.114; | ||
| + | 8.28.86.115; | ||
| + | 2604: | ||
| + | 2604: | ||
| + | }; | ||
| + | also-notify { | ||
| + | 8.28.86.114; | ||
| + | 8.28.86.115; | ||
| + | 2604: | ||
| + | 2604: | ||
| + | }; | ||
| + | }; | ||
| + | </ | ||
| - | Once we do that, we show examples of how to create A, AAAA, SPF, and dmarc. NOTE: Remember to test the populate with " | + | The IPv6 addresses above did not populate despite me having those entered in webmin under Bind9 Server > Zone defaults. You can see them in that area below and you can see that a test.club domain lacks them despite being populated there as seen in the screenshot below: |
| - | images | + | {{ : |
| + | |||
| + | This glitch is a bit annoying, but it is not strictly required for the zone to function as only IPv4 is sufficient. If, however, you want to add the IPv6 entries, you do so by navigating to Bind9 Server > Zone Name > Edit Zone Options and simply add them: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | It is not required to change anything on the slaves because these are master node entries and the slaves don't require any of these blocks. The slaves, on the other hand, have created corresponding zone entries like follows in ''/ | ||
| + | |||
| + | < | ||
| + | zone " | ||
| + | type slave; | ||
| + | masters { | ||
| + | 8.28.86.113; | ||
| + | 2604: | ||
| + | }; | ||
| + | allow-transfer { | ||
| + | 8.28.86.113; | ||
| + | 2604: | ||
| + | }; | ||
| + | file "/ | ||
| + | }; | ||
| + | </ | ||
| + | |||
| + | Webmin redundantly creates the transfer rule, but that won't hurt or change anything because it is moot due to the '' | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | Of course, you could also shell into the slaves and remove those transfer rules via the CLI, this is just to show that both methods work and are dealing with the exact same bind9 underbelly. Once we do that, we can !!FINALLY!! create A, AAAA, dmarc, spf, and or any other records we need. Here's what the zone's landing page looks like and what the record pages within it look like: | ||
| + | |||
| + | {{ : | ||
| + | {{ : | ||
| + | {{ : | ||
| + | {{ : | ||
| Now, we do some host testing again. Repeat host commands above | Now, we do some host testing again. Repeat host commands above | ||
| Line 421: | Line 474: | ||
| host cloudcommunity.club ns3.haacksnetworking.com | host cloudcommunity.club ns3.haacksnetworking.com | ||
| | | ||
| - | Once that's working, let's setup DNSSEC using the webmin gui on master ns1. | + | Once that's working, let's setup DNSSEC using the webmin gui on master ns1. To do that navigate to Bind9 DNS Server > Zone > Setup DNS Key: |
| - | image of that | + | {{ : |
| + | |||
| + | Once the DNSSEC key is created and the zone signed, you will, just like above, have to navigate over to your registrar and enter in the algorithm, digest, digest tag, and key tag. To see those values, just select Bind9 DNS Server > Zone > Setup DNS Key and instead | ||
| - | Add section above to use dig in order to verify | + | {{ : |
| + | |||
| + | As a final step, we can use the dig command | ||
| - | dig command | + | dig cloudcommunity.club DNSKEY +dnssec @8.28.86.113 |
| + | dig cloudcommunity.club DNSKEY +dnssec @8.28.86.114 | ||
| + | dig cloudcommunity.club DNSKEY +dnssec @8.28.86.115 | ||
| | | ||
| - | Verify what webmin is doing under the hood. Show examples of the slave entries it makes in named on ns2 and ns3 on the CLI but via webmin. Similarly, show a screen shot of the zone record file for cloudcommunity.club | + | Each node should report |
| + | |||
| + | < | ||
| + | ; <<>> | ||
| + | ;; global options: +cmd | ||
| + | ;; Got answer: | ||
| + | ;; ->> | ||
| + | ;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1 | ||
| + | ;; WARNING: recursion requested but not available | ||
| + | |||
| + | ;; OPT PSEUDOSECTION: | ||
| + | ; EDNS: version: 0, flags: do; udp: 1232 | ||
| + | ; COOKIE: f9d0bef39e0c56da010000006950c6e270c6a99b26e97171 (good) | ||
| + | ;; QUESTION SECTION: | ||
| + | ;cloudcommunity.club. IN DNSKEY | ||
| + | |||
| + | ;; ANSWER SECTION: | ||
| + | cloudcommunity.club. 3600 IN DNSKEY 256 3 15 yCykkNhKUB0H3F7B+F1ydS6lmTaQAhRkVLgq6Fy6xWo= | ||
| + | cloudcommunity.club. 3600 IN DNSKEY 257 3 15 g61Yq+dJTUxZpQDvQfqqK59CUv3IsDXyO8Sy229YVic= | ||
| + | cloudcommunity.club. 3600 IN RRSIG DNSKEY 15 2 3600 20260123020922 20251224020922 188 cloudcommunity.club. sbVDXR4RZpR0s2eXn3wyyJ4JGO2AZpX/ | ||
| + | cloudcommunity.club. 3600 IN RRSIG DNSKEY 15 2 3600 20260123020922 20251224020922 30893 cloudcommunity.club. AjoUcCUneoXo/ | ||
| + | |||
| + | ;; Query time: 100 msec | ||
| + | ;; SERVER: 8.28.86.113# | ||
| + | ;; WHEN: Sat Dec 27 22:57:54 MST 2025 | ||
| + | ;; MSG SIZE rcvd: 402 | ||
| + | </ | ||
| + | |||
| + | === Part 4 - Optional Unbound Recursive Resolver === | ||
| + | |||
| + | Now that you can create any record you please and sign your zones/ | ||
| sudo apt install unbound | sudo apt install unbound | ||
| | | ||
| - | The full unbound tutorial, including lan-side setups, can be found here. For this setup, a simple config such as this should work: | + | The full unbound tutorial, including lan-side setups, can be found [[https:// |
| - | | + | |
| + | # Bind to localhost only | ||
| + | interface: 127.0.0.1 | ||
| + | interface: ::1 | ||
| + | port: 5335 | ||
| + | do-ip4: yes | ||
| + | do-ip6: yes | ||
| + | prefer-ip6: yes | ||
| + | access-control: | ||
| + | access-control: | ||
| + | access-control: | ||
| + | # Optimize for 8 cores | ||
| + | num-threads: | ||
| + | msg-cache-slabs: | ||
| + | rrset-cache-slabs: | ||
| + | infra-cache-slabs: | ||
| + | key-cache-slabs: | ||
| + | # Cache settings for high query volume | ||
| + | cache-max-ttl: | ||
| + | cache-min-ttl: | ||
| + | rrset-cache-size: | ||
| + | msg-cache-size: | ||
| + | key-cache-size: | ||
| + | neg-cache-size: | ||
| + | # Enable prefetch and expired responses | ||
| + | prefetch: yes | ||
| + | prefetch-key: | ||
| + | serve-expired: | ||
| + | serve-expired-ttl: | ||
| + | # DNSSEC validation for DANE | ||
| + | #do-dnssec: yes | ||
| + | harden-dnssec-stripped: | ||
| + | harden-referral-path: | ||
| + | harden-below-nxdomain: | ||
| + | harden-algo-downgrade: | ||
| + | # Performance tweaks | ||
| + | #so-rcvbuf: 4m | ||
| + | #so-sndbuf: 4m | ||
| + | edns-buffer-size: | ||
| + | outgoing-range: | ||
| + | num-queries-per-thread: | ||
| + | jostle-timeout: | ||
| + | # | ||
| + | # Logging (minimal) | ||
| + | verbosity: 1 | ||
| + | log-queries: | ||
| + | log-replies: | ||
| + | use-syslog: yes | ||
| + | # Security and privacy | ||
| + | hide-identity: | ||
| + | hide-version: | ||
| + | use-caps-for-id: | ||
| + | qname-minimisation: | ||
| + | harden-large-queries: | ||
| + | harden-glue: | ||
| + | aggressive-nsec: | ||
| + | # Protocol settings | ||
| + | do-tcp: yes | ||
| + | do-udp: yes | ||
| + | # Disable subnetcache | ||
| + | module-config: " | ||
| | | ||
| It's crucial to bind unbound to 5335 since bind9 is already listening on 53. In order to have local recursive queries use unbound, we need to hijack all outbound resolver queries to ''/ | It's crucial to bind unbound to 5335 since bind9 is already listening on 53. In order to have local recursive queries use unbound, we need to hijack all outbound resolver queries to ''/ | ||
| Line 444: | Line 593: | ||
| After that, adjust the ufw rules to hijack all 53 url queries and send them to 5335. Open ''/ | After that, adjust the ufw rules to hijack all 53 url queries and send them to 5335. Open ''/ | ||
| - | < | + | < |
| # === Added NAT table for local DNS redirection to Unbound on port 5335 === | # === Added NAT table for local DNS redirection to Unbound on port 5335 === | ||
| *nat | *nat | ||
| Line 466: | Line 615: | ||
| If you are interested in setting up one of these authoritative Bind9 DNS clusters that are configured to use either CLI or the convenient webmin interface, just hit me up on Matrix. I'm available here: | If you are interested in setting up one of these authoritative Bind9 DNS clusters that are configured to use either CLI or the convenient webmin interface, just hit me up on Matrix. I'm available here: | ||
| - | * [[https:// | + | * [[https:// |
| + | |||
| + | Updates ... tmp directory was too small: | ||
| + | |||
| + | sudo mkdir -p / | ||
| + | sudo chown root:root / | ||
| + | sudo chmod 700 / | ||
| + | |||
| + | After that, navigate to Webmin Settings > Webmin Configuration and then specify custom tmp directory and enter ''/ | ||
| + | |||
| + | < | ||
| + | < | ||
| + | ServerName ns1.haacksnetworking.com | ||
| + | < | ||
| + | Require ip 185.242.226.78 | ||
| + | Require ip 2606: | ||
| + | </ | ||
| + | RewriteEngine On | ||
| + | RewriteCond %{HTTPS} off | ||
| + | RewriteRule ^ https:// | ||
| + | ProxyPass / | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | Alternately, | ||
| + | |||
| + | < | ||
| + | sudo nano / | ||
| + | [Definition] | ||
| + | failregex = ^< | ||
| + | ignoreregex = ^< | ||
| + | </ | ||
| + | |||
| + | After the filter is created, let's establish the jail: | ||
| + | |||
| + | < | ||
| + | sudo nano / | ||
| + | [webmin-apache] | ||
| + | enabled | ||
| + | port = http, | ||
| + | filter | ||
| + | logpath | ||
| + | / | ||
| + | maxretry | ||
| + | # | ||
| + | # | ||
| + | </ | ||
| + | |||
| + | Once you have setup the filter and jail, reload the configuration '' | ||
| + | sudo'' | ||
| - | --- // | + | --- // |