Split-horizon DNS, also known as split-brain DNS, is a technique that allows you to serve different DNS responses to clients based on their network location. You can provide one set of answers for internal clients and a completely different set for external clients.

Let’s see it in action. Imagine we have a web server at web.example.com. Internally, we want clients to connect to a private IP address, say 10.0.0.100. Externally, we want them to connect to a public IP address, 203.0.113.50.

Here’s how we can configure this using BIND, a popular DNS server.

First, on your internal DNS server, you’ll have a zone file for example.com that looks something like this:

$TTL 3600
@       IN      SOA     ns1.internal.example.com. admin.example.com. (
                        2023102701      ; Serial
                        3600            ; Refresh
                        1800            ; Retry
                        604800          ; Expire
                        86400 )         ; Negative Cache TTL
;
@       IN      NS      ns1.internal.example.com.
ns1     IN      A       192.168.1.10    ; Internal IP of the DNS server

web     IN      A       10.0.0.100      ; Internal IP for web.example.com

The key here is the web IN A 10.0.0.100 record. This is what internal clients will see.

Now, on your external DNS server (which is publicly accessible), your zone file for example.com would look like this:

$TTL 3600
@       IN      SOA     ns1.external.example.com. admin.example.com. (
                        2023102701      ; Serial
                        3600            ; Refresh
                        1800            ; Retry
                        604800          ; Expire
                        86400 )         ; Negative Cache TTL
;
@       IN      NS      ns1.external.example.com.
ns1     IN      A       203.0.113.10    ; Public IP of the external DNS server

web     IN      A       203.0.113.50    ; Public IP for web.example.com

Notice the web IN A 203.0.113.50 record. This is what external clients will see.

To make this work, you need to configure your network’s routing and your DNS server’s access control. Internal clients should be configured to use your internal DNS server. External clients (on the internet) should be configured to use your external DNS server. Your external DNS server should not be reachable by internal clients for the example.com zone, and vice-versa.

The problem this solves is security and performance. Internally, you might want to access a resource using a private IP for security reasons or because the public IP is not routable internally. Externally, you need a public IP so the internet can reach your service. Serving different IPs prevents exposing internal network structures and ensures correct routing.

Internally, when a client asks nslookup web.example.com (assuming the client is configured to use the internal DNS server 192.168.1.10), it gets 10.0.0.100. When an external client asks the same question to the external DNS server 203.0.113.10, it gets 203.0.113.50.

This setup is typically managed by having two separate DNS servers, or one DNS server with access control lists (ACLs) and views. In BIND, views are the mechanism for this. A view allows you to define different zone configurations based on the client’s IP address.

Here’s a snippet of a BIND named.conf using views:

acl "internal_clients" { 192.168.1.0/24; 10.0.0.0/8; };
acl "external_clients" { any; };

view "internal" {
    match-clients { internal_clients; };
    recursion yes;
    include "/etc/bind/zones.internal";
};

view "external" {
    match-clients { external_clients; };
    recursion yes;
    include "/etc/bind/zones.external";
};

And then your zones.internal and zones.external files would contain the respective zone definitions as shown earlier. The match-clients directive is what directs traffic to the correct view.

A common misconception is that you can achieve split-horizon by simply having duplicate A records in the same zone file. This is incorrect. The DNS protocol does not have a mechanism to differentiate clients based on their network origin for a single query to a single authoritative server. You absolutely need distinct zone data or distinct authoritative servers for different client groups.

The next logical step is to consider how to manage public certificates for services that have different internal and external IP addresses, as this often leads to certificate validation issues.

Want structured learning?

Take the full Dns course →