Prerequisites:
Lazy QA/Staging
In the staging of production systems it is often desirable to override DNS to point at a local staging server instead of the production one. For example, you may have a large number of scripts that call "www.xyz.com"; changing all of these to "wwwtest.xyz.com" would be a pain in the ass.
Sure, there are good ways around this if you have a decent QA environment. You can use a special QA network with its own DNS server. To some extent you can use rule-based proxies.
A large number of solutions involve editing your local hosts file (/etc/hosts under UNIX, \system32\drivers\etc\hosts on Windows) to override DNS.
This works due to a file named /etc/nsswitch.conf. This very useful file contains the rules that programs use to resolve host names and other directory services (sendmail aliases, autofs, etc).
Basically, when a program wants to connect to "www.xyz.com" it makes a call to gethostbyname(), which consults /etc/nsswitch.conf.
A common /etc/nsswitch.conf might contain the following line:
Listing 1:
This tells gethostbyname() to consult local files first (ie., /etc/hosts). If it can't find what it's looking for there it will consult DNS.
NOTE: Not all programs respect /etc/resolv.conf. For example, the "nslookup", "dig" and "host" commands will return DNS information regardless of what is in /etc/hosts.
Usually this works fine. You'll resolve
www.xyz.com normally with the entry commented out in /etc/hosts and resolve it to the staging IP with the entry present.
The problem comes in when you want certain users to use DNS, and certain users to use the overrides in /etc/hosts.
Per-user DNS overrides
The important thing to remember about configuration files in /etc (/etc/hosts, /etc/nsswitch.conf, etc.) is that they are considered system-level confs. That is, they apply to all users. gethostbyname() doesn't care which user called it--it just blindly returns results based on the system-level rules in /etc.
The trick to making this work is understanding how /etc/nsswitch.conf works. Let's take a closer look at our above example, which specifies the search order as "files dns". This means it consults /etc/hosts first, and only if it fails or doesn't find an entry will it try DNS.
The key is, "if it fails."
It's highly unlikely /etc/hosts will ever fail--it's just a flat file. It
is possible for DNS to fail, however. In fact, since this requires network access,
we can make it fail.
Our goal is for some users to resolve
www.xyz.com publicly, while forcing other users to hit staging. We can do this by providing public information via DNS and the staging IPs via /etc/hosts.
Change /etc/nsswitch.conf to consult DNS first, only falling back on /etc/hosts if that fails:
Listing 2:
Now any entry we put into /etc/hosts for "www.xyz.com" will be ignored unless the DNS server fails to respond. The next step is to force DNS to fail for certain users.
Let's say user jdoe has a uid of 503. We want Joe to hit staging. using the "-m owner" feature of iptables we can block him from hitting udp/tcp port 53 (DNS).
Listing 3:
/sbin/iptables -A OUTPUT -p tcp --dport 53 -m owner --uid-owner 503 -j REJECT
/sbin/iptables -A OUTPUT -p udp --dport 53 -m owner --uid-owner 503 -j REJECT |
User jdoe will now be unable to make DNS requests since udp/tcp port 53 outgoing is blocked. gethostbyname() will fail and thus fall back to /etc/hosts due to the options in /etc/nsswitch.conf. We can similarly add iptables rules for any user we want to hit staging.
You may need to restart your nscd service depending on how it's configured. nscd is a caching daemon that runs by default on some systems (Solaris, SuSE, etc.). More information can be found below:
http://linuxmanpages.com/man8/nscd.8.php
There is one problem with this method--
all hosts must be in /etc/hosts. If jdoe gets bored of QAing and wants to visit slashdot.org, he can't do so unless this is in /etc/hosts or he removes the iptables rule.
Packet filtering with iptables is very powerful and robust. To learn more about it visit the two links provided above in the prerequisites section, as it is a must-have utility for any Linux professional.