DEV Community

Cover image for Tunneling all your internet connections through a socks proxy
Jorge Alberto Díaz Orozco (Akiel)
Jorge Alberto Díaz Orozco (Akiel)

Posted on • Updated on

Tunneling all your internet connections through a socks proxy

A story

The seed of the problem

Not so many years ago when I used to live in Cuba, the only access to the internet I could use was using a Proxy set by the institution I was working for or the college I studied at. The managers on these networks used to restrict the contents you could access as hard as possible so at work you could not check Facebook or other social media, but that was not the main problem. Since Cuba is embargoed by the United States of America, several important resources like Docker images, Gitlab, and Google resources for coding in Android were all blocked for any Cuban IP. Conclusion: you need to use a VPN if you want anything done.
Not being able to pay for a VPS (no such thing as credit cards in Cuba) I was heavily using Tor, YourFreedom, or even an SSH tunnel if someone borrowed me their access to a VPS, and many other alternatives to circumvent censorship. Most of the time, these connections ended up in being a socks proxy either on my computer or my local trusted network, and I could use them easily from my browser or on several applications using tsocks or proxychains. But the holy grail of this problem was to get all the traffic from your computer to be tunneled only using a socks proxy, and that I could not achieve. Until now :-)

Recent development

What I could not foresee is that after all these years, a friend of mine would also face the same problem. As for today, two great alternatives for this are a good match in my opinion.
First, we have sshuttle and I absolutely love it. It helped me a lot during some time but it has a downside. It only works on top of SSH which is currently blocked by the only Cuban telecommunications company so we could not really use it.
Second, we have Outline and this one is also brilliant. I have read a lot about it because it seems it's heavily used to bypass censorship and all it is is a wrapper around a very nice set of tools. It basically sets a shadowsocks connection and configures your device so it behaves like a VPN. This seemed to be the right way to go, but for some odd reason, it did not want to work properly on my friend's computer.

Why not just using a VPN?

Well, Cuba is not precisely happy about their citizens using tricks to bypass their censorship and control, so they have managed to block protocols like OpenVPN. Every VPN that uses a handshake/header which is easily identifiable can be easily blocked. We could set up some obfuscation on top of the VPNs but this will require our users to also set up something on their side and that's "just fine" for a tech-savvy person, but not for our elders. In most cases, Outline is just perfectly fine because it's very hard to identify or block shadowsocks.

Making it work on a broken Linux

Most people will just re-install their OS and try again, but this time that was not an option. Also, I really wanted to fight this problem again, so, since Outline was the fittest option, I decided to go on and see what they are doing under the hood. They are open source (https://github.com/Jigsaw-Code/outline-client) so this was kind of an easy task.
Sadly, we could not isolate the problem in my friend's computer, but we were able to reproduce what the Outline folks do, and here's a guide to that:

Just tell me how to do it already!

  1. Start a shadowsocks server if you don't have one set already ss-server -p 6276 -k password. The IP address of this server is going to be $server_ip from now on.
  2. Install the shadowsocks-libev package. This will provide you with all the shadowsocks utilities and will set up your local proxy connected to the shadowsocks server.
  3. Install badvpn-tun2socks. This application will tunnel all your data using a Tun network interface in Linux. To install it clone their repository https://github.com/ambrop72/badvpn and follow the compile and install instructions here.
  4. Now, let's create a new tun network interface ip tuntap add dev tun0 mode tun user my_user, add an IP address to it ip a add 10.0.0.1/24 dev tun0, and bring the interface up ip link set dev tun0 up.
  5. Connect to our shadowsocks server ss-local -s $server_ip -p 6276 -k password -l 1080 and give it a try curl --socks5 socks5://localhost:1080 https://myip.wtf/json. If it shows your server IP address it means it's working.
  6. Start badvpn-tun2socks to start tunneling the data sent to tun0 to the socks proxy badvpn-tun2socks --tundev tun0 --netif-ipaddr 10.0.0.2 --netif-netmask 255.255.255.0 --socks-server-addr 127.0.0.1:1080. After this point you should be able to ping the virtual gateway ping 10.0.0.2 with successful results.
  7. Add a network route to guarantee your socks proxy is still going to connect using your default gateway ip r a $server_ip via $default_gateway
  8. Add a default route with a metric lower than the one provided by NetworkManager for your default gateway ip r a default via 10.0.0.2 metric 10 And this is it. After this point, all the connections on your Linux machine are routed to the tun0 interface and therefore to the socks proxy. Do a quick curl https://myip.wtf/json to check that you are in the location where your shadowsocks server is and enjoy another cup of coffee.

Final words

No, you probably won't need any of this if Outline works for you, but for me, it was very satisfying to finally beat this problem and to help my friend. We could not find why Outline was not working for him, but we managed to reproduce almost exactly what Outline does and had fun in the process.
Did you enjoy reading? Leave a <3 for me on this post and share it with your nerdy friends :-)

