How to Setup Shadowsocks

In this age of ideology and censorship, those of us who are still looking for the truth or at least in want to expose ourselves to lies from another perspective, are able to use a tool called Shadowsocks.

This is a free and open-source protocol widely used in several totalitarian countries to circumbent Internet censorship.

Most mainstream users will probably use a system such as NordVPN to achieve this.

However, Shadowsocks has the advantage of being more focused on traffic obfuscation given that it shows itself as pure HTTPS traffic as well as being more private if you take the DIY route.

The server

In my case I installed it on a VPS running Arch Linux.

After setting up the yay packet manager, I installed shadowsocks-rust from the AUR to have the actively developed implementation of the server. Then I did the same on my client computer.

On the server I used a configuration similar to the following at /etc/shadowsocks-rust/config_rust.json

{
    "server": "my_server_ip_or_domain",
    "server_port": "port_where_shadowsocs_server_listens",
    "password": "A randomly generated and secure password",
    "method": "aes-256-gcm",
    "user" : "A non-root user"
}

Tip: You can generate a pretty strong password with the following one liner in Linux.

tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 64  ; echo

In order to launch the server, it is enough to run:

sudo ssserver -c /etc/shadowsocks-rust/config.json

The port choice for the service will depend on what ports are kept open on the firewall you are trying to evade. Normally, these will be HTTP and HTTPS ports for web related access, which are ports 80 and 443 respectively.

Notice that if your server port is lower than 1024, you will need to run this command as root. However, this is not a secure approach regarding internet-facing services.

There are several solutions for this issue.

The first one is to use a tool such as authbind to bind sockets to priviledged ports without root.

The second one is to tell the shadowsocks server to listen in localhost, then setup an inverse proxy using nginx or iptables which are simpler utilities with a greater degree of trust.

If the machine runs additional services, the second solution might be the most scalable. But right now this is the only service I plan to run on this machine, so wrapping the binary within authbind is the fastest way to get this thing going in a relatively secure manner.

In order for this trick to work, we need to do some preparations first.

Giving access to port 443 the steps would be:

sudo touch /etc/authbind/byport/443
sudo chmod 777 /etc/authbind/byport/443

Then, as the user you want to execute as, run:

authbind --deep ssserver -c /etc/shadowsocks-rust/config.json

You can see that the server is running in usermode by checking the user with this command:

ps -aux | grep shadow

Manage with systemd

We can use systemd order to automatically start the service if the server is restarted, also to stop it and to start it as a daemon from the command line.

Create this file at /etc/systemd/system/shadowsocks-server.service.

Unit]
Description=Shadowsocks Server
After=network.target

[Service]
ExecStart=/usr/bin/authbind --deep /usr/bin/ssserver -c /etc/shadowsocks-rust/config.json
Restart=always
User=nonroot

[Install]
WantedBy=multi-user.target

The enable it and start it via:

sudo systemctl enable /etc/systemd/system/shadowsocks-server.service
sudo systemctl start shadowsocks-server.service

Verify the service is online via:

sudo systemctl status shadowsocks-server.service

The client

I did set the same configuration file on the client with a couple more parameters in order to specify the local port and address of the SOCKS server.

{
    "server": "my_server_ip_or_domain",
    "server_port": "port_where_shadowsocs_server_listens",
    "local_port": "localhost port where the socks5 proxy is set",
    "local_address": "127.0.0.1",
    "password": "A randomly generated and secure password",
    "timeout": 300,
    "method": "aes-256-gcm"
}

Given that the client service is not required to open priviledged ports, you do not need to use authbind and can use ports over 1024 in localhost.

You can use the following command and can convert it into a systemd service as explained in the previous section.

/usr/bin/sslocal -c /etc/shadowsocks-rust/config_rust.json

In order to test that you have been successful, you may go to the proxy settings of your system and set them to the local address and port in your client configuration.

Then you can ask google what is your ip and verify that it is indeed the one of the server, as proof that your HTTP requests are being routed through it.

whoami

Jaime Romero is a software developer and cybersecurity expert operating in Western Europe.