How to Configure BIND DNS Server to Return Different IPs Based on Client Subnet (Split-Horizon DNS)


2 views

In a corporate network with multiple locations connected via VPN, you might need to provide different IP addresses for the same hostname depending on which office the DNS query originates from. This is particularly useful when you have:

  • Office A with local server "dev" at 192.168.1.13
  • Office B that needs to access "dev" via VPN at 192.168.2.13

BIND's view functionality allows you to serve different DNS data to different clients based on their IP addresses. Here's how to implement it:

options {
    directory "/var/named";
    recursion yes;
    allow-query { any; };
};

acl "office_a" {
    192.168.1.0/24;
};

acl "office_b" {
    192.168.2.0/24;
};

view "internal_a" {
    match-clients { office_a; };
    zone "example.com" {
        type master;
        file "/var/named/office_a.example.com.zone";
    };
};

view "internal_b" {
    match-clients { office_b; };
    zone "example.com" {
        type master;
        file "/var/named/office_b.example.com.zone";
    };
};

view "default" {
    match-clients { any; };
    zone "example.com" {
        type master;
        file "/var/named/default.example.com.zone";
    };
};

Create separate zone files for each office:

office_a.example.com.zone:

$TTL 86400
@       IN      SOA     ns1.example.com. admin.example.com. (
                        2023081501 ; Serial
                        3600       ; Refresh
                        1800       ; Retry
                        604800     ; Expire
                        86400      ; Minimum TTL
)
        IN      NS      ns1.example.com.
dev     IN      A       192.168.1.13

office_b.example.com.zone:

$TTL 86400
@       IN      SOA     ns1.example.com. admin.example.com. (
                        2023081501 ; Serial
                        3600       ; Refresh
                        1800       ; Retry
                        604800     ; Expire
                        86400      ; Minimum TTL
)
        IN      NS      ns1.example.com.
dev     IN      A       192.168.2.13

After implementing the configuration:

  1. Reload BIND: sudo systemctl reload named
  2. Test from Office A: dig @dns-server dev.example.com should return 192.168.1.13
  3. Test from Office B: dig @dns-server dev.example.com should return 192.168.2.13

When implementing split-horizon DNS:

  • Keep your zone files synchronized
  • Monitor query performance as views add processing overhead
  • Consider using TSIG for secure zone transfers between views if needed

For more complex scenarios, you might consider using RPZ (Response Policy Zones):

options {
    response-policy { 
        zone "rpz-example"; 
    };
};

zone "rpz-example" {
    type master;
    file "/etc/namedb/rpz-example.zone";
    allow-query { none; };
};

In distributed enterprise networks with VPN connectivity between offices, accessing resources by the same hostname from different locations often requires different IP resolutions. Here's a typical setup:

Office A (Local Network): dev.example.com → 192.168.1.13
Office B (VPN Network): dev.example.com → 192.168.2.13

The solution lies in BIND's view functionality, which allows different DNS responses based on client subnet:

// named.conf
acl "office_a" {
    192.168.1.0/24;
};

acl "office_b" {
    192.168.2.0/24;
};

view "internal_a" {
    match-clients { office_a; };
    zone "example.com" {
        type master;
        file "/var/named/zones/example.com.office_a.db";
    };
};

view "internal_b" {
    match-clients { office_b; };
    zone "example.com" {
        type master;
        file "/var/named/zones/example.com.office_b.db";
    };
};

Create separate zone files for each view:

// example.com.office_a.db
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
    2023081501 ; Serial
    3600       ; Refresh
    1800       ; Retry
    604800     ; Expire
    86400      ; Minimum TTL
)

@       IN NS    ns1.example.com.
dev     IN A     192.168.1.13
// example.com.office_b.db
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (
    2023081501 ; Serial
    3600       ; Refresh
    1800       ; Retry
    604800     ; Expire
    86400      ; Minimum TTL
)

@       IN NS    ns1.example.com.
dev     IN A     192.168.2.13

Key considerations when implementing this solution:

  • Ensure proper file permissions for zone files (typically named:named)
  • Use separate serial numbers when updating zone files
  • Test configuration with named-checkconf before reloading
  • Consider adding a default view for unmatched clients

Test your configuration from both networks:

# From Office A
dig @dns-server dev.example.com

# From Office B (via VPN)
dig @dns-server dev.example.com

The responses should show the respective IP addresses for each location.

While views are powerful, they do add complexity to your DNS infrastructure:

  • Each view maintains separate caches
  • Memory usage increases with multiple views
  • Zone file management becomes more complex