Local port forwarding using shadowsocks-rust + openvpn over shadowsocks
Tags: openvpn, shadowsocks, portforwardng, tutorial
Published: 2023-09-08 22:58:16

## 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](https://github.com/shadowsocks/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
```

and extract the files:

```
mkdir shadowsocks
tar xvf shadowsocks-v1.16.1.x86_64-unknown-linux-gnu.tar.xz -C shadowsocks
```

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
```
Verify installation using this command:

```
sslocal --version

```
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
```


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
}
```
**(Please note simple-obfs is obsolete and you should consider using a more secure pluging such as xray.)
**

```
sudo systemctl restart shadowsocks-libev.service

```


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

```
nano sstunnel.json

```
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"

}
```
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
```
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
```
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

```
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
....
```
The rest of the configuration file remains intact.

Now I can connect to openvpn using this command:

```
sudo openvpn --config client.ovpn

```

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://...."
```

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"
```