Skip to content
/ utdnsd Public

A DNS forwarder serving requests from UDP transport by delegating them to upstream DNS servers with TCP.

Notifications You must be signed in to change notification settings

yousong/utdnsd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

utdnsd, a DNS forwarder serving requests from UDP clients by delegating them to upstream DNS servers with TCP. The idea is from ttdnsd of Tor Project.

OpenWrt package definition files can be found at waller repository; detailed instructions of how to import them should be included there.

Build

libubox from OpenWrt project is required. On Mac OS X with MacPorts installed, you can get libubox installed by using portfiles from macports-openwrt repository.

To build it locally (of course, CMake is required here).

cmake . && make

To configure the build (mainly the DEBUG option).

ccmake .

Or you can use build-scripts

Run.

When run without arguments, help text will be printed to stderr.

Usage: utdnsd [ -qrh ] -l <host[:port]> [ -s <host[:port]> ... ] [ -t <seconds> ]
  -l <host[:port]>  Address and port to listen to.
  -s <host[:port]>  Upstream DNS server we ask for service through TCP transport.
  -t <seconds>      Maximum delay for reconnect attempts (defaults to 5s).
  -T <seconds>      Maximum delay before the link was considered shoddy (defaults to 5s).
  -r                Reconnect on tcp connection hup.
  -q                Be quiet.
  -h                This output.

Currently, at most 8 -s <host:[port]> can be specified on the command line. Same upstream server can be specified multiple times with the -s option.

Example run.

yousong@yousongs-MacBook-Air:~/dev/utdnsd(master)$ ./utdnsd -l 127.0.0.1:8053 -s 202.130.97.66 -s 202.180.160.1 -s 203.91.143.19 -s 202.130.97.65 -s 202.174.131.19 -s 202.181.224.2 -s 202.45.84.58 -s 202.84.255.1 
info: connect to 202.130.97.66:53 succeeded.
info: connect to 202.180.160.1:53 succeeded.
info: connect to 203.91.143.19:53 succeeded.
info: connect to 202.130.97.65:53 succeeded.
info: connect to 202.174.131.19:53 succeeded.
info: connect to 202.181.224.2:53 succeeded.
info: connect to 202.45.84.58:53 succeeded.
info: connect to 202.84.255.1:53 succeeded.
info: start serving!
== SIGUSR1 received, statistics follows
>   202.130.97.66:53   state:1 reconn:0   served:42    staging:0   estimate:0  wbuf:0   rbuf:0   sent:1470     recv:13356   
>   202.180.160.1:53   state:1 reconn:0   served:9     staging:0   estimate:0  wbuf:0   rbuf:0   sent:315      recv:2367    
>   203.91.143.19:53   state:1 reconn:0   served:9     staging:0   estimate:0  wbuf:0   rbuf:0   sent:315      recv:2367    
>   202.130.97.65:53   state:1 reconn:0   served:42    staging:0   estimate:0  wbuf:0   rbuf:0   sent:1470     recv:11046   
>  202.174.131.19:53   state:1 reconn:0   served:11    staging:0   estimate:0  wbuf:0   rbuf:0   sent:385      recv:3018    
>   202.181.224.2:53   state:1 reconn:0   served:35    staging:0   estimate:0  wbuf:0   rbuf:0   sent:1225     recv:9205    
>    202.45.84.58:53   state:1 reconn:0   served:28    staging:0   estimate:0  wbuf:0   rbuf:0   sent:980      recv:7364    
>    202.84.255.1:53   state:1 reconn:0   served:19    staging:0   estimate:0  wbuf:0   rbuf:0   sent:665      recv:6061    
=================== statistics ends

As you can see from the above output, sending SIGUSR1 to utdnsd will cause it to print some statistics.

Quirks

Below are some different strategies or situations I came across while doing testing against a varieties of public DNS servers.

  • Only 1 query per TCP connection. Disconnect at the end of that transaction.

      114.114.114.114
    
  • Only 1 connection per IP (this is a guess), other connections may hang or delay with ACK, ACK, ...

Tips

If you have got a long list of usable DNS servers and in a decidophobia as to which ones to use. Then some randomness can help.

server_list='hk.txt.1'

total="$(wc -l "$server_list" | awk '{ print $1; }')"
[ "$total" -gt "8" ] && {
	total="$(( $total - 8 ))"
	pos="$(( $RANDOM % $total ))"
	servers="$(sed -n "$pos,$(($pos+7))p" "$server_list")"
} || {
	servers="$(cat "$server_list")"
}

sopts=""
for s in $servers; do
		sopts="$sopts -s $s"
done
./utdnsd -l 127.0.0.1:8053 $sopts

Test it with dig, nslookup.

# use +short for returning only IP adresses.
dig +noshort -p 8053 @127.0.0.1 www.openvpn.net
nslookup www.openvpn.net 127.0.0.1 -port=8053
nslookup www.openvpn.net 127.0.0.1:8053

TODO

  • A list of domain names from browser history for testing purposes.

Resources

About

A DNS forwarder serving requests from UDP transport by delegating them to upstream DNS servers with TCP.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published