DEV Community

Cover image for Local port forwarding using shadowsocks-rust + openvpn over shadowsocks
Mehdi mFat
Mehdi mFat

Posted on

Local port forwarding using shadowsocks-rust + openvpn over shadowsocks

How to forward local port using shadowsocks

The purpose here is to forward local port 3080 to remote port 2.2.2.2:1194 (where an openvpn server is listening) using shadowsocks.

To do this we'll use shadowsocks-rust:

First we download the latest binaries for linux:

wget https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.16.1/shadowsocks-v1.16.1.x86_64-unknown-linux-gnu.tar.xz
Enter fullscreen mode Exit fullscreen mode

and extract the files:

mkdir shadowsocks
tar xvf shadowsocks-v1.16.1.x86_64-unknown-linux-gnu.tar.xz -C shadowsocks
Enter fullscreen mode Exit fullscreen mode

Now we cd into the folder and make the binaries executable and move them to /usr/local/bin:

cd shadowsocks/
chmod +x ss*
sudo mv ss* /usr/local/bin
Enter fullscreen mode Exit fullscreen mode

Verify installation using this command:

sslocal --version

Enter fullscreen mode Exit fullscreen mode

Now we are ready to create our local tunnel.

To do this we obviously need a shadowsocks server. There are many tutorials for setting up one. However here is how you can quickly set up a shadowsocks server on a debian/ubuntu VPS:

sudo apt install shadowsocks-libev simple-obfs

sudo nano /etc/shadowsocks-libev/config.json
Enter fullscreen mode Exit fullscreen mode

with the following content:

{
   "server": "0.0.0.0",
   "server_port": DESIRED PORT,
   "password": "DESIRED PASSWORD",
   "timeout": 300,
   "method": "chacha20-ietf-poly1305",
   "mode": "tcp_only",
   "dns":"1.1.1.1",
   "plugin":"obfs-server",
   "plugin_opts": "obfs=http;obfs-host=cloudfront.net",
   "fast_open": false
}
Enter fullscreen mode Exit fullscreen mode

*(Please note simple-obfs is obsolete and you should consider using a more secure pluging such as xray.)
*

sudo systemctl restart shadowsocks-libev.service

Enter fullscreen mode Exit fullscreen mode

Now back to our local system, we create a shadowsocks tunnel configuration file:

nano sstunnel.json

Enter fullscreen mode Exit fullscreen mode

and paste these lines. Make necessary adjustments based on your shadowsocks server configuration:

{
"locals": [
{
            "protocol": "tunnel",

            "local_address": "127.0.0.1",
            "local_port": 3080,
            "forward_address":"2.2.2.2",
            "forward_port": 1194,

}
],
            "server": "SHADOWSOCKS_SERVER_IP",
            "server_port": SHADOWSOCKS_SERVER_PORT,
            "password": "SHADOWSOCKS_SERVER_PASSWORD",
            "method": "chacha20-ietf-poly1305",
            "mode": "tcp_only",
            "plugin": "obfs-local",
            "plugin_opts": "obfs=http;obfs-host=cloudfront.net"

}
Enter fullscreen mode Exit fullscreen mode

This file tells shadowsocks to forward connections to 127.0.0.1:3080 to the remote port 2.2.2.2:1194 which is our openvpn server, for example.

Now we can run the tunnel:

/usr/local/bin/sslocal -c sstunnel.json
Enter fullscreen mode Exit fullscreen mode

This is the output on my system:

$ /usr/local/bin/sslocal -c sstest.json 
2023-09-09T02:08:53.356339957+03:30 INFO  shadowsocks local 1.16.1 build 2023-09-01T05:08:00.031376835+00:00
 2023-09-09 02:08:53 [simple-obfs] INFO: obfuscating enabled
 2023-09-09 02:08:53 [simple-obfs] INFO: obfuscation http method: GET
 2023-09-09 02:08:53 [simple-obfs] INFO: obfuscating hostname: cloudfront.net
 2023-09-09 02:08:53 [simple-obfs] INFO: tcp port reuse enabled
 2023-09-09 02:08:53 [simple-obfs] INFO: listening at 127.0.0.1:41681
2023-09-09T02:08:53.357713632+03:30 INFO  shadowsocks TCP tunnel listening on 127.0.0.1:3080
Enter fullscreen mode Exit fullscreen mode

As you can see the last line
TCP tunnel listening on 127.0.0.1:3080
shows sslocal is listening at port 3080.

How to connect to openvpn over shadowsocks

Now let's assume we have an client.ovpn file for connecting to our 2.2.2.2:1194 openvpn server.

We open the client.ovpn file and make two changes:

  1. We change remote line to 127.0.0.1 3080
  2. We also tell openvpn to route the shadowsocks server IP through default gateway, not through the vpn tunnel:
route SHADOWSOCKS_SERVER_IP 255.255.255.255 net_gateway

Enter fullscreen mode Exit fullscreen mode

This is how my openvpn client configuration looks now:

client
proto tcp-client
remote 127.0.0.1 3080
route SHADOWSOCKS_SERVER_IP 255.255.255.255 net_gateway
....
Enter fullscreen mode Exit fullscreen mode

The rest of the configuration file remains intact.

Now I can connect to openvpn using this command:

sudo openvpn --config client.ovpn

Enter fullscreen mode Exit fullscreen mode

P.S: instead of creating a shadowsocks tunnel configuration file we can also use the following command:

sslocal --protocol tunnel -b "127.0.0.1:3080" -f "2.2.2.2:1194"  --server-url "ss://...."
Enter fullscreen mode Exit fullscreen mode

or

/usr/local/bin/sslocal --protocol tunnel -b "127.0.0.1:3080" -f "2.2.2.2:1194" -s "SHADOWSOCKS_SERVER_IP:PORT" -m "chacha20-ietf-poly1305" -k "SHADOWSOCKS_SERVER_PASSWORD" --plugin "obfs-local" --plugin-opts "obfs=http;obfs-host=cloudfront.net"
Enter fullscreen mode Exit fullscreen mode

Top comments (0)