Tunneling all traffic over DNS with a SOCKS proxy
This blogpost will be a short tutorial about the right settings and configuration files you need to achieve the setup outlined in the headline: Sending all IP traffic over a SOCKS proxy through a DNS-based tunnel into the internet.
You basically only need three things:
A DNS tunnel with Iodine
I won't dive into the details on how to setup Iodine, because there are already enough good tutorials on that. Basically, Iodine can be used to build an IP tunnel over DNS.
However, my described setup assumes that the private network 192.168.99.0/24
is configured with 192.168.99.1 being on the server side.
Furthermore, I assume that you can succesfully establish a connection to your iodine server and ping it over the tunnel.
With this setup, you do not necessarily need to have IP-forwarding enabled, because the traffic will go through a SOCKS5-proxy.
A SOCKS5 proxy
Back in the past (probably a couple of years ago), I decided to use ssocks as a SOCKS5 proxy. Not sure if that's still a good choice, but it runs fine for me.
Start ssocks with the following arguments to bind it to 192.168.99.1:8080
(don't ask why I used this port...):
/usr/local/bin/ssocksd -b 192.168.99.1 --port 8080
A transparent proxy redirector
Most of the magic happens on the client side with a tool called redsocks. Most linux distributions ship a package for it, but compiling it manually should work as well. The source code is on Github.
After establishing a connection with your DNS tunnel, we will use this tool to transparently redirect all outgoing connections through the SOCKS5 proxy on the server.
But first we need to adjust the configuration file /etc/redsocks.conf
:
base {
log_debug = off;
log_info = off;
log = "syslog:daemon";
daemon = on;
user = redsocks;
group = redsocks;
redirector = iptables;
}
redsocks {
local_ip = 127.0.0.1;
local_port = 31338;
ip = 192.168.99.1; // change here
port = 8080; // change here
type = socks5;
}
redudp {
local_ip = 127.0.0.1;
local_port = 10053;
ip = 192.168.99.1; // change here
port = 8080; // change here
dest_ip = 8.8.8.8;
dest_port = 53;
udp_timeout = 30;
udp_timeout_stream = 180;
}
dnstc {
local_ip = 127.0.0.1;
local_port = 5300;
}
I only changed the fields ip
and port
in the redtcp
and redudp
sections.
You can see that the redirector
setting indicates the use of iptables
. We therefor have to create a special ruleset that will redirect the outgoing traffic into redsocks, which in turn sends the traffic to the SOCKS proxy.
Create a file called /etc/iptables/redsocks.rules
with:
# Transparent SOCKS proxy
# See: http://darkk.net.ru/redsocks/
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:REDSOCKS - [0:0]
# Redirect all output through redsocks
-A OUTPUT -d XXX.XXX.XXX.XXX -j ACCEPT
-A OUTPUT -d 192.168.99.1 -j ACCEPT
-A OUTPUT -p tcp -j REDSOCKS
# Whitelist LANs and some other reserved addresses.
# https://en.wikipedia.org/wiki/Reserved_IP_addresses#Reserved_IPv4_addresses
-A REDSOCKS -d 0.0.0.0/8 -j RETURN
-A REDSOCKS -d 10.0.0.0/8 -j RETURN
-A REDSOCKS -d 127.0.0.0/8 -j RETURN
-A REDSOCKS -d 169.254.0.0/16 -j RETURN
-A REDSOCKS -d 172.16.0.0/12 -j RETURN
#-A REDSOCKS -d 192.168.0.0/16 -j RETURN
-A REDSOCKS -d 224.0.0.0/4 -j RETURN
-A REDSOCKS -d 240.0.0.0/4 -j RETURN
# Redirect everything else to redsocks port
-A REDSOCKS -p tcp -j REDIRECT --to-ports 31338
COMMIT
We have to adjust the example iptables rules a bit:
- Depending on the subnet you use, you have to comment out the matching
-A REDSOCKS -d ... -j RETURN
line. - We have to accept traffic to our socks5 proxy by adding
-A OUTPUT -d 192.168.99.1 -j ACCEPT
before the-A OUTPUT -p tcp -j REDSOCKS
line. - We have to accept traffic to our DNS tunnel server by replacing the
XXX.XXX.XXX.XXX
with the real ip address of the server runningiodined
.
After starting redsocks, e.g. with sudo systemctl start redsocks
, we have to activate the iptables rules with sudo iptables-restore < /etc/iptables/redsocks.rules
.
To test if the setup works correctly, you can run curl ifconfig.me
and hope that it returns the server's IP address.
Troubleshoot: DNS not resolving
In case you have problems resolving DNS queries using this setup, the root cause might be that the nameserver YYY.YYY.YYY.YYY
entry in your /etc/resolv.conf
does not match the dest_ip
address in the redudp
section. Try adjusting either one so that it's the same.
But why?
If you ask why you should use this (or a similar) DNS-tunnel based approach: It can become helpful if you're in a location where WiFi hotspots require a login and/or a payment before giving internet access. Sometimes, DNS queries are not blocked ;-)
-=-