how to tunnel dns to use a public server

if one’s public name server only performs recursive lookups for local hosts, one can tunnel dns requests to the server so that requests appear to be local. for the the examples that follow, the public name server is ns1.example.com. there are two examples, the first is insecure, and highly deprecated. the second uses ssh to establish a secure connection, and is the recommended method.

method 1- simple but insecure

WARNING! this method allows recursive queries to anyone who finds it!

  • Server side: + socat udp4-listen:53535,reuseaddr,fork UDP:localhost:53

  • Client side: + socat udp4-listen:53,reuseaddr,fork udp:ns1.example.com:53535

note that the port, 53535, is purely arbitrary. choose a port above 1024 if the tunnel is to be created by an unprivileged user.

method 2- slightly more complex, but secure

on client do:

launch socat to pass connections to tcp/53 on to udp/53535:

socat udp4-listen:53,reuseaddr,fork tcp:localhost:53535 &

create a ssh tunnel to the nameserver:

ssh -L 53535:localhost:53535 ns1.example.com

=== on the server, ns1.example.com,  do:

might want to verify that the tunnel isn't already up:
case uname in Linux) netstat -tuna ;; _BSD|Darwin) netstat -nafinet

esac | grep 53535

run socat to forward tcp/53535 to udp/53:

socat tcp4-listen:53535,reuseaddr,fork UDP:localhost:53