Install OpenVPN
sudo aptitude install openvpn
# open port 1194 (as shown here for the ufw firewall interface):
sudo ufw allow 1194
Become an Certificate Authority
Alternative to this way: Use TinyCA (there are Ubuntu packages available).
sudo mkdir /etc/openvpn/easy-rsa/
sudo cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
sudo chown -R $USER /etc/openvpn/easy-rsa/
cat << EOF | sudo tee -a /etc/openvpn/easy-rsa/vars >/dev/null
export KEY_COUNTRY="DE"
export KEY_PROVINCE="Hesse"
export KEY_CITY="Frankfurt"
export KEY_ORG="Your Organization"
export KEY_EMAIL="contact@example.org"
EOF
create the server certificates:
cd /etc/openvpn/easy-rsa/
source vars
./clean-all
./build-dh
./pkitool --initca
./pkitool --server server
cd keys
openvpn --genkey --secret ta.key
sudo cp server.crt server.key ca.crt dh1024.pem ta.key /etc/openvpn/
After making changes to the configuration restart the server:
sudo /etc/init.d/openvpn restart
For each client: Create a client certificate
Replace hostname with the actual hostname of the machine connecting to the VPN:
cd /etc/openvpn/easy-rsa/
source vars
./pkitool hostname
And copy the following files to the client:
/etc/openvpn/ca.crt/etc/openvpn/ta.key/etc/openvpn/easy-rsa/keys/hostname.crt/etc/openvpn/easy-rsa/keys/hostname.key
For an easier transfer you can bundle the 4 files into a .tar.bz2 file like this:
sudo -i # or just su (on Debian)
HOSTNAME="hostname"
cd /etc/openvpn/easy-rsa/keys
tar cjf bundle.tar.bz2 ../../ca.crt ../../ta.key $HOSTNAME.crt $HOSTNAME.key
All of this can be automated and made comfortable with the following helper bash script: https://gist.github.com/952469#file_create_keys_for_client.sh.
Revoke a client certificate
http://people.mandriva.com/~ybourhis/openvpn/index.html
http://openvpn.net/howto.html#revoke
Since an OpenVPN server’s only means of authentication is to check whether the certificate presented by a client is signed by the “right” CA, the only way to revoke VPN access is to revoke the certificate. This is also done on the CA system by calling
/etc/openvpn/easy-rsa/revoke-full <client-name>
ln /etc/openvpn/easy-rsa/keys/crl.pem /etc/openvpn/
This creates a crl.pem file which contains a list of all revoked certificates and a hardlink in /etc/openvpn. Then add the directive crl-verify crl.pem to your server.conf.
Set up a bridged VPN
Set up a bridged VPN using the tap0 device (as described in the Ubuntu Server Guide on OpenVPN).
Set up The Bridge
- according to https://help.ubuntu.com/10.04/serverguide/C/network-configuration.html#bridging
- more documentation on bridging:
/usr/share/doc/bridge-utils/
Install the package bridge-utils (containing mainly the binary brctl):
sudo apt-get install bridge-utils
(When doing this on a virtual server you might need to install udev too: # apt-get install udev)
And now make your /etc/network/interfaces look like this:
auto lo
iface lo inet loopback
auto br0
iface br0 inet static
address ww.xx.yy.zz
network ww.xx.yy.0
netmask 255.255.255.0
broadcast ww.xx.yy.255
gateway ww.xx.yy.1
bridge_ports eth0
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off
Restart networking to enable the bridge interface:
sudo /etc/init.d/networking restart
server configuration
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
sudo gzip -d /etc/openvpn/server.conf.gz
Now you have a server configuration file /etc/openvpn/server.conf (from the example file). Adjust it to:
local 192.168.1.2
dev tap0
up "/etc/openvpn/up.sh br0"
down "/etc/openvpn/down.sh br0"
;server 10.8.0.0 255.255.255.0
; the server's IP and subnet and the range of IP addresses the server may assign to connecting clients:
server-bridge ww.xx.yy.zz 255.255.255.0 ww.xx.yy.zz+1 ww.xx.yy.255-1
push "route ww.xx.yy.1 255.255.255.0"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DOMAIN example.com"
tls-auth ta.key 0 # This file is secret
user nobody
group nogroup
Now set up the tap0 helper files.
First the interface up script: sudo vim /etc/openvpn/up.sh
#!/bin/sh
BR=$1
DEV=$2
MTU=$3
/sbin/ifconfig $DEV mtu $MTU promisc up
/usr/sbin/brctl addif $BR $DEV
And now the interface down script: sudo vim /etc/openvpn/down.sh
#!/bin/sh
BR=$1
DEV=$2
/usr/sbin/brctl delif $BR $DEV
/sbin/ifconfig $DEV down
Make them executable for root:
sudo chmod 755 /etc/openvpn/down.sh
sudo chmod 755 /etc/openvpn/up.sh
using tun device as described in ubuntuusers.de Wiki
permalink: http://wiki.ubuntuusers.de/OpenVPN?rev=182021
server configuration
port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
;push "redirect-gateway def1 bypass-dhcp"
;push "dhcp-option DNS 208.67.222.222"
;push "dhcp-option DNS 208.67.220.220"
;client-to-client
keepalive 10 120
tls-auth ta.key 0 # This file is secret
comp-lzo
persist-key
persist-tun
status openvpn.status
verb 3
nice tweak: redirect all traffic through the VPN tunnel
diff for /etc/openvpn/server.conf:
--- a/openvpn/server.conf
+++ b/openvpn/server.conf
;push "redirect-gateway def1 bypass-dhcp"
+push "redirect-gateway def1"
+push "route-gateway 10.8.0.1"
restart openvpn:
sudo /etc/init.d/openvpn restart
Allow NAT when using ufw as firewall (as described on http://www.nowhere.dk/articles/tip_nat_with_ubuntus_ufw_firewall):
In the file /etc/default/ufw set the parameter DEFAULT_FORWARD_POLICY to ACCEPT
DEFAULT_FORWARD_POLICY="ACCEPT"
In /etc/ufw/sysctl.conf uncomment
net.ipv4.ip_forward=1
Right at the beginning of /etc/ufw/before.rules (after the introductory comments) add this whole code block:
# nat Table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Forward traffic through ppp0 - Change to match you out-interface
-A POSTROUTING -s 10.8.0.0/24 -o eth2 -j MASQUERADE
# don't delete the 'COMMIT' line or these nat table rules won't be processed
COMMIT
where 10.8.0.0/24 is the IP block from your VPN and eth2 is the network interface you want NAT to redirect requests to.
Restart the firewall:
sudo ufw disable && sudo ufw enable
On the clients you need to set the DNS server (to 208.67.222.222 for example). This can be done using scripts or using the setup of network-manager-openvpn.
If you suspect the NAT might not work, watch out for error messages on the server using
tailf /var/log/messages
client configuration
client
dev tun
;proto tcp
proto udp
remote your.openvpn.server.com 1194
;remote my-server-2 1194
;remote-random
resolv-retry infinite
nobind
;user nobody
;group nogroup
persist-key
persist-tun
;http-proxy-retry # retry on connection failures
;http-proxy [proxy server] [proxy port #]
;mute-replay-warnings
ca ca.crt
cert penryn.crt
key penryn.key
ns-cert-type server
tls-auth ta.key 1
;cipher x
comp-lzo
verb 3
;mute 20
set up the client using network-manager-openvpn
install network-manager-openvpn
Set up a new VPN configuration: OpenVPN. Set up the gateway to your OpenVPN server, The user certificate, ca certificate and private key have to be given (user.crt, ca.crt and user.key) and then change advanced params: LZO-compression, TCP; TLS-AUTH: ta.key and direction 1.
On the IPv4 settings set up the DNS Server to 208.67.222.222. Done.
Test the configuration
Try to connect and if it connected successfully, you can test the configuration like this:
ping 10.8.0.1
or if you run a webserver on the remote server you can check http://10.8.0.1 . If you run a network logger like wireshark, then listen on your physical connection and you will only see scrambled data in the packages.
speed
using netcat speedtest: speed over vpn connection: (4 754 432 bytes) / (16.64500 seconds) = 2.18 Mbps uncencrypted direct connection: (146 632 704 bytes) / (25.77 seconds) = 43.4 Mbps
using iperf speedtest:
iperf -s -p 2222
------------------------------------------------------------
Server listening on TCP port 2222
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 10.8.0.1 port 2222 connected with 10.8.0.6 port 50052
[ ID] Interval Transfer Bandwidth
[ 4] 0.0- 6.1 sec 1.70 MBytes 2.33 Mbits/sec
[ 5] local 192.168.1.20 port 2222 connected with 192.168.1.22 port 50055
[ 5] 0.0- 5.1 sec 32.4 MBytes 53.4 Mbits/sec
⚡ there is a problem here!
when I change the VPN to proto tcp on both sides then the result looks different: uncencrypted direct connection: (46 382 080 bytes) / (8.11 seconds) = 43.6 Mbps speed over vpn connection: (152 698 880 bytes) / (8.76100 seconds) = 132.975688 Mbps
philipp@lion:~$ iperf -s -p 2222
------------------------------------------------------------
Server listening on TCP port 2222
TCP window size: 85.3 KByte (default)
------------------------------------------------------------
[ 4] local 10.8.0.1 port 2222 connected with 10.8.0.6 port 50080
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-10.0 sec 179 MBytes 151 Mbits/sec
[ 5] local 192.168.1.20 port 2222 connected with 192.168.1.22 port 50079
[ 5] 0.0-10.0 sec 62.9 MBytes 52.7 Mbits/sec
now the vpn based connection (10.8.0.1) looks much faster!
It is even faster than the physical network connection. This can only be due to the zlib compression…
newer configuration
server
status openvpn.status
port 1194
proto tcp
dev tun
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1"
push "dhcp-option DNS 208.67.222.222"
client-to-client
keepalive 10 120
tls-auth ta.key 0 # This file is secret
comp-lzo
persist-key
persist-tun
verb 3
client
client
dev tun
auth-nocache
proto tcp-client
remote your.openvpn.server.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert philipp-ubuntu-virt.crt
key philipp-ubuntu-virt.key
ns-cert-type server
tls-auth ta.key 1
comp-lzo
verb 3
; now also set the dns entry:
script-security 2
up ./up.sh
where ./up.sh is
#!/bin/sh
# <http://openvpn.net/archive/openvpn-users/2006-10/msg00217.html>
# script to automatically set DNS information on connection
mv /etc/resolv.conf /etc/resolv.conf.hold # back up old file
for OPTION in "${foreign_option_1}" "${foreign_option_2}" "${foreign_option_3}" "${foreign_option_4}" "${foreign_option_5}" "${foreign_option_6}"
do
if [ -z "${OPTION}" ]; then
break
fi
if [ -n "$(echo ${OPTION} | grep DOMAIN)" ] || [ -n "$(echo ${OPTION} | grep DNS)" ]; then
echo ${OPTION} |sed -e 's/dhcp-option DOMAIN/search/g' -e 's/dhcp-option DNS/nameserver/g' >> /etc/resolv.conf
fi
done
if [ ! -f /etc/resolv.conf ]; then # openvpn did not set any DNS information
mv /etc/resolv.conf.hold /etc/resolv.conf
fi
and ./down.sh
#!/bin/sh
mv /etc/resolv.conf.hold /etc/resolv.conf
A more elaborate updown script (using resolvconf) can be found on https://gist.github.com/5084036e9a4b4206e074.
Statistics
Add a line to your /etc/openvpn/server.conf:
status openvpn.status
and use the python script from http://code.geek.sh/2009/07/simple-openvpn-server-statistics/
Resources
- Howto for IPv6 (German): https://wiki.rul3z.de/doku.php?id=ipv6-tunnel_ueber_openvpn