Setting up a Shadowsocks Server on Linux

If you’ve found this post, you probably don’t need me to tell you what Shadowsocks is or what it is for. You can read all about shadowsocks or shadowsocks-libev here.

Before we get started, make sure you have a Linux server running. I’m using a Vultr LA server. Linode is great too.

Basic Setup

Install shadowsocks-libev

First, clone the shadowsocks-libev repo:


git clone [email protected]:shadowsocks/shadowsocks-libev.git

Then, install the dependencies depending on your Linux flavor:


# Installation of basic build dependencies
## Debian / Ubuntu
sudo apt-get install --no-install-recommends gettext build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libmbedtls-dev libsodium-dev
## CentOS / Fedora / RHEL
sudo yum install gettext gcc autoconf libtool automake make asciidoc xmlto c-ares-devel libev-devel
## Arch
sudo pacman -S gettext gcc autoconf libtool automake make asciidoc xmlto c-ares libev

Finally, install shadowsocks-libev:


# Installation of libsodium
export LIBSODIUM_VER=1.0.16
wget https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VER.tar.gz
tar xvf libsodium-$LIBSODIUM_VER.tar.gz
pushd libsodium-$LIBSODIUM_VER
./configure --prefix=/usr && make
sudo make install
popd
sudo ldconfig
# Installation of MbedTLS
export MBEDTLS_VER=2.6.0
wget https://tls.mbed.org/download/mbedtls-$MBEDTLS_VER-gpl.tgz
tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz
pushd mbedtls-$MBEDTLS_VER
make SHARED=1 CFLAGS="-O2 -fPIC"
sudo make DESTDIR=/usr install
popd
sudo ldconfig
# Start building
git submodule init && git submodule update
./autogen.sh && ./configure && make
sudo make install

Option 2: with Snap

Snap is shipped with most modern OS, so it you are on Debian 9+, CenOS 7.6+, Ubuntu 16.04 LTS or later, just run


sudo snap install shadowsocks-libev

If you’re on older software, follow https://snapcraft.io/core to install snap core first, then run the above.

Configurations


sudo vim /etc/shadowsocks-libev/config.json
# For Debian:
sudo vim /etc/default/shadowsocks-libev


{
"server": ["[::0]", "0.0.0.0"], # alternatively, use your actual ipv6, ipv4 addresses
"server_port": "<YOUR CUSTOM PORT>",
"mode": "tcp_and_udp",
"password": "<YOUR STRONG PASSWORD>",
"timeout": 300,
"method": "aes-256-gcm"
}

Advanced Setups

TCP BBR

BBR (Bottleneck Bandwidth and Round-trip propagation Time) is latest and greatest from Google for TCP congestion control.

To put it simply, it’s the magic dust for juicing every last drop of your server network Google made open-source. Sweet, right?

Hey Linode users! Right now would be a good time to go and upgrade your kernel before moving on with the rest of the tutorial. Check out the last section of this post for how to do that.

Make sure you are root and run the following:


wget --no-check-certificate https://github.com/teddysun/across/raw/master/bbr.sh
chmod +x bbr.sh
./bbr.sh

When you’re done, reboot the server.

Then, check if we’re all set:


sysctl net.ipv4.tcp_available_congestion_control | grep -q 'bbr' && echo '1 Yes'; sysctl net.ipv4.tcp_congestion_control | grep -q 'bbr' && echo '2 Yes'; sysctl net.core.default_qdisc | grep -q 'fq' && echo '3 Yes'; lsmod | grep bbr | grep -q 'tcp_bbr' && echo '4 Yes'

If you don’t see four yes’s, run the following


echo "net.core.default_qdisc = fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control = bbr" >> /etc/sysctl.conf

simple-obfs


git clone https://github.com/shadowsocks/simple-obfs.git
cd simple-obfs
git submodule update --init --recursive
./autogen.sh && ./configure && make
sudo make install

Create a systemd service


sudo vim /etc/systemd/system/shadowsocks-libev.service


[Unit]
Description=Shadowsocks-libev Default Server Service
Documentation=man:shadowsocks-libev(8)
After=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
DynamicUser=true
LimitNOFILE=32768
ExecStart=/usr/local/bin/ss-server -c /etc/shadowsocks-libev/config.json
Restart=always
RestartSec=1
# ExecStart=/usr/bin/ss-server -c $CONFFILE $DAEMON_ARGS
[Install]
WantedBy=multi-user.target


systemctl daemon-reload
systemctl start shadowsocks-libev
systemctl enable shadowsocks-libev

Cron Job for Periodic Restarts

This is optional. It won’t make nearly as much of a different to speed as BBR would, but setting up a cron job that restarts the server every now and then may just prevent it from getting sluggish.

First, create a shell script. I usually put it under /root/restart-ss.sh.


date
systemctl restart shadowsocks-libev
systemctl status shadowsocks-libev

After that, let’s set up the cron job.


crontab -e

Append as the last line:


0 0 * * * bash /root/restart-ss.sh >> /root/ss-libev-cron.log

Perfect. Let’s restart the cron service and we’re good to go.


service cron restart

Multiple Users

If you want to have multiple users, use the following template for your config.json.


{
"server": ["[::0]", "0.0.0.0"],
"local_address": "127.0.0.1",
"local_port": 1080,
"port_password": {
"<port-1>": "<port-1-password>",
"<port-2>": "<port-2-password>"
},
"timeout": 300,
"method": "aes-256-gcm",
"fast_open": true
}

Other

Upgrading your Linux kernel (For Linode Users)

First, check your kernel information with:


uname -r

If it returns anything 4.9 and above, you are good to go. But for this instance 4.11+ actually works slightly better with BBR, so I’m still going to show you how kernel upgrade is done with Linode.

Install the Latest kernel

Go to http://kernel.ubuntu.com/~kernel-ppa/mainline/ to locate the latest linux image. Hint: look for the one that has linux-image and generic in it.

  1. Download the latest kernel:

wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.11.5/linux-image-4.11.5-041105-generic_4.11.5-041105.201706141137_amd64.deb

  1. Install kernel:

dpkg -i linux-image-4.11.5*.deb

  1. Checking if installation is complete:

ls /boot/vmlinuz*

Incidentally, I didn’t purge the old kernel for safety concerns…

Configure GRUB

If you don’t have GRUB installed yet:


apt-get install linux-image-virtual grub2

  1. Edit /etc/default/grub and change the parameters to the following:

GRUB_TIMEOUT = 10
GRUB_CMDLINE_LINUX =“console = ttyS0,19200n8”
GRUB_DISABLE_LINUX_UUID = true
GRUB_SERIAL_COMMAND =“serial --speed = 19200 --unit = 0 --word = 8 --parity = no --stop = 1”
GRUB_TERMINAL = serial

Keep everything else as it is.

  1. Update GRUB

update-grub

  1. Under the “Boot Settings” of your linode, change kernel to “Grub 2”

  2. Reboot your Linode


reboot