OpenVPN with Xor Patch

statue-of-liberty

OpenVPN is easily blocked. The Xor patch provides a modification that may allow OpenVPN to work in restrictive environmemts. It was originally developed by Clayface. The Tunnelblick project then split it into five components. In this article, we build OpenVPN with the Xor obfuscation patch.

The example given here makes these assumptions:

  • The server runs Ubuntu Linux version 18.04
  • The client runs Ubuntu Linux version 18.04
  • The server public IP address is 34.34.34.34, which you will need to change to correspond to your actual server public IP address
  • We communicate between client and server via `udp` on port `443`, which you may need to change, depending on what restrictions apply on your network

Prepare Server

To prepare the server to run OpenVPN with the Xor patch, we will allow packet forwarding, disable IPv6, open the firewall, and masquerade the source IP address of outgoing packets.

Start by making sure your server is up to date:

sudo apt-get update
sudo apt-get upgrade

Edit the system configuration file:

sudo vi /etc/sysctl.conf

Uncomment the line:

net.ipv4.ip_forward=1

Add at the bottom of the file the lines:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

Write the file to disk, and quit the editor. Make these changes effective:

sudo sysctl -p

Open your firewall for udp traffic on port `443` (in our example). This will require adding a rule to your Security Group in a cloud environment, or adding a rule to your iptables rules if that is what you are using as a firewall.

Masquerade the source IP address of outgoing packets:

sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE
sudo apt-get install iptables-persistent

Build OpenVPN with Xor Patch on Server

Download the OpenVPN 2.4.6 source code:

mkdir ~/Downloads

cd ~/Downloads

wget http://swupdate.openvpn.org/community/releases/openvpn-2.4.6.tar.gz

tar xvf openvpn-2.4.6.tar.gz

Get the Tunnelblick versions of the Xor patch files:

wget https://github.com/Tunnelblick/Tunnelblick/archive/master.zip

sudo apt-get install unzip

unzip master.zip

Copy the patch files into the OpenVPN directory:

