How to Setup OpenVPN on Ubuntu to Bypass Restrictive Firewalls

Background

Since I will be travelling to China next week I thought now would be a good time to setup a VPN that at least had some chance of working through the GFW. After doing some research I found there are a few possible solutions but the one I settled on was using OpenVPN with the scramble patch.

The goal of this guide is to help those travelling or living in China or other countries that have limitations on their internet access. In my case I am trying to bypass China’s Great Firewall which actively seeks out VPN connections and blocks them.  Using a typical OpenVPN configuration is no longer good enough as the GFW uses deep packet inspection to block OpenVPN connections.  Using an obfuscation technique I hope it will confuse the deep packet inspection and let the VPN function.  Full credit to the author of this thread for designing the scrambling technique.

Choosing a Server

I found a cheap VPN provider that has TUN/TAP enabled and a dedicated IP since I didn’t want to worry about a NAT’d IP. The actual specs of the machine are not that important as long as you get a sufficient amount of bandwidth for what you need it for.  I also selected one in the USA despite the privacy concerns but for the added benefit of being able to use it for US Netflix and other USA only services.  This is not meant to be an extremely NSA-proof server, but something I can use to get around China’s firewall restrictions.  If you have more privacy concerns, I would choose something in another country.

My Server Specs:

  • Ubuntu-12.04-x86_64-minimal
  • OpenVZ
  • 20gb HDD
  • RAM: 768mb / vSWAP: 768mb
  • 2TB Bandwidth
  • 1 IPv4

Lets get to setting up the server.

Setting Up The OpenVPN Server

The first thing to do is to make sure the system is up to date and the required packages are installed.
apt-get update
apt-get install
apt-get install gcc make automake autoconf dh-autoreconf file patch perl dh-make debhelper devscripts gnupg lintian quilt libtool pkg-config libssl-dev liblzo2-dev libpam0g-dev libpkcs11-helper1-dev chkconfig -y

After the system is updated, get the source code of OpenVPN and the patch.
cd $HOME/
wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.6.zip
unzip openvpn-2.3.6.zip
wget https://github.com/clayface/openvpn_xorpatch/archive/master.zip
unzip master.zip
cp openvpn_xorpatch-master/openvpn_xor.patch openvpn-2.3.6/
cd openvpn-2.3.6/
git apply --check openvpn_xor.patch
git apply openvpn_xor.patch

Lets make and install OpenVPN.
mkdir /etc/openvpn/
cd $HOME/openvpn-2.3.6/
./configure --prefix=/usr
make
make install
wget --no-check-cert https://Scott.StevensonOnThe.Net/files/OpenVPN/etcinitdopenvpn.sh -O /etc/init.d/openvpn
chmod +x /etc/init.d/openvpn
update-rc.d openvpn defaults

After this is complete, you should check to make sure OpenVPN has been added to the startup.  This way, if your machine restarts, OpenVPN will be started automatically.
chkconfig --list | grep openvpn
The output of this line should look like this:
openvpn 0:off 1:off 2:on 3:on 4:on 5:on 6:off
Now that OpenVPN is installed, we need to create the client and server certificates.

Lets create some folders for the client and server files.
mkdir $HOME/clientside
cd $HOME/clientside
git clone git://github.com/OpenVPN/easy-rsa
cd easy-rsa/easyrsa3
./easyrsa init-pki

In this step, you can specify the client name by replacing xclientx with the name of your client.  You will need to change it anywhere that you see xclientx.  This will generate the client req file.
./easyrsa gen-req xclientx nopass
mkdir $HOME/serverside
cd $HOME/serverside
git clone git://github.com/OpenVPN/easy-rsa
cd easy-rsa/easyrsa3

Generate keys/certificates for the server.
./easyrsa init-pki
./easyrsa build-ca
./easyrsa gen-req server nopass
./easyrsa sign-req server server
openssl dhparam -out dh2048.pem 2048
openvpn --genkey --secret ta.key
./easyrsa import-req $HOME/clientside/easy-rsa/easyrsa3/pki/reqs/xclientx.req xclientx
./easyrsa sign-req client xclientx

