Setting up ShadowVPN on Debian

Recently the main developer of ShadowVPN, a fast and secure VPN based on libsodium, used to circumvent internet censorship in China, was forced to remove all code from Github and stop working on such projects by the Chinese police (See here).

I decided to try out ShadowVPN, and I found it to provide better performance than OpenVPN with less RAM and CPU usage.

Here's a quick guide to setup both the ShadowVPN client and server on Debian.

Building ShadowVPN from Source

This process is the same on both the client and the server:

Install dependencies

sudo apt-get update
sudo apt-get install build-essential automake libtool git

Clone the Git Repo

git clone https://github.com/rains31/ShadowVPN.git
cd ShadowVPN
git clone https://github.com/jedisct1/libsodium.git

Build time

./autogen.sh
./configure --enable-static --sysconfdir=/etc
make
sudo make install

ShadowVPN is now installed on the device !

Configuring the server

If you are running a VPS, ensure you have the TUN / TAP interface enabled in your VPS control panel.

Generate the User token and Password

User tokens are hex representations of 8 byte values, you can generate one with the following command:
xxd -l 8 -p /dev/random

A long, random password for encrypting traffic can be generated with the following command:
dd if=/dev/urandom bs=64 count=1 | sha256sum

Keep those two values handy, you will need them for the server and client configuration.

Modify the default server config file

sudo vi /etc/shadowvpn/server.conf

Change server=0.0.0.0 (Line 6) to the IP address of the server if it has a static IP, if not leave it at 0.0.0.0 to listen on all interfaces.

Change # user_token=7e335d67f1dc2c01,ff593b9e6abeb2a5,e3c7b8db40a96105 (Line 14) to user_token=[GENERATED_USER_TOKEN] (Replace [GENERATED_USER_TOKEN] with the User token generated in the previous step.)

Change password=my_password (Line 18) to password=[GENERATED_PASSWORD]

Now save and exit the file with :x

Check the configuration

You can check the configuration file for errors by starting up a server in the console in verbose mode:
sudo shadowvpn -c /etc/shadowvpn/server.conf -v

If you see something along the lines of Sat Aug 22 14:03:32 2015 VPN started, then it's all good, quit the console server with CTRL+C

Start the server daemon

Start the server as a background process with sudo shadowvpn -c /etc/shadowvpn/server.conf -s start

Configuring the client

Modify the default client config file

sudo vi /etc/shadowvpn/client.conf

Change server=0.0.0.0 (Line 6) to the IP address of the server.

Change # user_token=7e335d67f1dc2c01,ff593b9e6abeb2a5,e3c7b8db40a96105 (Line 14) to user_token=[GENERATED_USER_TOKEN] (Replace [GENERATED_USER_TOKEN] with the User token generated in the previous step.)

Change password=my_password (Line 18) to password=[GENERATED_PASSWORD]

Change net=10.7.0.2/24 (Line 36) to net=10.7.0.1/16

Now save and exit the file with :x

Check the configuration

You can check the configuration file for errors by starting up a client in the console in verbose mode:
sudo shadowvpn -c /etc/shadowvpn/client.conf -v

If you get something along the lines of Sat Aug 22 14:03:54 2015 VPN started then you are now connected to the VPN !

Quit the console client by pressing CTRL+C.

Start the client daemon

Start the client as a background process with sudo shadowvpn -c /etc/shadowvpn/client.conf -s start

Now make sure it works by verifying your IP with the following command: wget -qO- http://ipecho.net/plain ; echo

If the returned IP address is that of the server then you're all set up, have fun with your new VPN connection !

Start ShadowVPN on system boot

Create the init script

sudo vi /etc/init.d/shadowvpn

Copy and paste the following script into the file:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          ShadowVPN
# Required-Start:    $remote_fs $syslog $network
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Manages the ShadowVPN daemon
# Description:       Handles start / stop actions of the ShadowVPN daemon
### END INIT INFO

# Author: Liam Jack <cuonic@cuonic.com>
#
# Please remove the "Author" lines above and replace them
# with your own name if you copy and modify this script.

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="ShadowVPN service"
NAME=shadowvpn
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="-c /etc/shadowvpn/server.conf"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

case "$1" in
  start)
    [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
    $DAEMON $DAEMON_ARGS -s start

    if test "$?" -eq 0; then
        [ "$VERBOSE" != no ] && log_daemon_msg "Daemon started successfully" "$NAME"
    else
        [ "$VERBOSE" != no ] && log_daemon_msg "Failed to start daemon" "$NAME"
    fi

    ;;
  stop)
    [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"

    $DAEMON $DAEMON_ARGS -s stop

    if test "$?" -eq 0; then
        [ "$VERBOSE" != no ] && log_daemon_msg "Daemon stopped successfully" "$NAME"
    else
        [ "$VERBOSE" != no ] && log_daemon_msg "Failed to stop daemon" "$NAME"
    fi

    ;;
  status)
    status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
    ;;
  restart)
    log_daemon_msg "Restarting $DESC" "$NAME"

    $DAEMON $DAEMON_ARGS -s restart

    if test "$?" -eq 0; then
                [ "$VERBOSE" != no ] && log_daemon_msg "Daemon restarted successfully" "$NAME"
        else
                [ "$VERBOSE" != no ] && log_daemon_msg "Failed to restart daemon" "$NAME"
        fi

    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop|restart|status}" >&2
    exit 3
    ;;
esac
:

If this is for the client daemon

Modify the line DAEMON_ARGS="-c /etc/shadowvpn/server.conf" to DAEMON_ARGS="-c /etc/shadowvpn/client.conf"

Add to boot

Make the file executable: sudo chmod 755 /etc/init.d/shadowvpn

sudo update-rc.d shadowvpn defaults

Test

sudo service shadowvpn start