cp Tunnelblick-master/third_party/sources/openvpn/openvpn-2.4.6/patches/*.diff openvpn-2.4.6

Apply the patches:

cd openvpn-2.4.6

patch -p1 < 02-tunnelblick-openvpn_xorpatch-a.diff

patch -p1 < 03-tunnelblick-openvpn_xorpatch-b.diff

patch -p1 < 04-tunnelblick-openvpn_xorpatch-c.diff

patch -p1 < 05-tunnelblick-openvpn_xorpatch-d.diff

patch -p1 < 06-tunnelblick-openvpn_xorpatch-e.diff

Install the prerequisites for the build:

sudo apt-get install build-essential libssl-dev iproute2 liblz4-dev liblzo2-dev libpam0g-dev libpkcs11-helper1-dev libsystemd-dev resolvconf pkg-config

Build, make, and install OpenVPN with Xor patch:

./configure --enable-systemd --enable-async-push --enable-iproute2

make

sudo make install

sudo mkdir /etc/openvpn

sudo mkdir /etc/openvpn/server

sudo mkdir /etc/openvpn/client

Install Easy RSA Version 3

cd ~/Downloads

wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz

tar -xvzf EasyRSA-nix-3.0.5.tgz

sudo mkdir -p /usr/share/easy-rsa/3

sudo cp -rf EasyRSA-3.0.5/* /usr/share/easy-rsa/3

cd /usr/share/easy-rsa/3

sudo cp vars.example vars

Edit the variables file:

sudo vi vars

Enter variables of your choosing, e.g.:

set_var EASYRSA_DN "org"

set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE "Guangdong"
set_var EASYRSA_REQ_CITY "Shenzhen"
set_var EASYRSA_REQ_ORG "Test Org"
set_var EASYRSA_REQ_EMAIL "test@example.com"

Write the file to disk, and quit the editor.

Create Certificates and Keys

These steps are easiest done as root. If you do not know
the root password, set it now:

sudo passwd root

Switch to root:

su -
cd /usr/share/easy-rsa/3

Create the public key infrastructure (PKI):

./easyrsa init-pki

./easyrsa build-ca nopass

./easyrsa gen-req 34.34.34.34 nopass

./easyrsa sign-req server 34.34.34.34

yes

./easyrsa gen-req adminpc nopass

./easyrsa sign-req client adminpc

yes

./easyrsa gen-dh

Copy the certificates and keys into the OpenVPN directories:

cp pki/ca.crt /etc/openvpn

cp pki/dh.pem /etc/openvpn/server

cp pki/issued/34.34.34.34.crt /etc/openvpn/server

cp pki/issued/adminpc.crt /etc/openvpn/client

cp pki/private/ca.key /etc/openvpn

cp pki/private/34.34.34.34.key /etc/openvpn/server

cp pki/private/adminpc.key /etc/openvpn/client

Generate TLS crypt key:

cd /etc/openvpn

openvpn --genkey --secret tls-crypt.key

In preparation for download to the client, make the client files readable by a non-root user:

chmod +r ca.crt

chmod +r client/adminpc.crt

chmod +r client/adminpc.key

chmod +r tls-crypt.key

Exit root session:

exit

Create OpenVPN Server Configuration File

Change into the OpenVPN server directory:

cd /etc/openvpn

Generate a password for Xor obfuscation:

openssl rand -base64 24

The result will be a 24-byte (192-bit) string, expressed in base 64 notation,
which will come to 32 printable characters. The sample which we will use from now on in this example looks like this:

DPeQw3SvyIMdJqckjznYVLVUSG4p4KIQ

Create the OpenVPN configuration file for the server:

sudo vi server/34.34.34.34.conf

Configure OpenVPN to listen on udp port 443. Make sure to add scramble parameters.

port 443
proto udp
dev tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server/34.34.34.34.crt
key /etc/openvpn/server/34.34.34.34.key
dh /etc/openvpn/server/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 1.1.1.1"
push "dhcp-option DNS 1.0.0.1"
keepalive 10 120
cipher AES-256-GCM
tls-crypt /etc/openvpn/tls-crypt.key
persist-key
persist-tun
status openvpn-status.log
verb 3
scramble obfuscate DPeQw3SvyIMdJqckjznYVLVUSG4p4KIQ

Write the file to disk, and quit the editor.

Set Up Systemd

sudo cp ~/Downloads/openvpn-2.4.6/distro/systemd/openvpn-server@.service.in /lib/systemd/system/openvpn-server@.service

sudo vi /lib/systemd/system/openvpn-server@.service

On line 13, change @sbindir@ to /usr/local/sbin.

Write the file to disk, and quit the editor.

Start OpenVPN on the server:

sudo systemctl start openvpn-server@34.34.34.34

sudo systemctl enable openvpn-server@34.34.34.34

sudo systemctl status openvpn-server@34.34.34.34

sudo ss -tulpn | grep 443

Exit your SSH or PuTTY session with the server:

exit

Prepare Client

Start by making sure your client Ubuntu Linux PC is up to date:

sudo apt-get update
sudo apt-get upgrade

Build OpenVPN with Xor Patch on Client

Download the OpenVPN 2.4.6 source code:

cd ~/Downloads

wget http://swupdate.openvpn.org/community/releases/openvpn-2.4.6.tar.gz

tar xvf openvpn-2.4.6.tar.gz

Get the Tunnelblick versions of the Xor patch files:

wget https://github.com/Tunnelblick/Tunnelblick/archive/master.zip

sudo apt-get install unzip

unzip master.zip

Copy the patch files into the OpenVPN directory:

cp Tunnelblick-master/third_party/sources/openvpn/openvpn-2.4.6/patches/*.diff openvpn-2.4.6

Apply the patches:

cd openvpn-2.4.6

patch -p1 < 02-tunnelblick-openvpn_xorpatch-a.diff

patch -p1 < 03-tunnelblick-openvpn_xorpatch-b.diff

patch -p1 < 04-tunnelblick-openvpn_xorpatch-c.diff

patch -p1 < 05-tunnelblick-openvpn_xorpatch-d.diff

patch -p1 < 06-tunnelblick-openvpn_xorpatch-e.diff

Install the prerequisites for the build:

sudo apt-get install build-essential libssl-dev iproute2 liblz4-dev liblzo2-dev libpam0g-dev libpkcs11-helper1-dev libsystemd-dev resolvconf pkg-config

Build, make, and install OpenVPN with Xor patch:

./configure --enable-systemd --enable-async-push --enable-iproute2

make

sudo make install

sudo mkdir /etc/openvpn

sudo mkdir /etc/openvpn/server

sudo mkdir /etc/openvpn/client

Download Certificates and Keys from Server to Client

Download the certificates and keys:

cd ~/Downloads
scp ubuntu@34.34.34.34:/etc/openvpn/ca.crt .
scp ubuntu@34.34.34.34:/etc/openvpn/client/adminpc.crt .
scp ubuntu@34.34.34.34:/etc/openvpn/client/adminpc.key .
scp ubuntu@34.34.34.34:/etc/openvpn/tls-crypt.key .

Copy the certificates and keys into position:

sudo cp ca.crt /etc/openvpn
sudo cp adminpc.crt /etc/openvpn/client
sudo cp adminpc.key /etc/openvpn/client
sudo cp tls-crypt.key /etc/openvpn

Create OpenVPN Client Configuration File

Create the client configuration file:

cd /etc/openvpn
sudo vi client/adminpc.conf

Insert the contents of the client configuration,
using the following as a model:

client
dev tun
proto udp
remote 34.34.34.34 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca /etc/openvpn/ca.crt
cert /etc/openvpn/client/adminpc.crt
key /etc/openvpn/client/adminpc.key
remote-cert-tls server
cipher AES-256-GCM
tls-crypt /etc/openvpn/tls-crypt.key
verb 3
scramble obfuscate DPeQw3SvyIMdJqckjznYVLVUSG4p4KIQ

Write the file to disk, and quit the editor.

Start OpenVPN Client

Open a terminal on your Ubuntu client, and start OpenVPN running:

sudo openvpn --config /etc/openvpn/client/adminpc.conf