How to Deploy a Censorship Resistant Shadowsocks-libev Server

Authors: Anonymous

Last update: Monday, December 6, 2021

中文版: 如何部署一台抗封锁的Shadowsocks-libev服务器

This tutorial documents how to install, configure and maintain a Shadowsocks-libev server. One cool thing about this tutorial is, by following this tutorial, your Shadowsocks-libev servers should be able to defend against various attacks, including active probing from the GFW and the partitioning oracle attack. Additionally, we compile a list of commonly asked questions, debunking common myths of Shadowsocks-libev. As of November 7, 2021, we received a few reports on the blocking of Shadowsocks ports. We thus share a way to setup backup ports to mitigate the inconvenience caused by port blocking.

Please consider bookmark this page because we commit to make this tutorial up-to-date and provide latest best practices to defend against emerging attacks. This tutorial is intended to be friendly to non-technical users. If you get lost at any step of this tutorial, please let us know and we will improve the documentation.


Install Snap

Snap is the officially recommended way to install Shadowsocks-libev.

  • If your server is running Ubuntu 16.04 LTS or later, Snap is already installed.
  • If your server is running some other Linux distributions, simply follow the corresponding installation instructions.

Now double check you have both snapd and Snap core installed:

sudo snap install core

Install Shadowsocks-libev

Now we install the latest Shadowsocks-libev from the edge channel:

sudo snap install shadowsocks-libev --edge


Below is the recommended configuration for Shadowsocks-libev server:


You need to replace the password ExamplePassword with a much stronger one. A strong password is recommended to mitigate the latest Partitioning Oracle Attacks against Shadowsocks servers. A handy way to generate a strong password from your terminal is: openssl rand -base64 16.

You may also want to change the server_port from 8388 to a different value between 1024 and 65535.

Now, open the default configuration file:

sudo nano /var/snap/shadowsocks-libev/common/etc/shadowsocks-libev/config.json

After copying and pasting your settings to the file, type Ctrl + x to exit. The text editor will ask "Save modified buffer?", and you can type y and then hit Enter.

The default configuration file path is too long to remember, and it is not well documented elsewhere yet. We thus encourage you to bookmark this page so that you can go back to check it whenever you want.


We use ufw to open ports for the Shadowsocks server.

To install ufw on a Debian-based server:

sudo apt update && sudo apt install -y ufw

Then open ports for ssh and Shadowsocks-libev. Note that if you set the server_port to a value different than 8388 in /var/snap/shadowsocks-libev/common/etc/shadowsocks-libev/config.json, you need to change the value 8388 below accordingly:

sudo ufw allow ssh
sudo ufw allow 8388

Now enable ufw:

sudo ufw enable

If it prompts Command may disrupt existing ssh connections. Proceed with operation (y|n)?, type y and hit Enter.

Finally, run sudo ufw status, and the output should look like this:

Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
8388                       ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
8388 (v6)                  ALLOW       Anywhere (v6)

Run Shadowsocks-libev

Now you can start the Shadowsocks-libev:

sudo systemctl start

Remember to let Shadowsocks-libev auto-start after a server reboot:

sudo systemctl enable


Check status and log

To check the status of the service:

sudo systemctl status

If you see Active: active (running) in green, your Shadowsocks-libev server is running properly; if you see Active: failed in red, jump to the end of journalctl -u to see what is wrong.

Reload configuration file

Whenever you change the configuration file, remember to restart Shadowsocks-libev to load the latest settings:

sudo systemctl restart

Mitigate port blocking by having backup ports

As of November 7, 2021, we received a few reports on the blocking of Shadowsocks ports.

In particular, since the GFW has been reportedly doing port blocking, rather than IP blocking, having a few backup ports may mitigate the incovenience when port blocking happens.

A user can run the following command on server to redirect both TCP and UDP traffic ranging from port 12000 to 12010, to port 8388:

sudo iptables -t nat -A PREROUTING -p tcp --dport 12000:12010 -j REDIRECT --to-port 8388
sudo iptables -t nat -A PREROUTING -p udp --dport 12000:12010 -j REDIRECT --to-port 8388

Remember to:

  1. replace 12000:12010 with a different range that only you know (we suggest any port from 1024 to 65535);
  2. replace 8388 with the Shadowsocks port you used.

This way, whenever a port on server got blocked, a user only needs to change the configurations of server_port on the clients, without having to login to the server, change configuration, and then restart Shadowsocks. For example, if you had been using port 12000 but it got blocked, all you need to do is changing the server_port from 12000 to another backup port 12001 on your client.

When properly configured, the output should look like this:

sudo iptables -t nat -L PREROUTING -nv --line-number
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 REDIRECT   tcp  --  *      *              tcp dpts:12000:12010 redir ports 8388
2        0     0 REDIRECT   udp  --  *      *              udp dpts:12000:12010 redir ports 8388

Note that setting a PREROUTING rule on ephermeral ports (/proc/sys/net/ipv4/ip_local_port_range) will not disrupt normal outgoing connections that use those ephermeral ports as source ports.


Q: Why did my server still get blocked when I followed your tutorial?

A: As of November 7 2021, we indeed received a few report on the blocking of Shadowsocks. Since this tutorial can defend all known active probing attacks by the GFW, it is likely that the censor has employed some unknown attacks against Shadowsocks-libev. If your server got blocked, too, please consider using the backup ports to mitigate the blocking. We also encourage you report the block to us and we will carefully investigate it.

Q: Should I install Shadowsocks-libev from a distribution repo?

A: A distribution repo may not always include the latest version of Shadowsocks-libev. For example, as of January 2021, the version included in Debian buster repo was v3.2.5, which was not sufficient to defend active probings from the GFW (see Figure 10).

Q: How can I update Shadowsocks-libev via snap?

A: Usually you don’t have to update it manually because snap automatically updates all apps once per day. To manually update immediately: sudo snap refresh.

Q: Why do you use chacha20-ietf-poly1305?

A: Because it is one of the AEAD ciphers, which can defend the active probings by the GFW. It is also the default encryption method for both Shadowsocks-libev and OutlineVPN.

Q: Should I use any stream cipher in Shadowsocks?

A: No. It is unacceptably insecure. Even the latest version of Shadowsocks-libev operating in stream cipher mode is vulnerable to active probing (see Figure 10). More devastatingly, an attacker can get full decryption of recorded Shadowsocks sessions, without knowing the password.

Q: But my “airport” is still using stream cipher?

A: Then it is clear sign that your “airport” has very poor security awareness. Point the owners to this tutorial, as well as this post and this summary.

Q: Should I change the server_port to some common ports like 443?

A: No. The GFW can still suspect your Shadowsocks traffic, regardless of the server port you use.

Q: Why do you operate Shadowsocks-libev in tcp_and_udp mode?

A: Previously, we used tcp_only mode to mitigate the Partitioning Oracle Attacks against Shadowsocks servers; however, as Vinicius pointed out, the partitioning oracle attack is not feasible when you have long random passwords, and it is recommended to “enable UDP support in order to enjoy better video calls”.

Q: Why do you disable fast_open?

A: We recommend that you read this rationale.


This report appeared first on GFW Report.

We encourage you to share your comments publicly or privately. Our private contact information can be found at the footer of GFW Report.