Compile shadowsocks-libev statically
(Update 2021-01-01: this article has been revised to adopt latest ss-libev
)
Previously I’ve discussed how to compile and run an user-mode Linux.
In this post, I’ll talk about how to compile a statically-linked shadowsocks-libev
.
Preparation
Before we do anything, we need to install basic build packages.
Following are common package group you may use:
CentOS/Fedora:
sudo yum groupinstall "Development Tools"
Debian/Ubuntu:
sudo apt-get install build-essential
Arch Linux/Manjaro:
sudo pacman -Sy base-devel
You may happen to install git
, autoconf
, automake
, libtool
, gettext
, asciidoc
, xmlto
manually.
To compile shadowsocks-libev
(ss-libev
for short) statically, its dependencies must be compiled(also static) first.
ss-libev
depends on several packages: mbedTLS
, libsodium
, pcre
, libev
, c-ares
.
And assuming current directory is /tmp/foo
and statically-linked packages will be installed in $SS_DIR
(using --prefix
option in configure
file).
# Replace to yours
SS_DIR=$HOME/ss-libev
mkdir -p "$SS_DIR"
Compile dependencies
mbedTLS
set -euf
VER=$(curl -sL https://api.github.com/repos/ARMmbed/mbedtls/releases/latest | grep '"tag_name":' | cut -d'"' -f4 | tr -d 'v')
wget https://github.com/ARMmbed/mbedtls/archive/v$VER.tar.gz -O mbedtls-$VER.tar.gz
tar xf mbedtls-$VER.tar.gz
pushd mbedtls-$VER
# Install into $SS_DIR
sed -i "s|DESTDIR=/usr/local|DESTDIR=$SS_DIR/mbedtls|" Makefile
CC=gcc AR=ar LD=ld LDFLAGS=-static make -j$(nproc) && make install
# Back to /tmp/foo
popd
libsodium
set -euf
VER=$(curl -sL https://download.libsodium.org/libsodium/releases/ | cut -d'"' -f2 | grep "^libsodium-" | grep "tar\.gz$" | grep "\-stable\." | sort -V | tail -1 | grep -Eo "[0-9]+(\.[0-9]+)+")
wget https://download.libsodium.org/libsodium/releases/libsodium-$VER-stable.tar.gz
tar xf libsodium-$VER-stable.tar.gz
pushd libsodium-stable
./configure --host=$(uname -m)-linux --prefix=$SS_DIR/libsodium --disable-ssp --disable-shared
make -j$(nproc) && make install
popd
pcre
set -euf
VER=$(curl -sL https://ftp.pcre.org/pub/pcre/ | cut -d'"' -f2 | grep "^pcre-" | grep "tar\.gz$" | sort -V | grep -Eo "[0-9]+\.[0-9]+" | tail -1)
wget https://ftp.pcre.org/pub/pcre/pcre-$VER.tar.gz
tar xf pcre-$VER.tar.gz
pushd pcre-$VER
./configure --host=$(uname -m)-linux --prefix=$SS_DIR/pcre --disable-shared --enable-utf8 --enable-unicode-properties
make -j$(nproc) && make install
popd
libev
set -euf
VER=$(curl -sL http://dist.schmorp.de/libev/ | cut -d'"' -f2 | grep "^libev-" | grep "\.tar.gz$" | grep -Eo "[0-9]+\.([0-9]+)+")
wget http://dist.schmorp.de/libev/libev-$VER.tar.gz
tar xf libev-$VER.tar.gz
pushd libev-$VER
./configure --host=$(uname -m)-linux --prefix=$SS_DIR/libev --disable-shared
make -j$(nproc) && make install
popd
c-ares
set -euf
VER=$(curl -sL https://api.github.com/repos/c-ares/c-ares/releases/latest | grep '"name":' | cut -d'"' -f4 | grep -E "^[0-9]+(\.[0-9]+)+$")
URL=$(curl -sL https://api.github.com/repos/c-ares/c-ares/releases/latest | grep browser_download_url | cut -d'"' -f4 | grep "\.tar\.gz$")
wget $URL
tar xf c-ares-$VER.tar.gz
pushd c-ares-$VER
./configure --host=$(uname -m)-linux --prefix=$SS_DIR/c-ares --disable-shared
make -j$(nproc) && make install
popd
Compile shadowsocks-libev statically
You can download latest ss-libev
from GitHub API:
VER=$(curl -sL https://api.github.com/repos/shadowsocks/shadowsocks-libev/releases/latest | grep '"tag_name"' | grep -Eo "[0-9]+(\.[0-9]+)+")
wget https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$VER/shadowsocks-libev-$VER.tar.gz
tar xf shadowsocks-libev-$VER.tar.gz
pushd shadowsocks-libev-$VER
# Run the same commands listed below...
Or simply git clone
it:
# Build upon HEAD, which functionalities may unstable.
git clone --depth 1 https://github.com/shadowsocks/shadowsocks-libev
pushd shadowsocks-libev
git submodule init
git submodule update
./autogen.sh
LIBS="-lpthread -lm" \
LDFLAGS="-Wl,-static -static -static-libgcc" \
./configure --host=$(uname -m)-linux \
--prefix=$SS_DIR/shadowsocks-libev \
--disable-documentation \
--enable-static \
--with-mbedtls=$SS_DIR/mbedtls \
--with-sodium=$SS_DIR/libsodium \
--with-pcre=$SS_DIR/pcre \
--with-ev=$SS_DIR/libev \
--with-cares=$SS_DIR/c-ares
make -j$(nproc) && make install
popd
Compile simple-obfs
simple-obfs
is a simple obfuscating tool(plugin) used in ss-libev
, which also can be statically compiled.
git clone --depth 1 https://github.com/shadowsocks/simple-obfs
pushd simple-obfs
git submodule init
git submodule update
./autogen.sh
LIBS="-lpthread -lm" LDFLAGS="-Wl,-static -static -static-libgcc -L$SS_DIR/libsodium/lib -L$SS_DIR/libudns/lib -L$SS_DIR/libev/lib" CFLAGS="-I$SS_DIR/libsodium/include -I$SS_DIR/libudns/include -I$SS_DIR/libev/include" ./configure --host=$(uname -m)-linux --prefix=$SS_DIR/shadowsocks-libev --disable-ssp --disable-documentation
make -j$(nproc) && make install
popd
After all things done, you should have a copy of statically-linked simple-obfs
and ss-libev
:
[$SS_DIR/shadowsocks-libev/bin]# ls -l
total 19344
-rwxr-xr-x 1 root root 1617280 Aug 2 14:25 obfs-local
-rwxr-xr-x 1 root root 1765240 Aug 2 14:25 obfs-server
-rwxr-xr-x 1 root root 3801592 Aug 2 14:21 ss-local
-rwxr-xr-x 1 root root 1628344 Aug 2 14:21 ss-manager
-rwxr-xr-x 1 root root 5388 Aug 2 14:21 ss-nat
-rwxr-xr-x 1 root root 3737000 Aug 2 14:21 ss-redir
-rwxr-xr-x 1 root root 3965760 Aug 2 14:21 ss-server
-rwxr-xr-x 1 root root 3271912 Aug 2 14:21 ss-tunnel
If you trying detect one of those file, say, ss-local
, it’ll shows:
$ file ss-local
ss-local: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=6584349d54fbf0f9e1c389c57ae1394dcbec2543, not stripped
$ ldd ss-local
not a dynamic executable
Which indicates it’s statically-linked(ss-nat
is an exception, it’s a shell script).
You can take further steps to strip all symbols, or even pack them up, which can decrease file size significantly.
Before you do anything to the final production, remember to back them up.
# Strip out all symbols
[$SS_DIR/shadowsocks-libev/bin]# find . ! -name 'ss-nat' -type f | xargs strip -s
# NOTE: This should be optional, may make them unstable even erroneous.
[$SS_DIR/shadowsocks-libev/bin]# find . ! -name 'ss-nat' -type f | xargs upx -9
# Also remember to test them
[$SS_DIR/shadowsocks-libev/bin]# find . ! -name 'ss-nat' -type f | xargs upx -t
We’re done, you can now use ss-libev
.
FYI, I’ve built ss-libev
successfully under Debian 8 x64, its kernel is 3.16.0-4-amd64
.