Tech 5 min read

ShadowSocks server setup notes, with 2025 updates

IkesanContents

I used to build ShadowSocks servers when I was running a China-facing service. I found my old notes, so I am putting them here together with the current state of things.

What ShadowSocks is

ShadowSocks is a SOCKS5 proxy developed in 2012 by the Chinese programmer “clowwindy”. It is mainly used to bypass China’s internet censorship, the GFW (Great Firewall).

People often call it “ShadowSocks VPN” or “China VPN”, but strictly speaking it is a proxy, not a VPN. I know, I know, but “VPN” is the word that gets the point across faster.

Compared with a VPN:

  • VPN: routes all traffic through an encrypted tunnel
  • ShadowSocks: can proxy only selected apps or browsers, so it is lightweight and fast

From around 2019, ShadowSocks detection and blocking became serious in China, and successors such as V2Ray and Trojan have also appeared.

Server setup

These steps are for CentOS 7. I used a ConoHa VPS back then.

Install

Use teddysun’s install script:

wget --no-check-certificate -O shadowsocks.sh https://raw.githubusercontent.com/teddysun/shadowsocks_install/master/shadowsocks.sh
chmod +x shadowsocks.sh
./shadowsocks.sh 2>&1 | tee shadowsocks.log

The installer will ask for a password, port, and encryption method.

Service management

# Start
/etc/init.d/shadowsocks start

# Stop
/etc/init.d/shadowsocks stop

# Restart
/etc/init.d/shadowsocks restart

# Status
/etc/init.d/shadowsocks status

Firewall

ConoHa disabled SELinux and iptables by default. If firewalld is enabled, stop it.

systemctl stop firewalld
systemctl disable firewalld

Or just open the port used by ShadowSocks:

firewall-cmd --permanent --add-port=8388/tcp
firewall-cmd --permanent --add-port=8388/udp
firewall-cmd --reload

DNS

To avoid name-resolution problems, add Google Public DNS:

vi /etc/resolv.conf

Add:

nameserver 8.8.8.8
nameserver 8.8.4.4

File descriptor limits

To raise concurrent connections:

vi /etc/security/limits.conf

Add:

root soft nofile 51200
root hard nofile 51200

Kernel tuning

vi /etc/sysctl.conf

Add:

# max open files
fs.file-max = 51200

# max read buffer
net.core.rmem_max = 67108864

# max write buffer
net.core.wmem_max = 67108864

# max processor input queue
net.core.netdev_max_backlog = 250000

# max backlog
net.core.somaxconn = 4096

# resist SYN flood attacks
net.ipv4.tcp_syncookies = 1

# reuse timewait sockets when safe
net.ipv4.tcp_tw_reuse = 0

# turn off fast timewait sockets recycling
net.ipv4.tcp_tw_recycle = 0

# short FIN timeout
net.ipv4.tcp_fin_timeout = 30

# short keepalive time
net.ipv4.tcp_keepalive_time = 1200

# outbound port range
net.ipv4.ip_local_port_range = 10000 65000

# max SYN backlog
net.ipv4.tcp_max_syn_backlog = 8192

# max timewait sockets held by system simultaneously
net.ipv4.tcp_max_tw_buckets = 5000

# TCP Fast Open
net.ipv4.tcp_fastopen = 3

# TCP memory
net.ipv4.tcp_mem = 25600 51200 102400

# TCP receive buffer
net.ipv4.tcp_rmem = 4096 87380 67108864

# TCP write buffer
net.ipv4.tcp_wmem = 4096 65536 67108864

# turn on path MTU discovery
net.ipv4.tcp_mtu_probing = 1

# TCP congestion control
net.ipv4.tcp_congestion_control = hybla

Apply the settings:

sysctl -p

Check logs

less -n /var/log/shadowsocks.log

Configuration file

The ShadowSocks config lives at /etc/shadowsocks.json.

{
    "server": "0.0.0.0",
    "server_port": 8388,
    "password": "your_password",
    "method": "aes-256-gcm",
    "timeout": 300
}

If you want separate passwords per user, edit /etc/shadowsocks.json like this:

{
    "server": "0.0.0.0",
    "port_password": {
        "8388": "user1_password",
        "8389": "user2_password",
        "8390": "user3_password"
    },
    "method": "aes-256-gcm",
    "timeout": 300
}

Using different ports makes it easier to track who is using which connection.

Encryption method

In the past, aes-256-cfb and chacha20 were common. Today I would recommend:

  • AES-256-GCM: good balance of security and speed for servers
  • ChaCha20-IETF-Poly1305: power-efficient for mobile devices and ARM CPUs

Avoid these older ciphers:

  • RC4-based ciphers (rc4-md5, etc.)
  • DES-based ciphers
  • CFB mode (aes-256-cfb, etc.) because of weak security

Kernel tuning improvements

The sysctl.conf settings above were fine at the time, but if I were doing it now I would change a few things.

Enable tcp_tw_reuse

# original
net.ipv4.tcp_tw_reuse = 0

# recommended
net.ipv4.tcp_tw_reuse = 1

This allows reuse of TIME_WAIT sockets. 0 still works, but 1 is more efficient. Keep tcp_tw_recycle set to 0 - the official wiki warns not to enable it.

Switch congestion control to BBR

# original
net.ipv4.tcp_congestion_control = hybla

# recommended (Linux 4.9+)
net.ipv4.tcp_congestion_control = bbr

hybla was a reasonable choice for very high-latency links such as satellite connections, and it was not unreasonable for China-Japan traffic either. But today Google’s BBR performs better. It is available on Linux 4.9 and later.

Notes

  • Since 2019, China has used DPI (Deep Packet Inspection) to detect ShadowSocks
  • The server IP itself may get blocked
  • It is worth considering harder-to-detect protocols such as V2Ray, Trojan, or Xray

Successors

ShadowSocks led to protocols that focus more on bypassing censorship:

  • V2Ray / Xray: support multiple protocols and can disguise traffic as HTTPS with WebSocket or gRPC
  • Trojan: designed to fully imitate HTTPS traffic

They are more complex to configure, but they are useful in heavily restricted environments.

-> Continue with: V2Ray (WebSocket+TLS) server setup notes

-> Summary: Comparison of VPN protocols for China-facing connectivity


I am not publishing this because of tensions between Japan and China. Absolutely not.

References