DNS Tunnelling

I got DNSTunelling to work. It’s a PoC code now, but it works. I managed to get ppp up and send a few packets and even SSH to the other computer! The more I think about it, the more I am convinced that the choices I made were not the bad ones.

  1. The use of PPP instead of TUN/TAP – makes the application more language independent (no need for ioctls, fnctls), supports compression, authentication, etc.
  2. The use of dnsjava package – maybe not the fastest one but the code is nice, understandable, doesn’t segfault and the whole thing is only 400 lines of code.
  3. The use of DNS structures – CNAME, instead of IP – it is standard and allows to transmit quite a few data in the CNAME record

How it works: Query – sending the DNSencoded name query – <querydata>.DOMAIN Reply – two records: <querydata>.DOMAIN => CNAME <replydata>.DOMAIN, and <replydata>.DOMAIN => A <some IP address>

Currenty we’re not using the information in the IP address, but we can. We also set quite a small TTL (1 second), so that the server doesn’t cache the requests and we don’t have to add random numbers to randomize them.

HACK: if both query and reply are zero-length, the DNS server crashes on “CNAME points to itself” => the reply has “r” addedd in front of it. We need to make a proper solution.

Running programs

  • java -cp .:dnsjava-1.6.4.jar DNSTunnelClient [ipaddress[:port]]
  • java -cp .:dnsjava-1.6.4.jar DNSTUnnelServer

ignoring the debug information, our DNS tunnel works like a real tunnel – stdin on one side appears on stdout on the other side.

Now the BIG TRICK – running the real tunnel with ppp:

  • pppd noauth debug nodetach passive? 10.0.0.1:10.0.0.2 pty “java -cp .:dnsjava-1.6.4.jar DNSTUnnelServer”
  • pppd noauth debug nodetach pty “java -cp .:dnsjava-1.6.4.jar DNSTunnelClient [ipaddress[:port]]”

Note that both the server has to be run as root (to be able to open port 53) and to run pppd with option noauth. Client has also run as root.

If you are worried about security, there is a workaround.

  1. Configure /etc/ppp/options and /etc/ppp/*-secrets to allow client-server authentication
  2. Add users running the scripts to the group dip (Debian)
  3. Run the DNS server on some high port (>1024)
  4. Add an iptables redirect rule (iptables -t nat -I PREROUTING -p udp –destination-port 53 -j REDIRECT –to-ports 53)

ifconfig <- look for ppp0 ping 10.0.0.2 ping 10.0.0.1

VOILA!

TODOs:

  • adaptive polling depending on traffic
  • discarding stdin data when no requests (server)???
  • randomizing packets – copunters
  • error handling!
  • runtime parameters
  • testing the real setup
  • javadoc, packaging, readme, manual

Leave a Reply