Can BIND alter a response based on requesting IP address?
Hello Serverfault,
I work for a hospital who set up their network using 192.168.0.0/23 (before I arrived). We are wanting to have laptops and mobile clients connect from remote locations using VPN, but the hospital network clashes very hard with most home routers. I have pressured the management to give us time to change it, but being a hospital with servers/equipment/etc all over the place this has been impossible to arrange. So we 'fixed' the issue by using a 1:1 nat of 10.22.0.0/23.
The issue: Clients can connect and access resources using the 10.22.0.0/23 IPs without issues, but if they query the DNS server they receive 192.168.0.0/23 responses. Is there a correct way in BIND to translate these on the fly to 10.22.0.0/23 addresses if the query originates from the VPN subnet? Emphasis on correct, as I have it working via BIND views using the following in cron:
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
This works great, but is delayed by 15 to 20 minutes due to BIND journal taking approximately 15 minutes to write back to the db.company.local file.
I have read a bit on RPZ, but the information seems spotty. Can anyone point me in the right direction? If not, can you make my solution more elegant?
EDIT: I'd just like to make it clear I am already using BIND views, but I am doing it with two zones. I am generating my second zone off the first, sending it through sed to change the IPs, and performing an rndc reload on that zone in that view. This has a large delay, is there a way to use the same zone file across both views, and alter the DNS response at query time?
Thanks!
Solution 1:
This should be a process problem. Normally admins would add new records into the zone files of both views. Force them to use scripts if their memory is bad. Discipline them if they refuse to use the scripts. But if it's a madhouse and you just need this to work, I think you might be able to do this with view based response policies.
Let's say you have records that look like this:
$ORIGIN db.company.local.net.
test1 IN A 10.22.0.1
test2 IN A 10.22.1.255
In the view options for your 192space view, define the following response policy:
options {
response-policy { zone "192remap.rpz"; };
}
zone "192remap.rpz" {
type master;
file "192remap.rpz.zone";
};
The response policy will be used to rewrite all 10space IPs to 192space. This is like any other zone file, but the NS records are meaningless and the records have special meanings. Since writing out every single IP address remap by hand would be a chore, we'll use $GENERATE
blocks to populate the zone file for you.
@ IN SOA localhost. root.localhost. (
2 ; serial
3H ; refresh
1H ; retry
1W ; expiry
1H) ; minimum
IN NS localhost.
; 32.$.0.22.10.rpz-ip. -> 10.22.0.$/32
$GENERATE 0 255 32.$.0.22.10.rpz-ip. A 192.168.0.$
$GENERATE 0 255 32.$.1.22.10.rpz-ip. A 192.168.1.$
This will not only remap any of these 10.22.0.0/23 IPs found in the ANSWER section of a DNS response, but also catch any sneaky IPs that show up in the AUTHORITY or ADDITIONAL sections for whatever reason. A request for test1.db.company.local.net.
(10.22.0.1) should have its reply rewritten to 192.168.0.1, and only for the clients hitting your 192space view.
Hope this helps, and let us know if it works. You can find more information about RPZ and links to the documentation in another answer I wrote a few months back.
Solution 2:
yes you can do this with bind views:
http://www.zytrax.com/books/dns/ch7/view.html
basically, you define each view as a subnet, and then each view maintains its own zone file. depending on the source ip/subnet of the dns query, you will get a different "view".
this is common for name servers to use in an "internal"/"external" views, so as dns names resolve publicly on external view, but resolve "internal" to the private ip of the host on internal lan, when queried from the internal private lan(s).