Simple Tcp Vpn Over Ssh Socks

Simple Tcp Vpn Over Ssh Socks

Github Project:

Poor-man’s VPN for TCP traffic over SSH dynamic socks tunnel, uses Linux/iptables

Taken some TCP tunneling code from Christophe Devine, and turned it into a transparent socks proxy. This serves as a lightweight / poor-man’s VPN connection, to combine firewalled networks into one. Requirements; use linux on your end, and you need to be able to connect to an SSH server on the network you want to reach. And the local and remote network IP-ranges should NOT overlap 😉 Note: this proxy ONLY works with TCP packets, not with UDP. So your DNS server won’t work accross it.

Created somewhere between 2002 and 2014. Feel free to use and modify to suit your needs. Thijs Kaper, 3 feb 2018.

Compile using gcc (c-compiler):

gcc myproxy.c -o myproxyCode language: CSS (css)

Use linux iptables to send traffic for certain network ranges to this proxy code. You can choose to send specific ranges to the proxy, and leave the rest of your traffic default:

# send single IP to the proxy
sudo iptables -t nat -A OUTPUT -p tcp -d -j DNAT --to-destination

# send IP range 172.30.*.* to the proxy
sudo iptables -t nat -A OUTPUT -p tcp -d -j DNAT --to-destination language: PHP (php)

Or you can send ALL traffic, except some ranges to the proxy like this: Note: make sure you add an exclude line for the ip address to which you are tunneling 😉 Or better; make sure your complete local network is excluded (DNS+gateway will be on there).

# Exclude ranges (10.*, localhost, and virtualbox 192.168.3.*, tunnel-host):
sudo iptables -t nat -A OUTPUT -p tcp -d -j ACCEPT
sudo iptables -t nat -A OUTPUT -p tcp -d -j ACCEPT
sudo iptables -t nat -A OUTPUT -p tcp -d -j ACCEPT
sudo iptables -t nat -A OUTPUT -p tcp -d <TUNNELHOSTIP> -j ACCEPT

# default other traffic to proxy:
sudo iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination

# start SSH socks tunnel to your tunnelhost:
ssh -fN -D6020 youruser@TUNNELHOSTIP

# start tunnel software (port 6021 listens for iptables traffic, and 6020 is ssh socks tunnel):
myproxy 6021 6020Code language: PHP (php)

Note: before you start messing with iptables, you could make a backup of your current rules using:

sudo iptables-save >iptables-backup.rulesCode language: CSS (css)

This can be restored using:

sudo iptales-restore <iptables-backup.rulesCode language: CSS (css)

Or if you want to clear all rules (not recommended when you are using iptables rules, for example when running docker locally, or when using some sort of firewall package):

sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t nat -L

Knowledge about networking, ssh-keys, and c-programming helps a lot in understanding this tunnel 😉

If you are in the unlucky situation where local and remote networks overlap, you can try just using single IP numbers in the connect and forwards, or… you can modify this C-code to change the network range just before sending the data on. For example, if both local and remote use 10.0.*.*, you can translate a virtual address of 192.168.*.* to the remote’s 10.0.*.*, and then forward all 192.168.*.* using this proxy. Of course any DNS entries won’t work anymore, so you should add entries to your /etc/hosts file in that case.

DISCLAIMER: I have not tried writing beautiful code 😉 It’s just a hacked together M.V.P. (Minimal Viable Product). It works quite nicely, but possibly can be improved much. I do use it in this form quite regularly (many years already), and have not seen the need for more functionality/fixes yet.

You might also want to take a look at SSHUTTLE it’s sort of similar, but is more developed, and has more features. It can be started quite simple, for example like this:

# tunnel ALL traffic using sshuttle (just change the into a smaller range if needed):
sshuttle -r youruser@TUNNELHOSTIP -vCode language: PHP (php)

It handles setting up your iptables rules for you.


Leave a Reply

Your email address will not be published. Required fields are marked *