Free internet
You might sometimes find yourself behind a captive portal, or your SIM card plan may run out of data. Although an internet connection is not viable in such cases, you can still access the internet using a technique called DNS Tunneling.
DNS tunnels are perfectly legal, though a bit slow, and, like a VPS, they provide a good way to protect yourself from malicious attackers.
Iodine is a well-known, efficient, and open-source software that allows you to tunnel IPv4 data through a DNS server. With just one server running Iodine and a network connection, you can connect to the internet, although the speed is typically very poor in most cases.
Installing Iodine is beyond the scope of this guide, but you can find numerous guides on Google detailing how to install and run Iodine.
If you are happy with Iodine's speed, you don't need this guide, although it will be almost impossible to download large files or watch YouTube videos with a single tunnel.
In this guide, we will learn how to merge multiple connections and tunnels into a single, optimized internet connection. This guide is not for the faint-hearted.
Premise:
We are using a Linux system.
Prerequisites:
- A VPS or Server with Iodine installed ( requires a domain name pointing to your VPS/server ).
- Multiple active network connections, such as Wi-Fi and mobile data (SIM card), USB tethering and the like. Each connection does not require internet access but must be able to perform DNS queries. You can test this using commands like
nslookup
ordig
. - haproxy
- iproute2
- net-tools
- socat
Install each package:
root@root:~$ apt install haproxy iproute2 net-tools socat
Part One: Testing
First, connect to the Wi-Fi, or another available network. Use nslookup
or dig
to test your DNS connection. If you get a reply, you're on track!
root@root:~$ nslookup 1.1.1.1
1.1.1.1.in-addr.arpa name = one.one.one.one.
Authoritative answers can be found from:
root@root:~$ nslookup google.com
Server: 194.168.4.100
Address: 194.168.4.100#53
Non-authoritative answer:
Name: google.com
Address: 216.58.201.110
Name: google.com
Address: 2a00:1450:4009:823::200e
I recommend testing Iodine as well. If it connects successfully, simply disconnect it for now.
root@root:~# sudo iodine -f -P YOUR_PASSWORD t1.yourdomain.com
Opened dns0
Opened IPv4 UDP socket
Sending DNS queries for t1.yourdomain.com to 194.168.4.100
Autodetecting DNS query type (use -T to override).
Using DNS type NULL queries
Version ok, both using protocol v 0x00000502. You are user #1
Setting IP of dns0 to 10.0.1.3
Setting MTU of dns0 to 1130
Server tunnel IP is 10.0.1.1
Testing raw UDP data to the server (skip with -r)
Server is at 77.69.9.15, trying raw login: OK
Sending raw traffic directly to 77.69.9.15
Connection setup complete, transmitting data.
Part Two: Connecting
Now that we have proven that our Iodine DNS tunnel works, let's identify our interfaces:
root@root:~# ip route list
default via 192.168.108.147 dev usb0 proto dhcp src 192.168.108.234 metric 213
default via 192.168.0.1 dev wlp0s20f3 proto dhcp src 192.168.0.56 metric 303
169.254.0.0/16 dev wlp0s20f3 scope link metric 1000
192.168.0.0/24 dev wlp0s20f3 proto dhcp scope link src 192.168.0.56 metric 303
192.168.108.0/24 dev usb0 proto dhcp scope link src 192.168.108.234 metric 213
The above means that i can use usb0
and wlp0s20f3
, a USB-Tethering connection and a Wi-Fi connection respectively.
To ease things up, we will take advantage of Linux Network Namespaces.
Let's create two new namespaces. For the sake of simplicity, we will name them WifiConnection and UsbConnection:
root@root:~# ip netns add "WifiConnection"
root@root:~# ip netns add "UsbConnection"
Now let's assign an interface to each namespace:
root@root:~# ip link set wlp0s20f3 netns "WifiConnection"
root@root:~# ip link set usb0 netns "UsbConnection"
Bring the interfaces up:
root@root:~# ip netns exec WifiConnection ip link set wlp0s20f3 up
root@root:~# ip netns exec UsbConnection ip link set usb0 up
Assign an IP to each interface:
root@root:~# ip netns exec WifiConnection dhclient wlp0s20f3
root@root:~# ip netns exec UsbConnection dhclient usb0
Bring the loopback interfaces up
root@root:~# ip netns exec WifiConnection ip link set lo up
root@root:~# ip netns exec UsbConnection ip link set lo up
Now run Iodine:
root@root:~# ip netns exec WifiConnection iodine -f -P YOUR_PASSWORD 8.8.8.8 t1.yourdomain.com
root@root:~# ip netns exec UsbConnection iodine -f -P YOUR_PASSWORD 1.1.1.1 t1.yourdomain.com
Next, open the socks5 tunnels. The ports 2240 & 2340 are random; i just like the numbers.
( you can view the IP of the remote server by looking at the output of Iodine, specifically "Server tunnel IP is 10.0.1.1" )
root@root:~# ip netns exec WifiConnection ssh srv@10.0.1.1 -D 2240
root@root:~# ip netns exec UsbConnection ssh srv@10.0.1.1 -D 2340
Now use socat
to listen to UsbConnection and WifiConnection:
root@root:~# socat tcp-listen:2241,fork,reuseaddr exec:'ip netns exec WifiConnection /usr/sbin/sshd -i',nofork
root@root:~# socat tcp-listen:2242,fork,reuseaddr exec:'ip netns exec UsbConnection /usr/sbin/sshd -i',nofork
We can now forward the DNS tunnels:
ssh root@0.0.0.0 -p 2241 -L 2240:127.0.0.1:2240
ssh root@0.0.0.0 -p 2242 -L 2340:127.0.0.1:2340
Amazing, we now have two socks5 connections acting as DNS tunnels: one on 127.0.0.1:2240
and another one on 127.0.0.1:2340
All that's left to do is set up a load balancer between the two connections. Keep in mind that you can use as many connections as you want!
For example, you could create a third connection by plugging one of these USB Wi-Fi adapters.
Enough with the chit-chat. Edit haproxy config file haproxy.cfg, usually /etc/haproxy/haproxy.cfg, and make sure that the default mode is set to tcp and not http.
Also, add the following lines to your HAProxy config file:
frontend socks5-in
bind *:1080
default_backend socks5-out
backend socks5-out
balance roundrobin
server proxy1 127.0.0.1:2240 check
server proxy2 127.0.0.1:2340 check
The configurations above will create a new socks5 connection on port 1080.
You can now use 127.0.0.1:1080 as socks5 proxy, distributing traffic evenly between the tunnels.
So, that's it. Next time you can't pay your internet bill, don't panic—just follow this guide and get back online in no time!
Sidenotes:
- If you use Cloudflare, the NS record must be unproxied.
- Check your Server's firewall and make sure Port 53 can accept UDP packets.
Top comments (0)