Physical setupThe main computer is runs Ubuntu Linux and has two 100MBit ethernet interfaces, eth0 and eht1. eth0 is connected to the laptop, eth1 is connected to the router. Laptop runs Windows XP, and is connected to the main computer. The router is overfirewalled in a particularly fascist way and is beyond my control. This was the reason why I did the whole hack thing. Somewhere on the Internet there are HTTP Tunnel servers. Everyone can connect to them using encrypted connections to port 80, for greater anonymity or simply to get around stupid firewalls.
Layer 1The first layer of the setup was just a normal network. Router gives the main computer IP through DHCP. Desktop-laptop connection is statically set up, I may change it to use DHCP later, but it's more convienient to leave it static during frequent reconfiguration time. Desktop is NATing laptop, and is getting NATed by router, nothing unusual:
ifconfig eth0 192.168.1.1 echo 1 >/proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -j MASQUERADE -o eth1
Layer 2Now let's get to the funny things. The unfortunate thing is that HTTP Tunnel client runs only on Windows. If it wasn't for that, there would be no need to have a setup as elaborate as this. So I installed HTTP Tunnel on the laptop. It provides SOCKS4/5 server on 192.168.1.2:1080. Now it is possible to anonymously use the Internet from either the laptop or the desktop, at least from the apps that support SOCKS4/5. However, configuring SOCKS4/5 in every single app isn't very convenient, so...
Layer 3And now the fun part. I configured iptables so that it lets connection on the local network and to whitelisted ports through without:
And to forward all other connections to transocks server:
/sbin/iptables -t nat -A OUTPUT -o lo -j RETURN /sbin/iptables -t nat -A OUTPUT -d 127.0.0.1 -j RETURN /sbin/iptables -t nat -A OUTPUT -d 192.168.0.0/16 -j RETURN /sbin/iptables -t nat -A OUTPUT -p tcp --dport 22 -j RETURN # SSH /sbin/iptables -t nat -A OUTPUT -p tcp --dport 80 -j RETURN # HTTP /sbin/iptables -t nat -A OUTPUT -p tcp --dport 443 -j RETURN # HTTPS /sbin/iptables -t nat -A OUTPUT -p udp --dport 53 -j RETURN # DNS
So connections to slashdot.org:80 goes straight, while connections to irc.freenode.net:6667 get redirected to 127.0.0.1:1211. This is almost the right thing, however you can probably see a little problem here - how the heck does transocks know where the user wanted to get connected. That's the best part. Kernel remembers the original destination and we can get to it using:
/sbin/iptables -t nat -A OUTPUT -p tcp --syn -j DNAT --to-destination 127.0.0.1:1211
Now transocks connects to the specified SOCKS4/5 server (configuration in /etc/socks.conf), and the server connects to the right website through a tunnel.
getsockopt(clientfd, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr *)&dstaddr, &dstlen);
In the endSo the complete path the connection goes through is:
- An application on desktop tries to connect to irc.freenode.net:6667
- iptables redirect connection to transocks desktop:1211
- transocks on desktop reads the original destination using getsockopt
- transocks connects to SOCKS4/5 server (HTTP tunnel client) on laptop - 192.168.1.1:1080
- HTTP Tunnel client on laptop tries to connect to HTTP Tunnel servers
- desktop NATs the connection and lets it through
- router NATs the connection again and lets it through
- HTTP Tunnel server connects to irc.freenode.net:6667, wow :-D