There are few good choices like OpenVPN, SoftEther, Pritunl etc. If you prefer something much more robust, I'd suggest to take look at strongSwan (IPSec + ESP). If you prefer something temporary just use ssh tunnel ssh -D 9050 user@server
, install proxychains and proxychains firefox
, vola you're traffic is encrypted. The only issue is, it's hard use socks proxy on un-rooted mobile phone and sessions are temporary.
I choose OpenVPN since it's widely used and it's easy to configure. However OpenVPN has it's drawbacks, it's easier to detect if a person is using OpenVPN by checking the packet MTU size.
Creating FreeBSD server on Azure
Create a new freebsd 10.3 instance on Azure, generate SSH key using the following command
openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout vpn_server.key -out vpn_server.pem
Don't forget to change the default username (azureuser) and block all ports except 22 till we configure the VPN server. You may wonder why FreeBSD, well here's the resource usage on a fully functional vpn server
Enable IP packet forwarding
Enable IP forwarding on the server by setting net.inet.ip.forwarding=1
in sysctl.conf file.
sudo sysctl net.inet.ip.forwarding=1
sudo nano /etc/sysctl.conf
Enable packet filter (pf)
pf
is the freebsd version of iptables, OpenVPN 10.8.0.0/24
must be routed properly, open /etc/pf.conf
as root and add the following configuration
ext_if=hn0 # if your interface is eth0 then use that instead
openvpn_subnet="{10.8.0.0/24}"
# similar to iptables -t nat -a POSTROUTING -s 10.8.0.0/24 -o hn0 -j MASQUERADE
nat on $ext_if from $openvpn_subnet to any -> ($ext_if)
Start pf by default using sudo sysrc pf=yes
after system reboot.
Installing DNSCrypt and Unbound
Install dnscrypt-proxy on the FreeBSD sudo pkg install dnscrypt-proxy
. Update the /etc/rc.conf
file so the dnscrypt autostarts after reboots, add the following config to /etc/rc.conf
. cs-useast
is the dnscrypt provider is closest to the server location, you can choose one that's closest to you from this list
# dnscrypt-proxy
dnscrypt_proxy_enable="YES"
dnscrypt_proxy_flags="-a 127.0.0.1:54"
dnscrypt_proxy_resolver="cs-useast"
dnscrypt_proxy_logfile="/dev/null"
Install unbound to act as a local dns cache sudo pkg install unbound
. Edit the unbound config file /var/unbound/unbound.conf
using sudo and add the following configuration
server:
username: unbound
directory: /var/unbound
chroot: /var/unbound
do-not-query-localhost: no
interface: 0.0.0.0
access-control: 0.0.0.0/0 refuse # disable access to rest of the world
access-control: 127.0.0.0/8 allow # enable access to local network
access-control: 10.8.0.0/24 allow # enable access to OpenVPN subnet
hide-identity: yes
hide-version: yes
auto-trust-anchor-file: "/var/unbound/root.key"
#include: /var/unbound/forward.conf
#include: /var/unbound/lan-zones.conf
#include: /var/unbound/control.conf
forward-zone:
name: "." # use for ALL queries
forward-addr: 127.0.0.1@40 # dnscrypt-proxy
Update the default DNS resolvers on /etc/resolv.conf
to use unbound, 127.0.0.1
on port 53 as the default dns resolver
# Generated by resolvconf
# search XXXXXX.c4.internal.cloudapp.net
# nameserver XXX.XXX.XXX.XXX
# unbound + dnscrypt-proxy
nameserver 127.0.0.1
Start the unbound server after reboot sudo sysrc local_unbound_enable=YES
, by default the unbound used the config file located at /var/unbound/unbound.conf
. If you plan to use different location, update the /etc/rc.conf
file to pass the config file we saved in STEP2 to unbound after reboot
# Unbound
unbound_flags="-c /var/unbound/unbound.conf"
Reboot the server sudo reboot
and test the DNS resolution with the following command
drill -S freebsd.org
# this should print somethink like
;; Number of trusted keys: 1
;; Chasing: freebsd.org. A
DNSSEC Trust tree:
freebsd.org. (A)
|---freebsd.org. (DNSKEY keytag: 48075 alg: 8 flags: 256)
|---freebsd.org. (DNSKEY keytag: 25814 alg: 8 flags: 257)
|---freebsd.org. (DS keytag: 25814 digest type: 2)
|---org. (DNSKEY keytag: 64353 alg: 7 flags: 256)
|---org. (DNSKEY keytag: 9795 alg: 7 flags: 257)
|---org. (DNSKEY keytag: 17883 alg: 7 flags: 257)
|---org. (DS keytag: 9795 digest type: 2)
| |---. (DNSKEY keytag: 39291 alg: 8 flags: 256)
| |---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
|---org. (DS keytag: 9795 digest type: 1)
|---. (DNSKEY keytag: 39291 alg: 8 flags: 256)
|---. (DNSKEY keytag: 19036 alg: 8 flags: 257)
;; Chase successful
drill google.com
# Output
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 51628
;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; google.com. IN A
;; ANSWER SECTION:
google.com. 300 IN A 216.58.218.238
;; AUTHORITY SECTION:
;; ADDITIONAL SECTION:
;; Query time: 25 msec
;; SERVER: 127.0.0.1
;; WHEN: Sun Nov 13 03:16:49 2016
;; MSG SIZE rcvd: 44
Installing OpenVPN
Install openvpn and easy-rsa by running sudo pkg install openvpn easy-rsa
. Create a new directory sudo mkdir /usr/local/etc/openvpn
and copy sample configuration file and easy-rsa files.
cp /usr/local/share/examples/openvpn/sample-config-files/server.conf \
/usr/local/etc/openvpn/openvpn.conf
cp -r /usr/local/share/easy-rsa /usr/local/etc/openvpn/easy-rsa
Edit the vars
file under /usr/local/etc/openvpn/easy-rsa
and change the following,
cd /usr/local/etc/openvpn/easy-rsa
sudo vi vars
set_var EASYRSA_REQ_COUNTRY "US" # "COUNTRY"
set_var EASYRSA_REQ_PROVINCE "NY" # "PROVINCE"
set_var EASYRSA_REQ_CITY "New York" # "CITY"
set_var EASYRSA_REQ_ORG "ORG" # "ORGANIZATION"
set_var EASYRSA_REQ_EMAIL "admin@localhost" # "EMAIL"
set_var EASYRSA_REQ_OU "VPN Server" # "ORGANIZATIONAL UNIT"
set_var EASYRSA_REQ_CN "vpn" # COMMON_NAME
set_var EASYRSA_KEY_SIZE 4096 # set key size to 4096
set_var EASYRSA_CA_EXPIRE 3650 # Set self-signed CA to expire after 10 years
set_var EASYRSA_CERT_EXPIRE 1825 # Set cert to expire after 5 years, don't worry even if you lost
# the certs or if they are compromised, you can revoke them.
Now start generating the keys, now run sudo ./easyrsa.real help
to print the list of commands. Lets start with building PKI
Build Public Key Infrastructure (PKI)
Initialize PKI by running init-pki
sudo ./easyrsa.real init-pki
-- Output --
Note: using Easy-RSA configuration from: ./vars
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /usr/local/etc/openvpn/easy-rsa/pki
Once PKI is initialized, run build-ca
to build CA, It will ask for a password and a common name, use a strong random password because it's used to encrypt the key and if the password is compromised, it'll compromise entire PKI.
Tip: cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1
to generate 32 char long random string
sudo ./easyrsa.real build-ca
-- Output --
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
....................++
.................++
writing new private key to '/usr/local/etc/openvpn/easy-rsa/pki/private/ca.key.UCYBDDSvsh'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/usr/local/etc/openvpn/easy-rsa/pki/ca.crt
Now generate the vpn server certificate with sudo ./easyrsa.real build-server-full openvpn-server nopass
with certificate name as openvpn-server
and without the password. It'll ask the password for ca.key, enter the password used in the previous step.
# ./easyrsa.real build-server-full openvpn-server nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
.....................................................................................++
.............................................................................++
writing new private key to '/usr/local/etc/openvpn/easy-rsa/pki/private/openvpn-server.key.65YXAVRkws'
-----
Using configuration from /usr/local/etc/openvpn/easy-rsa/openssl-1.0.cnf
Enter pass phrase for /usr/local/etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'openvpn-server'
Certificate is to be certified until Nov 11 21:30:50 2021 GMT (1825 days)
Write out database with 1 new entries
Data Base Updated
Check the certificate with sudo ./easyrsa.real show-cert openvpn-server
, it should print something like this
Note: using Easy-RSA configuration from: ./vars
Showing cert details for 'openvpn-server'.
This file is stored at:
/usr/local/etc/openvpn/easy-rsa/pki/issued/openvpn-server.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
commonName = vpn
Validity
Not Before: Nov 12 21:30:50 2016 GMT
Not After : Nov 11 21:30:50 2021 GMT
Subject:
commonName = openvpn-server
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
4B:E5:F1:1A:01:1F:9F:AB:C8:72:16:9B:70:C9:C9:9D:6B:6B:50:E8
X509v3 Authority Key Identifier:
keyid:A6:13:41:E5:E8:E1:A2:B7:03:91:D8:83:8D:DA:F7:9C:28:34:FF:A4
DirName:/CN=vpn
serial:AD:B0:43:C8:3B:25:03:B3
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Key Usage:
Digital Signature, Key Encipherment
Once the server certificate is generated, build a client certificate sudo ./easyrsa.real build-client-full <UNIQUE_NAME_GOES_HERE> nopass
, nopass
leaves the client key unencrypted, it's upto you if you want to leave it that way. If you need client certificates for another device, repeat the above step but make sure you use a different name.
sudo ./easyrsa.real build-client-full desktop nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
.....................................................................................................
...................................................................++
writing new private key to '/usr/local/etc/openvpn/easy-rsa/pki/private/desktop.key.m4nxiIGhou'
-----
Using configuration from /usr/local/etc/openvpn/easy-rsa/openssl-1.0.cnf
Enter pass phrase for /usr/local/etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'desktop'
Certificate is to be certified until Nov 11 21:42:07 2021 GMT (1825 days)
Write out database with 1 new entries
Data Base Updated
finally generate Diffie Hellman parameters dh.pem
using sudo ./easyrsa.real gen-dh
. This openssl uses generator 2 by default but if you want more secure prime, use generator 5 ( it takes a while to generate a 4096 bit long prime, please be patient)
sudo ./easyrsa.real gen-dh
Create a directory keys
in /usr/local/etc/openvpn
, copy the generated keys to /usr/local/etc/openvpn/keys
.
cd /usr/local/etc/openvpn/easy-rsa
cp pki/dh.pem pki/ca.crt pki/issued/openvpn-server.crt \
pki/private/openvpn-server.key /usr/local/etc/openvpn/keys
Copy the individual keys to the respective client.
Client Cert: /usr/local/etc/openvpn/easy-rsa/pki/issued/<name>.crt
Client Key: /usr/local/etc/openvpn/easy-rsa/pki/private/<name>.key
CA Cert: /usr/local/etc/openvpn/easy-rsa/pki/ca.crt
# archive the above files for easy distribution.
# use scp or rsync to download the archive.
tar czvf desktop.tar.gz pki/ca.crt pki/issued/desktop.crt pki/private/desktop.key
Generate OpenVPN server and client config files
Now edit the OpenVPN server configuration file openvpn.conf
, first change dir to cd /usr/local/etc/openvpn
and edit the openvpn.conf
file we copied in the initial steps or simply copy-paste the following configuration
# Server configuration
;listen IPADDRESS_OF_NIC
# Port
;port 1194 # best to use a random port
port YYYYY
# TCP or UDP
proto udp
# Routed IP tunnel
dev tun
# Cert and keys
ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/openvpn-server.crt
key /usr/local/etc/openvpn/keys/openvpn-server.key
dh /usr/local/etc/openvpn/keys/dh.pem
# HMAC
# both server and client must have copy of ta.key
# ta.key 0 --> server
# ta.key 1 --> client
tls-auth /usr/local/etc/openvpn/keys/ta.key 0
# Cryptographic cipher
# select AES 256 bit
cipher AES-256-CBC
# tls support
remote-cert-tls client
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
# Force clients to use unbound + dnscrypt-proxy server
push "dhcp-option DNS 10.8.0.1"
# Allow clients to see each other
;client-to-client
# Resume client config for multiple users
;duplicate-cn
# Ping client every 10 secs
keepalive 10 120
# Disable compression
# you can enable it if you like
;comp-lzo
# Privileges, chroot
# chroot /var/openvpn
user nobody
group nobody
# The persist options will try to avoid
# accessing certain resources on restart
# that may no longer be accessible because
# of the privilege downgrade.
persist-key
persist-tun
# client status information
status openvpn-status.log
# log
log openvpn.log
# presistant log accross reboots
;log-append openvpn.log
verb 4
mute 20
Now let's create the client openvpn configuration file and copy paste the following config. Make sure you replace all the certs i.e copy ca.crt and past it inbetween <ca> </ca>
tags, change server ip address (XXX.XXX.XXX.XXX) and port (YYYYY)
#Run in client mode
client
# tun/tap
dev tun
# TCP or UDP
proto udp
# remote SERVER_IP_ADDRESS SERVER_OPENVPN_PORT
# you can add multiple OpenVPN servers to load balance
# between them. Enable remote-random to tell client to
# choose a random server
remote XXX.XXX.XXX.XXX YYYYY
;remote-random
# keep retrying if connection is lost
# enable this if one of your clients is
# a mobile or laptop
resolv-retry infinite
nobind
# if non-windows systems enable
;user nobody
;group nobody
persist-key
persist-tun
# tls auth
remote-cert-tls server
# Enable if server has compression enabled
;comp-lzo
# logging
verb 4
mute 20
# Use same cipher as server
cipher AES-256-CBC
# ca ca.crt
# cert client.crt
# key client.key
# tls-auth ta.key 1
# You can also embed the files within the config, easier for distribution.
#ca [inline]
#cert [inline]
#key [inline]
#tls-auth [inline] 1
key-direction 1
# ca.crt
#<ca>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
#</ca>
# client.crt
#<cert>
#</cert>
# client.key
#<key>
#</key>
# ta.key
#< tls-auth >
#</tls-auth>
Now we just need to enable openvpn to run as a daemon and reboot the system
sudo sysrc openvpn_enable="YES"
sudo sysrc openvpn_if="tun"
sudo reboot
Download the client configuration files and import them into your network manager. That's it, your network traffic is now encrypted.
Tip: OpenVPN on android recognized .ovpn
files, simply replace the client.conf --> client.ovpn
Well then, I'm gonna go and play 0 A.D.