Working with legacy infrastructure often presents unique DNS challenges. In healthcare environments where network changes require extensive coordination, we frequently encounter IP scheme conflicts with residential networks - particularly when 192.168.0.0/23 overlaps with common home router configurations.
The existing 1:1 NAT solution (192.168.0.0/23 ↔ 10.22.0.0/23) functions at the network layer but breaks at DNS resolution. The cron-based view implementation has several technical drawbacks:
# Current implementation (simplified)
*/5 * * * * sed -e 's/192.168.0./10.22.0./' -e 's/192.168.1./10.22.1./' \
/var/lib/bind/db.company.local > /var/lib/bind/db.company.local.ext \
&& rndc reload company.local in extView
Instead of maintaining separate zone files, we can implement response rewriting within BIND itself. Here's a more elegant solution using BIND's built-in functionality:
view "internal" {
match-clients { !10.22.0.0/23; localhost; };
zone "company.local" {
type master;
file "/var/lib/bind/db.company.local";
};
};
view "vpn" {
match-clients { 10.22.0.0/23; };
zone "company.local" {
type master;
file "/var/lib/bind/db.company.local";
response-policy {
zone "rpz.company.local";
};
};
};
zone "rpz.company.local" {
type master;
file "/var/lib/bind/db.rpz.company.local";
allow-query { none; };
};
Create a response policy zone (RPZ) file that handles the translation dynamically:
; db.rpz.company.local
$TTL 1H
@ SOA ns1.company.local. hostmaster.company.local. (
2023081501 ; serial
1h ; refresh
15m ; retry
1w ; expiry
1h ; minimum
)
NS ns1.company.local.
; Rewrite rules
192.168.0.0/23 CNAME rewrite.company.local.
rewrite.company.local A 10.22.0.1
; Specific host rewrites
server1.company.local A 10.22.0.50 ; instead of 192.168.0.50
When implementing this solution:
- Enable
rndc trace
to monitor RPZ processing - Consider adding
rpz-passthru
for non-matching queries - Test with
dig +short @localhost server1.company.local
from VPN clients
For BIND 9.16+, you can use the rewrite
statement for more granular control:
view "vpn" {
match-clients { 10.22.0.0/23; };
rewrite {
name prefix "192.168.0." "10.22.0.";
name prefix "192.168.1." "10.22.1.";
};
// ... rest of view configuration
};
Many organizations face IP address conflicts when merging networks, especially when the original internal network uses common private IP ranges like 192.168.0.0/23. In healthcare environments with sensitive equipment, changing these addresses becomes particularly challenging due to:
- Legacy medical devices with hardcoded IPs
- Critical systems that can't tolerate downtime
- Complex network topologies with distributed equipment
The interim solution using 1:1 NAT for VPN clients (mapping 192.168.0.0/23 to 10.22.0.0/23) creates a DNS challenge. While clients can access resources via the translated addresses, DNS continues to return the original internal IPs. The current implementation with cron and sed has several drawbacks:
# Current implementation (flawed due to delay)
sed -e 's/192.168.0./10.22.0./' -e 's/192.168.1./10.22.1./' \
/var/lib/bind/db.company.local > /var/lib/bind/db.company.local.ext \
&& /usr/sbin/rndc reload company.local in extView
The correct approach involves using BIND's view functionality with client IP matching. Here's a complete configuration example:
// named.conf options
options {
directory "/var/named";
version "not currently available";
allow-query { any; };
};
// Internal view for LAN clients
view "internal" {
match-clients { 192.168.0.0/23; localhost; };
recursion yes;
zone "company.local" {
type master;
file "/var/named/db.company.local";
};
};
// External view for VPN clients
view "external" {
match-clients { 10.22.0.0/23; };
recursion yes;
zone "company.local" {
type master;
file "/var/named/db.company.local.vpn";
};
};
For more dynamic translation without maintaining separate zone files, RPZ provides a powerful alternative:
// RPZ configuration in named.conf
options {
response-policy { zone "rpz.company.local"; };
};
zone "rpz.company.local" {
type master;
file "/var/named/db.rpz.company.local";
allow-query { none; };
};
// RPZ zone file content
$TTL 1H
@ IN SOA ns1.company.local. admin.company.local. (
2023060101 ; serial
1h ; refresh
15m ; retry
1w ; expiry
1h ; minimum
)
NS ns1.company.local.
; Rewrite rules for VPN clients
192.168.0.0/23.client-vpn CNAME 10.22.0.0/23
*.company.local.client-vpn CNAME rpz-passthru.
When implementing these solutions, consider:
- View matching occurs before recursive resolution, adding minimal overhead
- RPZ processing happens after resolution but before response
- For large networks, maintain separate zone files to avoid runtime translations
- Monitor query rates with
rndc stats
to detect performance impact
A more maintainable long-term solution involves restructuring your DNS architecture:
// named.conf split-horizon configuration
view "vpn-clients" {
match-clients { 10.22.0.0/23; };
zone "internal.company.local" {
type forward;
forwarders { 192.168.0.53; }; // Internal DNS
};
zone "company.local" {
type master;
file "/var/named/db.company.local.vpn";
};
};