After all the certificates and keys are generated, copy them to the respective client and server directories.
cp $HOME/serverside/easy-rsa/easyrsa3/pki/ca.crt $HOME/serverside/
cp $HOME/serverside/easy-rsa/easyrsa3/pki/issued/server.crt $HOME/serverside/
cp $HOME/serverside/easy-rsa/easyrsa3/dh2048.pem $HOME/serverside/
cp $HOME/serverside/easy-rsa/easyrsa3/pki/private/server.key $HOME/serverside/
cp $HOME/serverside/easy-rsa/easyrsa3/ta.key $HOME/serverside/
cp $HOME/serverside/easy-rsa/easyrsa3/pki/issued/xclientx.crt $HOME/clientside/
cp $HOME/serverside/easy-rsa/easyrsa3/ta.key $HOME/clientside/
cp $HOME/serverside/easy-rsa/easyrsa3/pki/ca.crt $HOME/clientside/
cp $HOME/clientside/easy-rsa/easyrsa3/pki/private/xclientx.key $HOME/clientside/

Create the client configuration script.
nano $HOME/clientside/xclientx.ovpn
If nano is not installed, install it before the previous step.
apt-get install nano
Using nano, create a configuration with the following:
client
dev tun
scramble obfuscate insert_password_here
proto udp
remote insert_server_address_here 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert xclientx.crt
key xclientx.key
tls-auth ta.key 1
remote-cert-tls server
cipher AES-256-CBC
comp-lzo
verb 3
fast-io
script-security 2

As you can see, I am using port 443, but any port can be used as long as its the same on the server and client side.  The reason I am choosing port 443 is because this is a common port for encrypted traffic.  I am hoping traffic on this port may be left alone by the GFW more then a random port.  Each situation is different however, so choose what will work for you.

After saving the configuration (ctrl-o and then ctrl-x) its time to merge the configuration and the certificates into one file.
cd $HOME/clientside/
wget https://Scott.StevensonOnThe.Net/files/OpenVPN/merge.sh -O merge.sh
chmod +x merge.sh

Edit the file to change the xclientx names.  Save the file.
nano merge.sh
Run the script.
$HOME/clientside/merge.sh
Now there will be a single file in your $HOME/clientside/ directory called xclientx.ovpn. Use WinSCP to connect via SCP to this directory and copy the file to your PC. We will use it later to setup OpenVPN on our PC.

The server setup is very much the same as the client setup.  Open nano and create a configuration file.

For the DNS settings, you can set it to anything you want, but I went to the Open Nic Project to find some DNS servers that keep no logs and are close to my server location to keep the DNS lookups quick.  You can also use Google (8.8.8.8, 8.8.4.4) or OpenDNS (208.67.222.222, 208.67.220.220).  I have left in Googles DNS for the example.
nano $HOME/serverside/server.conf
port 443
proto udp
dev tun
scramble obfuscate test
ca ca.crt
cert server.crt
key server.key
tls-auth ta.key 0
dh dh2048.pem
server 10.8.0.0 255.255.255.0
cipher AES-256-CBC
comp-lzo
persist-key
persist-tun
user nobody
group nogroup
status openvpn-status.log
verb 3
push "redirect-gateway def1"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 5 30

Like we did with the client configuration, merge the keys, certificates and configuration into one file.
cd $HOME/serverside/
wget --no-check-cert https://Scott.StevensonOnThe.Net/files/OpenVPN/merge_server.sh -O merge_server.sh
chmod +x merge_server.sh
./merge_server.sh
cp $HOME/serverside/server.conf /etc/openvpn/

Next enable data redirect.
nano /etc/sysctl.conf
Uncomment the following line and save the file. (ctrl-o)
net.ipv4.ip_forward=1
Make a file for the firewall settings.
nano /usr/local/bin/firewall.sh
Paste the following rules and save the file.
#!/bin/bash
iptables -t filter -F
iptables -t nat -F
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s "10.8.0.0/24" -j ACCEPT
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s "10.8.0.0/24" -j MASQUERADE

Change the permissions on the file so its executable
chmod +x /usr/local/bin/firewall.sh
/usr/local/bin/firewall.sh
iptables --list

Make the firewall settings apply after each reboot.
nano /etc/rc.local
Add the following to the file before the line “exit 0” and save it.
/usr/local/bin/firewall.sh
Apply the settings.
sysctl -w net.ipv4.ip_forward=1
/etc/init.d/openvpn restart

Any time changes are made to the server configuration OpenVPN must be restarted.  To restart OpenVPN use the following:
/etc/init.d/openvpn restart

Now that we have the server and client configuration completed, all that remains is to set this up on the client PC.  Download OpenVPN 2.3.6 from the official source. Install this on your Windows machine.  After installation, you need to apply the patched executable to make scramble work. Download from here. (Mirror: OpenVPN Scramble Patched Windows 64bit 2.3.6)  Replace the file located in C:\Program Files\OpenVPN\bin.

I’ll post an update from China if this works.  :wave:

Next: How To Add and Remove Users

3 Reader Comments

Leave a Comment