Oldest comments (4)

Collapse
 
mfat profile image
Mehdi mFat

Thanks for this. It seems that shadowsocks-rust has built-in TUN support.

Collapse
 
alllexx88 profile image
alllexx88

shadowsocks-rust has built-in TUN support

It does, but I couldn't get both IPv4 AND IPv6 tunneling to work at the same time, without badvpn, with shadowsocks-rust alone.

Collapse
 
mohammad258852 profile image
Mohammad Aghaie

thanks for this article. it worked for me
but how can i disable it?

Collapse
 
alllexx88 profile image
alllexx88 • Edited

Thanks for sharing. Based on this I created simple scripts to switch on and off socket traffic forwarding, and also added IPv6. I thought I'd share this in response, so here goes. The prerequisites are shadowsocks-rust and badvpn-git (the stable release 1.999.130 from 2015 does not support --socks5-udp).

UPD: add UDP support.

First, I use two systemd template services:
/usr/lib/systemd/system/shadowsocks-rust@.service (on Arch linux it comes with shadowsocks-rust package):

[Unit]
Description=Shadowsocks-Rust Client Service
After=network.target
Wants=network-online.target

[Service]
Type=simple
DynamicUser=yes
NoNewPrivileges=yes
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_ADMIN
ExecStart=/usr/bin/ssservice local --log-without-time -c /etc/shadowsocks-rust/%i.json

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

And a minimalistic service for badvpn-tun2socks, /etc/systemd/system/tun2socks@.service:

[Unit]
Description=A tun2socks template

[Service]
Environment="ARGS=%I"
ExecStart=/bin/bash -c "badvpn-tun2socks $ARGS"
Enter fullscreen mode Exit fullscreen mode

Then we also need /etc/shadowsocks-rust/shadowsocket-client.json (feel in with your info):

{
 "remarks": "Ssserver",
 "server": "<server ip>",
 "server_port": <port>,
 "local_port": 1080,
 "method": "<method, the most commonly used one is chacha20-ietf-poly1305>",
 "mode":"tcp_and_udp",
 "password": "<pass>"
}
Enter fullscreen mode Exit fullscreen mode

Finally on/off scripts.

The on script:

#!/bin/sh

[ $(id -u) -ne 0 ] && echo "Must be root to run this script" >&2 && exit 1

systemctl start shadowsocks-rust@shadowsocket-client
ip link set dev stun0 down 2>/dev/null
ip tuntap del dev stun0 mode tun 2>/dev/null
ip tuntap add dev stun0 mode tun
# badvpn-tun2socks --tundev stun0 --netif-ipaddr 10.0.0.2 --netif-netmask 24 --netif-ip6addr fc00:192:168:117::2 --socks-server-addr 127.0.0.1:1080 --socks5-udp
systemctl start $(systemd-escape --template tun2socks@.service -- "--tundev stun0 --netif-ipaddr 10.0.0.2 --netif-netmask 24 --netif-ip6addr fc00:192:168:117::2 --socks-server-addr 127.0.0.1:1080 --socks5-udp")
ip a add 10.0.0.1/24 dev stun0
ip a add fc00:192:168:117::1/64 dev stun0
ip link set dev stun0 up
ip r a 10.0.0.2 dev stun0
ip r a fc00:192:168:117::2 dev stun0

ip r a default via 10.0.0.2 metric 10
ip r a default via fc00:192:168:117::2 metric 10
Enter fullscreen mode Exit fullscreen mode

The off script:

#!/bin/sh

[ $(id -u) -ne 0 ] && echo "Must be root to run this script" >&2 && exit 1

ip r d default via 10.0.0.2 metric 10
ip r d default via fc00:192:168:117::2 metric 10
# badvpn-tun2socks --tundev stun0 --netif-ipaddr 10.0.0.2 --netif-netmask 24 --netif-ip6addr fc00:192:168:117::2 --socks-server-addr 127.0.0.1:1080 --socks5-udp
systemctl stop $(systemd-escape --template tun2socks@.service -- "--tundev stun0 --netif-ipaddr 10.0.0.2 --netif-netmask 24 --netif-ip6addr fc00:192:168:117::2 --socks-server-addr 127.0.0.1:1080 --socks5-udp")
systemctl stop shadowsocks-rust@shadowsocket-client
ip link set dev stun0 down
ip tuntap del dev stun0 mode tun
Enter fullscreen mode Exit fullscreen mode