"All the configurations and zone files I used are available on GitHub, and I'll walk you through the key parts that made the security features work."
When I decided to dive deep into DNS security, I knew I needed to move beyond the theoretical knowledge I'd picked up over the years. Sure, I understood how DNS queries worked and could troubleshoot basic resolution issues, but I had never actually implemented the security features that make DNS infrastructure robust and secure.
That's when I decided to build my own DNS infrastructure in my home lab using BIND9. My goal was simple: understand how DNS security really works by getting my hands dirty with the actual configurations.
Why BIND9 and Why Security?
I chose BIND9 for two main reasons - it's the most widely deployed DNS server software in enterprise environments, and it has comprehensive security features that I wanted to learn. I wasn't interested in just setting up basic DNS resolution; I wanted to understand split-horizon DNS
, TSIG authentication
, secure zone transfers
, and dynamic DNS security
. The learning approach was straightforward: build it, break it, fix it, and understand what's happening at every step.
The Lab Setup
I created a multi-VLAN environment in my home lab to simulate real-world network segmentation:
- Primary DNS Server: dns1 (192.28.1.213)
- Secondary DNS Server: dns2 (192.24.1.214)
- Domain: gentech.solution
- Internal Network: 192.28.1.0/24, 192.24.1.0/24
- External Network: 192.27.1.0/24 (simulated via different VLAN)
The ease of this setup was that I could test different scenarios by simply switching between VMs on different VLANs - no need for actual separate physical networks.
What Split-Horizon DNS Actually Is
Think of split-horizon DNS like having two different phone books for the same company - one that internal employees see with everyone's extensions, and a public one that only shows the main reception number.
In normal DNS, everyone gets the same answer when they ask "where is vault.gentech.solution?" But with split-horizon DNS, your DNS server is smart enough to know who's asking and gives different answers based on whether you're inside the network or outside.
It's like having a bouncer at a club who knows the regulars. When someone from inside asks about internal systems, they get the real addresses. When strangers from the internet ask, they get nothing - or sometimes even fake information.
Split-Horizon DNS Actually Works
The moment that really made DNS security click for me was when I finally got split-horizon DNS working. I had configured different views in BIND9 - one for internal clients and another for external clients.
Here's what happened during my testing sequence:
- From my internal VM (192.28.1.x), I queried
vault.gentech.solution
- Result:
192.24.1.130
- perfect! - I switched to my external VM (192.27.1.x) and ran the same query
- Result:
NXDOMAIN
- The server acted like the record didn't exist
The same DNS server was giving completely different answers based on where the query came from. Internal users could see sensitive systems like the vault server, while external users got nothing. It wasn't just security through obscurity - it was network-level access control.
What TSIG Authentication Actually Is
Imagine you're running two bank branches that need to share customer account updates with each other. You can't just trust any random person who walks up claiming to be from the other branch - you need a secret handshake that proves they're legitimate.
TSIG (Transaction Signature) is basically that secret handshake for DNS servers. It's a shared secret key that two DNS servers use to prove to each other "yes, I'm really who I say I am, and this data hasn't been tampered with."
Without TSIG, anyone on the internet could potentially trick your DNS servers into accepting fake updates or stealing your entire DNS database through unauthorized zone transfers. With TSIG, every single DNS message gets cryptographically signed - like having a tamper-proof seal on every communication.
TSIG Authentication in Action
When I first configured TSIG between my primary and secondary DNS servers, I'll be honest - I wasn't entirely sure it would work. The concept seemed straightforward enough: generate a shared secret, configure both servers with the same key, and watch them authenticate each other.
But DNS is one of those things where you never really know if your security is working until you test it properly.
I generated a TSIG key (basically a long, random string that both servers would know) and added it to both my primary and secondary BIND9 configurations. The idea was simple: when my secondary server wanted to pull zone updates, it would sign its request with this key. The primary server would verify the signature before sending any data.
When I triggered a legitimate zone transfer with the proper TSIG key:
- The secondary server sent a signed request
- My primary server verified the signature and responded positively
- Zone data flowed smoothly between the servers
- Both servers logged successful, authenticated transactions
- Journal files were created and records updated automatically
It was like watching two security guards exchange proper credentials - professional, efficient, and secure.
Then I decided to play attacker. I spun up another VM and tried to request zone transfers without the TSIG key:
- The requests hit my primary DNS server
- Immediate rejection - not even a "wrong password" message, just flat denial
- Security events logged showing unauthorized transfer attempts
- Zero data leaked to the attacking system
The difference was that legitimate traffic flowed freely, while unauthorized requests got slammed shut immediately.
The Learning Process
What made this project valuable wasn't just getting the configurations working - it was understanding how these security features actually behave in practice. Reading about split-horizon DNS in documentation is one thing; watching it work in real-time with your own test queries is completely different.
The most challenging aspect was getting all the configurations properly coordinated between multiple servers, views, keys, and access control lists. But once everything clicked into place, I had a much deeper appreciation for how enterprise DNS infrastructure protects internal resources while maintaining necessary external services.
The Technical Details
Now, let's dive into the actual BIND9 configurations that created this secure DNS infrastructure. I'll walk you through each section and explain what's happening behind the scenes.
Setting Up Access Control Lists (ACLs)
First, I defined who's "internal" and who can be trusted:
include "/etc/bind/keys/zone-xfer.key";
acl "internal-network" {
192.28.1.0/24;
192.24.1.0/24;
127.0.0.1;
};
acl "secondaries" {
192.24.1.214;
};
What this does: Think of ACLs as VIP lists at a club. The internal-network
ACL defines which IP ranges get the "insider" treatment - they can see everything. The secondaries
ACL identifies my backup DNS server that's allowed to copy zone data.
The zone-xfer.key
file contains the shared secret that makes TSIG authentication work. More on that in a moment.
Split-Horizon Views
Here's where the real thing happens - the same DNS server behaves completely differently based on who's asking:
Internal View (The VIP Section)
view "internal" {
match-clients { internal-network; };
zone "gentech.solution" {
type primary;
file "/etc/bind/zones/db.gentech.solution.internal";
allow-transfer { key "zone-xfer"; secondaries; };
also-notify { 192.24.1.214; };
allow-update { key "zone-xfer"; };
};
What this means: When someone from my internal networks (192.28.1.x or 192.24.1.x) asks about vault.gentech.solution
, they get the internal zone file that contains all the sensitive servers, including the vault at 192.24.1.130
.
The allow-transfer
and allow-update
lines mean "only accept zone transfers and dynamic updates if they're signed with our secret key." No key = no access.
External View (The Public Lobby)
view "external" {
match-clients { any; };
zone "gentech.solution" {
type primary;
file "/etc/bind/zones/db.gentech.solution.external";
allow-transfer { key "zone-xfer"; secondaries; };
also-notify { 192.24.1.214; };
allow-update { key "zone-xfer"; };
};
};
The key difference: External users get the external zone file that only contains basic public information. When they ask about vault.gentech.solution
, they get NXDOMAIN - as far as they know, that server doesn't exist.
Comprehensive Security Logging
The logging setup was crucial for understanding what was happening:
logging {
channel security_log {
file "/var/log/named/security.log" versions 3 size 5m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
channel update_log {
file "/var/log/named/update.log" versions 3 size 5m;
severity info;
print-time yes;
print-severity yes;
print-category yes;
};
// … more channels
category security { security_log; };
category update { update_log; };
category update-security { security_log; };
};
Why this matters: Every TSIG authentication attempt, every zone transfer, every dynamic update gets logged with timestamps and client IPs. When I tested unauthorized access, I could see exactly when and how the attempts were blocked.
Hardening the DNS Server
The security options lock down the server:
The security thinking:
recursion no
means this server only answers for domains it's authoritative forallow-transfer { none; }
blocks zone transfers unless explicitly allowed per-zone- The "Not Disclosed" settings prevent information leakage about the server
- Rate limiting stops abuse and DDoS attempts
How the TSIG Authentication Works
The real security comes from the TSIG keys. Every zone transfer and dynamic update requires this shared secret:
allow-transfer { key "zone-xfer"; secondaries; };
allow-update { key "zone-xfer"; };
In practice: When my secondary server requests a zone transfer, it signs the request with the shared key. BIND verifies the signature and only then allows the transfer. Without the key, requests get denied and logged as security events.
This is what made watching the logs so satisfying - I could see legitimate transfers succeeding and unauthorized attempts getting blocked in real-time.
The Result
This configuration creates multiple layers of security:
- Network segmentation through views
- Cryptographic authentication via TSIG
- Complete audit trails through comprehensive logging
- DDoS protection via rate limiting
- Information hiding to reduce the attack surface
The best thing is that it's all transparent to legitimate users while blocking unauthorized access at every level.
The Zone Files: Where Split-Horizon Happens
Here's where you can see the real difference between what internal and external users get when they query the same domain:
External Zone File
When external users query gentech.solution
, they get this zone file:
@ IN NS ns1.gentech.solution.
@ IN NS ns2.gentech.solution.
; Name server A records (glue)
ns1 IN A 208.67.222.222 # OpenDNS
ns2 IN A 8.8.8.8 # Google DNS
www IN A 8.8.4.4 # Google DNS alt
mail IN A 1.1.1.1 # Cloudflare DNS
What external users see: Just basic public services with generic public IP addresses. No internal systems, no sensitive infrastructure. If they query for vault.gentech.solution
- they get NXDOMAIN (doesn't exist).
Internal Zone File
When internal users query the same domain, they get completely different information:
ns1 A 192.28.1.213 # Real internal DNS server
ns2 A 192.24.1.214 # Real backup DNS server
vault A 192.24.1.130 # SECRET - only internals see this
hrsystem A 192.24.1.135 # HR system - internal only
intranet A 192.28.1.120 # Company intranet
exam A 192.24.1.218 # Exam system
testhost A 192.28.1.199 # Dynamic DNS test host
What internal users see: All the real infrastructure with actual internal IP addresses. The vault.gentech.solution
what external users can't even see? Internal users get 192.24.1.130
.
The Split-Horizon Effect in Action
Same query, different results:
- Internal user queries
vault.gentech.solution
→ Gets192.24.1.130
- External user queries
vault.gentech.solution
→ GetsNXDOMAIN
(server pretends it doesn't exist)
This is security through network segregation - not just hiding information, but serving completely different zone data based on who's asking.
Reverse DNS - Complete the Picture
The reverse zones ensure that IP-to-name lookups also work correctly:
192.24.1.0/24 reverse zone:
214 IN PTR ns2.gentech.solution.
130 IN PTR vault.gentech.solution. # The secret server
135 IN PTR hrsystem.gentech.solution.
192.28.1.0/24 reverse zone:
213 IN PTR ns1.gentech.solution.
120 IN PTR intranet.gentech.solution.
Why reverse zones matter: When internal monitoring tools do reverse DNS lookups on 192.24.1.130
, they get back vault.gentech.solution
. External users can't even reach that IP range, so the reverse lookup is irrelevant to them.
The Security Beauty
This setup creates:
- External attackers scanning
gentech.solution
only see generic public services - Internal users get full access to all company resources with proper internal routing
- No information leakage - sensitive server names and IPs are completely hidden from external view
The same DNS infrastructure serves both audiences with completely different reality maps. That's the power of split-horizon DNS - one server, multiple truths.
Secondary DNS Server: Building Redundancy with TSIG Security
Now that the primary DNS server was working, I needed to set up the secondary server for redundancy. This is where TSIG authentication really shines - ensuring that only authorized servers can replicate zone data.
Secondary Server Configuration
The secondary server configuration is much simpler, but the security is just as tight:
view "internal" {
match-clients { internal-network; };
zone "gentech.solution" {
type secondary;
file "/var/cache/bind/db.gentech.solution.internal.slave";
primaries { 192.28.1.213 key "zone-xfer"; };
notify no;
allow-notify { 192.28.1.213; };
};
What this does: The secondary server says, "I'm a slave for this zone, get data from 192.28.1.213, but ONLY if they provide the correct TSIG key." No key = no zone transfer.
The notify no
setting means the secondary doesn't send notifications, while allow-notify
restricting who can tell it about zone updates.
The Moment of Truth: Testing Everything
Once both servers were configured, I ran comprehensive tests to prove the security model actually worked. Here are the results that convinced me this setup was secure:
Dynamic DNS Security Test
Authorized update (with TSIG key):
$ nsupdate -k /opt/zone_key/zone-xfer.key -v /tmp/ddns-test.txt
[Success - no output]
Unauthorized update (no key):
$ nsupdate -v /tmp/ddns-test.txt update failed: REFUSED
Security logs showed exactly what happened:
update-security: info: signer "zone-xfer" approved
update-security: error: update 'gentech.solution/IN' denied
This was great, legitimate updates succeeded and created journal files automatically, while unauthorized attempts were blocked and logged with full audit trails.
Split-Horizon Results That Proved It Works
Internal client (192.28.1.217) querying vault:
$ dig @192.28.1.213 vault.gentech.solution
vault.gentech.solution. 604800 IN A 192.24.1.130
External client (192.27.1.219) same query:
$ dig @192.28.1.213 vault.gentech.solution
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 13715
Same server, same query, completely different results. Internal users got the real vault server IP, external users got "doesn't exist."
Zone Transfer Security in Action
Authorized transfer (from secondary with TSIG):
xfer-out: info: transfer of 'gentech.solution/IN': AXFR started: TSIG zone-xfer
xfer-out: info: AXFR ended: 1 messages, 11 records, 388 bytes
Unauthorized transfer attempts:
$ dig @192.28.1.213 gentech.solution AXFR ; Transfer failed.
Security log:
security: error: zone transfer 'gentech.solution/AXFR/IN' denied
The logging was incredibly detailed - I could see exactly when transfers succeeded with proper authentication, and when unauthorized attempts were blocked.
What Impressed Me Most
The incremental zone transfer (IXFR) logs showed:
xfer-out: info: transfer of 'gentech.solution/IN': IXFR started: TSIG zone-xfer (serial 2025081707 -> 2025081708)
This wasn't just copying entire zone files - the system was intelligently transferring only the changes between serial numbers, all cryptographically authenticated. When I added that exam.gentech.solution
record via dynamic DNS, only that specific change got replicated to the secondary server.
The Security Model That Actually Works
After all this testing, I had built a DNS infrastructure with:
Multiple security layers:
- Network-based access control (views)
- Cryptographic authentication (TSIG keys)
- Complete audit logging (every operation tracked)
- Automated redundancy (secondary server with secure replication)
Real-world features:
- Split-horizon for internal vs external users
- Secure dynamic DNS updates
- Authenticated zone transfers
- Rate limiting against DDoS
- Information hiding to reduce the attack surface
What This Taught Me
The biggest learning wasn't just getting the configurations right - it was seeing how DNS security actually behaves in practice. Reading about TSIG authentication is one thing; watching unauthorized transfer attempts get blocked while legitimate ones succeed with full audit trails is completely different.
The comprehensive logging meant that in a production environment, security teams would have complete forensic evidence of every DNS operation. No unauthorized access could happen without leaving detailed traces.
Most importantly: This wasn't theoretical security - it was practical, tested, working security that I could verify with my own hands in my home lab.
This project transformed my understanding of DNS from "name resolution service" to "critical infrastructure that requires multiple layers of cryptographic and network-based protection."
Resources & Full Configuration Files
GitHub Repository: https://github.com/Deba1995/DNS-Infrastructure-Design-and-Implementation
This repo contains all the BIND9 configuration files, zone files, and test logs mentioned in this post. Feel free to clone it and adapt it for your own lab environment.
What you'll find:
- Complete primary and secondary server configs
- Internal and external zone files
- TSIG key examples
- Test output logs showing security in action
Have you implemented TSIG authentication or split-horizon DNS in your environment? What security challenges did you face? Share your experiences in the comments below.