DNS Override for a Single Process
I needed to run a mobile emulator on my laptop, in order to test some DNS server changes before releasing them.
However, since the emulator had no option to override its DNS settings it used my laptop’s DNS settings, so to make it query a different server I had to modify my laptop’s settings.
This meant that I broke a lot of other programs running on my laptop, so for example I couldn’t edit the DNS server and test the emulator at the same time. Very frustrating.
I made a script that’s using
LD_PRELOAD to monkey-patch
fopen and return a custom version of
It basically works like this:
- Create a new
resolv.conffile and store it in an environment variable
- Append my shared library to
LD_PRELOADto make my
fopenhide the standard one
execto the binary you want to run
- When the binary calls
fopen, our function is called. If the requested file is not
/etc/resolv.conf, we pass everything to the original function. If it is, we open a pointer to the modified file instead
The code is available under dns-override
nitz@mars:~$ nslookup google.com Server: 127.0.1.1 Address: 127.0.1.1#53 Non-authoritative answer: Name: google.com Address: 126.96.36.199 nitz@mars:~$
nitz@mars:~$ ~/projects/dns-override/dns-override.sh -s 188.8.131.52 nslookup google.com Server: 184.108.40.206 Address: 220.127.116.11#53 Non-authoritative answer: Name: google.com Address: 18.104.22.168 nitz@mars:~$
- Took me a while to figure out there are
- I’m opening read streams for
/etc/resolv.conf, even when write streams are required. Could produce some weird behaviour
- My original goal was passing something like
DNS_SERVERS=22.214.171.124to the library, but it was much easier generating the entire
resolv.conffile in a shell script.
- I’m only targeting
resolv. However, that should cover all of my use cases so I’m happy.