OpenVPN

From Frack - Hackerspace Friesland
Jump to navigationJump to search
Onderwerp: OpenVPN
OpenVPN Logo.png
Deskundigen
Gebruiker Elmer.jpg Elmer
Gebruiker Elmer.jpgElmer de Looff (Elmer) Rol: niet-deelnemer Deskundig met: Arduino, ENC28J60, Elektronica, GnuCash, HTML, LPD8806, Linux, MediaWiki, Mercurial, Netwerken, OpenVPN, Programmeren, Python, SSH, Software, Solderen Beginnend met: Dm-crypt, Javascript Werkt aan: Geen projecten :(
,
Afbeelding Anoniem.png Fludizz
Fludizz Rol: deelnemer Deskundig met: GL-Inet, Glasvezel lassen, Iptables, Linux, Netwerken, Nftables, OpenVPN, Python, RaspberryPi, Software Beginnend met: ENC28J60 Werkt aan: Geen projecten :(
Onderdeel van Linux, Beveiliging, Netwerken

OpenVPN is open sourcesoftware waarmee een beveiligde dataverbinding in de vorm van een Virtueel Particulier Netwerk (VPN) kan worden opgezet. OpenVPN versleutelt de communicatie door middel van het Transport Layer Security-protocol (TLS).

Multi-client TLS server

Het opzetten van een VPN server is natuurlijk pas echt interessant wanneer er meer dan 1 gebruiker kan verbinden. Op deze manier hoeft niet voor elke verbinding een aparte configuratie, geheime sleutel en poort geconfigureerd te worden. De stappen om dit te realiseren zijn een stuk uitgebreider dan voor de setup met slechts een enkele client, vandaar deze uitleg.

Het opzetten van deze VPN server bestaat grof gezien uit 3 stappen:

Veiligheidswaarschuwing

Om deze handleiding eenvoudig te houden worden de stappen tbv de Certificate Authority en de OpenVPN server op dezelfde machine uitgevoerd. Dit is niet noodzakelijk, en kan leiden tot grove beveiligingsproblemen wanneer er op de OpenVPN server onrechtmatig root privileges worden verstrekt aan malafide gebruikers. Deze zouden dan beheer krijgen over de prive-sleutel van de server. Deze kan vervolgens gebruikt worden om extra server certificaten aan te maken om MITM-aanvallen mee te plegen, of extra certificaten aan te maken die niet herleidbaar zijn naar een bekende gebruiker.

Voor toepassingen waar alle gebruikers van de server redelijk te vertrouwen zijn, en er degelijk beheer is van het root-account is dit geen serieus probleem, maar baseer geen grote VPN-dienst op deze handleiding ;-)

Aanmaken van certificaten

Beginstappen easy-rsa

Zoals gezegd draaien we de Certificaat-Autoriteit (vanaf nu: CA) op dezelde machine als onze VPN server. De eerste stap is uiteraard de installatie van OpenVPN zelf. Deze komt uit de standaard Debian/Ubuntu repository, en is zo te installeren:

root@Maxwell:~# apt-get install openvpn

Hierna kopieren we de easy-rsa voorbeeld-directory naar de directory die we willen gebruiken voor onze certificaat-server:

root@Maxwell:~# cp -a /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/maxwell
root@Maxwell:~# cd /etc/openvpn/maxwell

We gebruiken hier een map met dezelfde naam als de lokale machinenaam. Op deze manier zijn verschillende server en client configuraties uit elkaar te houden, maar de namen zijn uiteraard volledig naar eigen keuze.

Voor alle volgende commando's is het belangrijk dat deze uitgevoerd worden vanuit de zojuist gekopieerde map.

Certificaat-configuratie

De volgende stap is het instellen van de certificaatgegevens. Deze staan in het bestand vars. Open dit met je favoriete editor, en pas de paar waarden onderaan aan, deze zijn hier ter voorbeeld ingevuld:

# easy-rsa parameter settings
 
# NOTE: If you installed from an RPM,
# don't edit this file in place in
# /usr/share/openvpn/easy-rsa --
# instead, you should copy the whole
# easy-rsa directory to another location
# (such as /etc/openvpn) so that your
# edits will not be wiped out by a future
# OpenVPN package upgrade.
 
# This variable should point to
# the top level of the easy-rsa
# tree.
export EASY_RSA="`pwd`"
 
#
# This variable should point to
# the requested executables
#
export OPENSSL="openssl"
export PKCS11TOOL="pkcs11-tool"
export GREP="grep"
 
 
# This variable should point to
# the openssl.cnf file included
# with easy-rsa.
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
 
# Edit this variable to point to
# your soon-to-be-created key
# directory.
#
# WARNING: clean-all will do
# a rm -rf on this directory
# so make sure you define
# it correctly!
export KEY_DIR="$EASY_RSA/keys"
 
# Issue rm -rf warning
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
 
# PKCS11 fixes
export PKCS11_MODULE_PATH="dummy"
export PKCS11_PIN="dummy"
 
# Increase this to 2048 if you
# are paranoid.  This will slow
# down TLS negotiation performance
# as well as the one-time DH parms
# generation process.
export KEY_SIZE=2048
 
# In how many days should the root CA key expire?
export CA_EXPIRE=3650
 
# In how many days should certificates expire?
export KEY_EXPIRE=3650
 
# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="NL"
export KEY_PROVINCE="Friesland"
export KEY_CITY="Leeuwarden"
export KEY_ORG="Frack"
export KEY_EMAIL="keyparty@frack.nl"

We hebben hier de key_size opgeschroeft naar 2048 bits. Dit op aanraden van de uitvinders/ontwikkelaars van RSA, zie ook TWIRL. Verder zijn de organisatie en locatiegegevens ingevuld (onderaan). Dit zijn de enige wijzigingen die gedaan hoeven worden aan het voorbeeldbestand.

De volgende stap is om de PKI (Public Key Infrastructure) te initialiseren:

. ./vars
./clean-all
./build-ca

De laatste handeling creert de prive-sleutel van onze certificaat-server. Er worden hier om een aantal stukken informatie gevraagd, maar als de vars goed zijn ingevuld kunnen deze alle volstaan met de standaard-waarde (enter drukken dus). Dit ziet er zo uit:


root@Maxwell:/etc/openvpn/maxwell# . ./vars 
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/maxwell/keys
root@Maxwell:/etc/openvpn/maxwell# ./clean-all 
root@Maxwell:/etc/openvpn/maxwell# ./build-ca
Generating a 2048 bit RSA private key
.........................+++
.....+++
writing new private key to 'ca.key'
-----
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.
-----
Country Name (2 letter code) [NL]:
State or Province Name (full name) [Friesland]:
Locality Name (eg, city) [Leeuwarden]:
Organization Name (eg, company) [Frack]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [Frack CA]:
Name []:
Email Address [keyparty@frack.nl]:
root@Maxwell:/etc/openvpn/maxwell# 

Hierna hebben we de volgende bestanden in onze keys directory staan:

  • ca.crt – Het publieke certificaat van de CA. Dit is informatie die nodig is voor servers en clients om te verifieren dat de andere partij een certificaat gebruikt dat door deze CA is afgegeven.
  • ca.key – De prive-sleutel van de CA. Dit bestand is alleen nodig op de certificaat-server, en dient geheim te blijven.
  • De overige bestanden die er staan zijn op dit moment niet relevant

TLS-Auth configuratie

Het gebruik van tls-auth voegt een digitale handtekening toe aan elk pakket. Hierdoor zijn Denial-of-Service aanvallen, portscans voor UDP servers, buffer-overflow aanvallen in SSL/TLS te ondervangen omdat deze pakketten met een verkeerde handtekening verder niet behandeld worden.

Het aanmaken en gebruik hiervan is eenvoudig:

openvpn --genkey --secret keys/ta.key

Server certificaat

Nu de certificaat-server zelf is opgezet, is de volgende stap het aanmaken van de Diffie-Hellman parameters [1] en het server-certificaat. Hiermee kunnen gebruikers verifieren dat ze contact hebben met de server die ze proberen te bereiken, en is een essentieleel onderdeel van de encryptie. Het te gebruiken commando is:

./build-dh
./build-key-server server

En dit levert het volgende resultaat:

root@Maxwell:/etc/openvpn/maxwell# ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...................................................................+...................
.......................................................................................
.+..................................................................................+..
....+..................................................................................
.......................+.......................................+............ (ingekort)
root@Maxwell:/etc/openvpn/maxwell# ./build-key-server server
Generating a 2048 bit RSA private key
..............................................................+++
.+++
writing new private key to 'server.key'
-----
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.
-----
Country Name (2 letter code) [NL]:
State or Province Name (full name) [Friesland]:
Locality Name (eg, city) [Leeuwarden]:
Organization Name (eg, company) [Frack]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [server]:maxwell
Name []:
Email Address [keyparty@frack.nl]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/maxwell/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'NL'
stateOrProvinceName   :PRINTABLE:'Friesland'
localityName          :PRINTABLE:'Leeuwarden'
organizationName      :PRINTABLE:'Frack'
commonName            :PRINTABLE:'maxwell'
emailAddress          :IA5STRING:'keyparty@frack.nl'
Certificate is to be certified until May 11 23:29:00 2022 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
root@Maxwell:/etc/openvpn/maxwell#

Zoals te zien is op (bijna) alle vragen het standaard antwoord voldoende. De Common-Name van het certificaat is hier aangepast naar de hostname van de machine, maar dit is niet vereist.

Nieuwe bestanden in de keys directory:

  • dh2048.pem – Diffie Hellman paramters (uitermate grote priemgetallen, een van de fundamenten van RSA)
  • server.crt – Het publieke certificaat van de OpenVPN server. Dit is informatie die nodig is voor clients om te verifieren dat de server gecertificeerd is door de CA.
  • server.csr – Dit is het zogeheten Certificate Signing Request, ofwel het bestand waar de certificate-server het certificaat vanaf creert. In configuraties waar de CA losstaat van de server, wordt dit document door de aanvrager gestuurd aan de CA. Dit bestand is verder niet belangrijk, en ook niet geheim.
  • server.key – De prive-sleutel van de server. Dit bestand is alleen nodig op de OpenVPN-server, en dient geheim te blijven.

Client certificaat

Wanneer het server certificaat aangemaakt is, is het tijd om voor de verschillende clients de certificaten te maken. Voor deze handleiding maken we certificaten aan voor 2 gebruikers, Bob en Sarah.

./build-key bob
./build-key sarah

Dit levert het volgende resultaat (de uitvoer is van slechts 1 certificaat, om het een beetje kort te houden):

root@Maxwell:/etc/openvpn/maxwell# ./build-key bob
Generating a 2048 bit RSA private key
..........................................+++
...........................................................
.........................................................+++
writing new private key to 'bob.key'
-----
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.
-----
Country Name (2 letter code) [NL]:
State or Province Name (full name) [Friesland]:
Locality Name (eg, city) [Leeuwarden]:
Organization Name (eg, company) [Frack]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [bob]:
Name []:
Email Address [keyparty@frack.nl]:bob@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/maxwell/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'NL'
stateOrProvinceName   :PRINTABLE:'Friesland'
localityName          :PRINTABLE:'Leeuwarden'
organizationName      :PRINTABLE:'Frack'
commonName            :PRINTABLE:'bob'
emailAddress          :IA5STRING:'bob@example.com'
Certificate is to be certified until May 11 23:40:54 2022 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
root@Maxwell:/etc/openvpn/maxwell# 

Mocht Bob buiten Leeuwarden wonen, dan is dit direct in het certificaat op te geven. Zo ook Bob's emailadres en dergelijke. Dit is niet bijzonder belangrijk, maar wanneer er veel certificaten worden uitgegeven is het handig om tenminste 1 uniek identificerend stukje informatie in een certificaat te hebben.

Hierna hebben we de volgende nieuwe bestanden in onze keys directory:

  • bob.crt – Dit is Bob's publieke certificaat. Hiermee kunnen anderen verifieren dat de communicatie die ze ontvangen inderdaad van Bob afkomstig is.
  • bob.csr – net als voor de server is dit Bob's officiele verzoek voor een certificaat.
  • bob.key – Bob's prive-sleutel. Deze gebruikt hij om z'n informatie met de server te versleutelen, en dient hij strikt geheim te houden.
  • Eenzelfde set bestanden voor Sarah, met dezelfde betekenis.

Intrekken van certificaten

Om een client certificaat in te trekken, weer vanuit de huidige directory:

. ./vars
./revoke-full sarah

Het laden van .vars is van belang wanneer aanpassingen gedaan willen worden na uitloggen en opnieuw inloggen (omdat het intrekken van certificaten iets is dat zelden direct gebeurt).

Een certificaat intrekken geeft dan het volgende resultaat:

root@Maxwell:/etc/openvpn/maxwell# . ./vars 
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/maxwell/keys
root@Maxwell:/etc/openvpn/maxwell# ./revoke-full sarah
Using configuration from /etc/openvpn/maxwell/openssl.cnf
Revoking Certificate 03.
Data Base Updated
Using configuration from /etc/openvpn/maxwell/openssl.cnf
sarah.crt: /C=NL/ST=Friesland/L=Leeuwarden/O=Frack/CN=sarah/emailAddress=sarah@example.com
error 23 at 0 depth lookup:certificate revoked
root@Maxwell:/etc/openvpn/maxwell# 

Bundelen van client-benodigdheden

Om makkelijk de certificaten en sleutels benodigd voor Bob en Sarah uit te geven kunnen we ze inpakken en daarna via een bestaand veilig kanaal versturen. Het is mogelijk om dit hele proces te doorlopen zonder bestaande veilige communicatie, maar dat is niet voor deze handleiding.

cd keys
tar -cf /root/bob.tar bob.crt bob.key ca.crt ta.key
tar -cf /root/sarah.tar sarah.crt sarah.key ca.crt ta.key

Server-configuratie

Nu de CA opgezet is en we certificaten hebben gemaakt voor zowel de server als de verschillende gebruikers, is het grootste deel van het werk gedaan (en extra client-certificaten aanmaken is kinderspel). Het is tijd om te OpenVPN server zelf in te richten. Een voorbeeldconfiguratie om een en ander uit te leggen:

# TLS Server configuration
tls-server
tls-auth maxwell/keys/ta.key 0
dev tun
 
# Certificates and private key
ca maxwell/keys/ca.crt
cert maxwell/keys/server.crt
key maxwell/keys/server.key
 
# Diffie Hellman parameters
dh maxwell/keys/dh2048.pem
 
# Keepalive and persistence
keepalive 10 120
persist-key
persist-tun
 
# Local security
chroot /var/openvpn
user nobody
group nogroup
 
# Statuslog and logging verbosity
status maxwell.log
verb 3
 
# Enable compression on the VPN link.
comp-lzo

De volgorde van de items in de configuratie zijn niet van belang, maar zijn hier gegroepeerd en geschikt op belangrijkheid.

  • We beginnen door aan te geven dat onze deze configuratie een server betreft, specifiek eentje met tls-auth' ingeschakeld. Hierbij hoort uiteraard het bestand met het gedeelde geheim. Verder geven we aan wat voor 'device' OpenVPN moet emuleren. In dit geval kiezen we voor een tunnel; dit plaatst gebruikers en server in losse netwerken met daartussen routing.
  • De CA en server certificaten en de prive-sleutel van de server
  • Diffie Hellman sleutel-communicatie paramters
  • Instellingen om de VPN verbinding opnieuw te maken wanneer deze wegvalt, en om sleutels in geheugen te houden. Dit laatste is vooral relevant wanneer de prive-sleutels voorzien zijn van wachtwoord-beveiliging.
  • Een stukje lokale beveiliging door het VPN proces niet als root te laten draaien, en te beperken tot een aparte map. Zie hieronder.
  • Een logfile om belangrijke informatie ter foutoplossing te bewaren. In deze configuratie wordt de logfile gemaakt in de lokale directory. Dit kan ook aangepast naar een bestand in bijvoorbeeld /var/log/openvpn/ (zorg wel dat deze directory dan bestaat).
  • Inschakelen van compressie, dit zorgt er in de meeste gevallen voor dat de extra ruimte die door OpenVPN nodig is (voor encapsulatie) weer wordt teruggewonnen. Deze instelling moet op zowel server and client gedaan worden!

Dit bestand als .conf-bestand opslaan in de /etc/openvpn/ directory en daarna kan OpenVPN herstart worden.

Server chroot directory

Het chroot'en van OpenVPN kan alleen slagen wanneer de genoemde chroot directory bestaat. Standaard is deze niet aangemaakt, dus als root user moet deze aangemaakt worden:

mkdir /var/openvpn

(Her)starten OpenVPN service

Om de configuratie te (her)laden en zowel server- als client-verbinding opnieuw te initialiseren voeren we het volgende uit:

service openvpn restart

Dit geeft op onze voorbeeldserver de volgende output:

root@Maxwell:/etc/openvpn# service openvpn restart
Stopping virtual private network daemon:.
Starting virtual private network daemon: maxwell.
root@Maxwell:/etc/openvpn# 

Al het internet door de VPN server routen

Het is mogelijk om vanaf de server routes te geven aan de gebruikers. Deze gebruiken dan (mits hun eigen configuratie dit niet uitschakelt of negeert) de verbinding naar de server voor al hun internet. Dit betekent dat de gebruikers in hun lokale netwerk alleen versleutelde gegevens wegsturen, en daar beschermd zijn tegen luistervinken.

In de OpenVPN server configuratie wordt de volgende regel toegevoegd:

# Route all internet through OpenVPN server
push "redirect-gateway def1"
# Ensure client has functional DNS (provider DNS will likely fail)
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

Om routing naar het internet toe te staan moet op de server IP Forwarding aangezet worden. Dit kan tijdelijk gedaan worden door het volgende commando:

echo 1 > /proc/sys/net/ipv4/ip_forward

Om dit permanent te maken moet dit ingesteld worden in /etc/sysctl.conf. Vaak staat de benodigde regel hier al in, maar is deze uitgeschakeld. Haal het commentaar weg en klaar ben je.

iptables configuratie

De volgende regels zijn nodig om de OpenVPN server te gebruiken als #gateway of om het #lokale netwerk beschikbaar te maken (als root):

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s 10.0.32.0/24 -j ACCEPT    
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s 10.0.32.0/24 -o eth0 -j MASQUERADE

Het genoemde netwerk (10.0.32.0/24) is het netwerk waaruit de clients hun IP's krijgen toegewezen. De genoemde adapter (eth0) is vanuit het VPN gezien de externe adapter. Dat wil zeggen, de adapter van waaruit het VPN verkeer op het lokale netwerk uitkomt.

Iets meer detail aangaande de externe adapter: Dit is de adapter die de OpenVPN server gebruikt om het IP op te zoeken. Dit is afhankelijk van de route tabel van de OpenVPN server, maar doorgaans zal alles op eth0 uitkomen.

IP's toewijzen aan clients en lokaal netwerk beschikbaar maken

Buiten het gehele internet kan het interessant zijn om (alleen) het lokale netwerk waar de VPN server staat beschikbaar te maken. Op deze manier is het mogelijk om vanaf afstand "in" het netwerk aan de verre kant te komen. De configuratie hiervan is alweer geheel aan de server-kant, en hoeft niet in de client-configuratie te komen:

# Port forwarding etc
server 10.0.32.0 255.255.255.0
ifconfig-pool-persist maxwell/ipp.txt
push "route 192.168.99.0 255.255.255.0"

Bovenstaande doet twee zaken:

  • Voor elke verbonden gebruiker is er een point-to-point verbinding waar IPs uit de 10.0.32.0/24-range gebruikt worden. Daarbij worden deze IPs hergebruikt voor dezelfde clients (de persist regel).
  • Het netwerk 192.168.99.0/24 wordt door de clients geroute naar de OpenVPN server. Alle verzoeken voor dat netwerk zullen dus niet lokaal verwerkt worden, maar vanuit het netwerk van de server.

Als we met deze configuratie de server herstarten ziet deze er zo uit:

root@Maxwell:/etc/openvpn# service openvpn restart
Stopping virtual private network daemon: maxwell.
Starting virtual private network daemon: maxwell.
root@Maxwell:/etc/openvpn# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.32.2       0.0.0.0         255.255.255.255 UH    0      0        0 tun0
10.0.32.0       10.0.32.2       255.255.255.0   UG    0      0        0 tun0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
192.168.56.0    0.0.0.0         255.255.255.0   U     0      0        0 eth2
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth1
root@Maxwell:/etc/openvpn# 

Zoals te zien wordt voor de bestaande server een tun0 device aangemaakt dat een lokaal IP uit de 10.0.32.0/24-range kent. Het 192.168.99.0/24 netwerk is hier niet te zien, dat bestaat niet, maar straks op de client zal te zien zijn dat dit wel degelijk wordt aangeboden. (192.168.56.0.24 is het lokale netwerk van mijn VirtualBox omgeving)

Het beschikbaar gemaakte netwerk is onbereikbaar

Het kan zijn dat het netwerk dat je zojuist beschikbaar hebt gemaakt, alsnog onbereikbaar is. Kijk hiervoor de volgende zaken na:

  1. De client machine krijgt een route naar het netwerk opgegeven vanaf de OpenVPN server
  2. De OpenVPN server heeft ip_forwarding aan staan (cat /proc/sys/net/ipv4/ip_forwarding)
  3. De machine in het beschikbaar gemaakte netwerk heeft een route terug naar de client.
    Dit laatste is vaak niet het geval wanneer de OpenVPN server niet de gateway is van het lokale netwerk. Om communicatie terug naar de client mogelijk te maken zal op de gateway (waarschijnlijk modem/router) de volgende route moeten worden toegevoegd (op basis van de voorbeeld-informatie): netwerk: 10.250.0.0/24, gateway: 192.168.99.10. Dit gateway IP is het IP-adres van de OpenVPN server in het lokale netwerk.

Client-configuratie

Nu de server geconfigureerd is, en draait, is het tijd om de eerste gebruiker op te zetten en te verbinden. Tijdens het opzetten van de CA hebben we voor de clients twee tar-archieven geamaakt. Hiervan nemen we er een en plaatsen de bestanden hiervan in de (nieuw aangemaakte) directory ~/openvpn:

mkdir -p ~/openvpn/maxwell
tar -xf bob.tar -C ~/openvpn/maxwell
cd ~/openvpn

In deze map maken we vervolgens de client-configuratie aan, die we maxwell.conf zullen noemen:

# Client type
client
dev tun
 
# Remote endpoint and persistence settings
remote 192.168.56.2
resolv-retry infinite
persist-key
persist-tun
 
# Don't bind to local port, drop privileges when VPN established
nobind
user nobody
group nogroup
 
# Verify remote is a server, and provide key details
ns-cert-type server
ca maxwell/ca.crt
cert maxwell/bob.crt
key maxwell/bob.key
tls-auth maxwell/ta.key 1
 
# Enable compression on the VPN link.
comp-lzo
verb 3

Er gebeuren in deze configuratie de volgende dingen (ook hier gelden dezelfde regels over volgorde en groepering als bij de server configuratie):

  • We geven aan dat we een client zijn, en ook hier dat we een tunnel willen aanmaken
  • We vertellen waar de OpenVPN server te vinden is, dit wisselt uiteraard per server ;)
  • We vertellen OpenVPN niet een vaste poort te gebruiken, en na opzetten van de verbinding te privileges te verlagen
  • We controleren of het certificaat van de andere kant van de verbinding werkelijk een server is (dit helpt met het voorkomen van MITM aanvallen), en geven de certificaten en sleutel voor verificatie en encryptie op. We geven hier ook het gedeelde TLS geheim op, maar gebruiken hier de tweede index (1 ipv 0).
  • We schakelen compressie in (en vertellen hoeveel we in de logs te zien willen krijgen)

VPN verbinding inschakelen

Als eerste test starten we de OpenVPN verbinding vanuit een draaiende terminal. Hier is gelijk te zien wat er gebeurt tijdens het verbinden:

sudo openvpn maxwell.conf

Dit geeft de volgende (voorbeeld) output:

elmer@Penrose:~/openvpn$ sudo openvpn maxwell.conf
[sudo] password for elmer: 
Tue May 15 01:05:23 2012 OpenVPN 2.2.1 x86_64-linux-gnu [SSL] [LZO2] [EPOLL] [PKCS11] [eurephia] [MH]
[PF_INET6] [IPv6 payload 20110424-2 (2.2RC2)] built on Mar 30 2012
Tue May 15 01:05:23 2012 NOTE: OpenVPN 2.1 requires '--script-security 2' or higher to call user-defined
scripts or executables
Tue May 15 01:05:23 2012 Control Channel Authentication: using 'maxwell/ta.key' as a OpenVPN static key file
Tue May 15 01:05:23 2012 LZO compression initialized
Tue May 15 01:05:23 2012 NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay
Tue May 15 01:05:23 2012 UDPv4 link local: [undef]
Tue May 15 01:05:23 2012 UDPv4 link remote: [AF_INET]192.168.56.2:1194
Tue May 15 01:05:23 2012 [maxwell] Peer Connection Initiated with [AF_INET]192.168.56.2:1194
Tue May 15 01:05:25 2012 TUN/TAP device tun3 opened
Tue May 15 01:05:25 2012 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
Tue May 15 01:05:25 2012 /sbin/ifconfig tun3 10.0.32.6 pointopoint 10.0.32.5 mtu 1500
Tue May 15 01:05:25 2012 GID set to nogroup
Tue May 15 01:05:25 2012 UID set to nobody
Tue May 15 01:05:25 2012 Initialization Sequence Completed

Dit voegt het volgende device toe aan de netwerkadapters:

root@Penrose:~# ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.0.32.6  P-t-P:10.0.32.5  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:68 errors:0 dropped:0 overruns:0 frame:0
          TX packets:110 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:10259 (10.2 KB)  TX bytes:23415 (23.4 KB)

Te zien is dat er een IP wordt uitgedeeld uit de reeks van de OpenVPN server zelf, en dat dit een Point-to-Point verbinding is.

De volgende (relevante) routes worden toegevoegd aan het systeem, wat zowel het internet als het 'lokale' netwerk van de OpenVPN server beschikbaar maakt:

root@Penrose:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.32.5       128.0.0.0       UG    0      0        0 tun0
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 wlan0
10.0.32.1       10.0.32.5       255.255.255.255 UGH   0      0        0 tun0
10.0.32.5       0.0.0.0         255.255.255.255 UH    0      0        0 tun0
128.0.0.0       10.0.32.5       128.0.0.0       UG    0      0        0 tun0
169.254.0.0     0.0.0.0         255.255.0.0     U     1000   0        0 wlan0
192.168.1.0     0.0.0.0         255.255.255.0   U     2      0        0 wlan0
192.168.56.0    0.0.0.0         255.255.255.0   U     0      0        0 vboxnet0
192.168.99.0    10.0.32.5       255.255.255.0   UG    0      0        0 tun0

Internet gaat nu vanaf de laptop (client), naar de VM (OpenVPN server), en vanaf daar via de shared WLAN adapter naar het internet.

N.B.: Het kan even duren voordat de routing/gateway configuratie goed werkt, een paar ogenblikken geduld is aan te raden.

root@Penrose:~# ping 8.8.8.8 -c4 -I tun0
PING 8.8.8.8 (8.8.8.8) from 10.0.32.6 tun0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_req=1 ttl=52 time=38.1 ms
64 bytes from 8.8.8.8: icmp_req=2 ttl=52 time=34.9 ms
64 bytes from 8.8.8.8: icmp_req=3 ttl=52 time=35.6 ms
64 bytes from 8.8.8.8: icmp_req=4 ttl=52 time=34.7 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 34.707/35.872/38.146/1.376 ms

Success, ping via tun0

Automatisch verbinden

Om de VPN verbinding automatisch te laten beginnen wanneer de computer opstart (bijvoorbeeld in geval van een server die op een veilige manier een database-server op een ander netwerk moet raadplegen), is het mogelijk om de configuratie in de OpenVPN map te plaatsen. De volgende stappen dienen uitgevoerd te worden door de gebruiker root:

  • Plaats de certificaten en sleutels voor deze VPN verbinding in de directory /etc/openvpn/maxwell/
  • Maak deze map en bestanden leesbaar alleen voor de gebruiker root
  • Plaats de configuratie in /etc/openvpn/maxwell.conf
  • Herstart OpenVPN en de client wordt automatisch gestart
root@Penrose:~# cp -a openvpn/maxwell /etc/openvpn/maxwell
root@Penrose:~# cp openvpn/maxwell.conf /etc/openvpn/
root@Penrose:~# cd /etc/openvpn/
root@Penrose:/etc/openvpn# chmod 600 maxwell/*
root@Penrose:/etc/openvpn# chmod 700 maxwell/
root@Penrose:/etc/openvpn# service openvpn restart
 * Stopping virtual private network daemon(s)...
   *   No VPN is running.
 * Starting virtual private network daemon(s)...
   *   Autostarting VPN 'maxwell'
root@Penrose:/etc/openvpn#

Handgestart vpn-script

Het volgende script gaat er vanuit dat alle OpenVPN client configuraties in de map .openvpn in de home-directory van de gebruiker staan. Bovenaan worden twee variabelen ingevuld die per script anders zijn, verder is dit startup script voor een groot aantal VPN verbindingen herbruikbaar.

In de map ~/.openvpn/ plaatsen we eerst het volgende script tunnel_builder.sh:

#!/bin/bash
#
# Generic OpenVPN Tunnel builder
# (c) Edsger de Looff 2012 - some improvements by Elmer de Looff
 
# PID-File location and contents, and the VPN command to run
PIDFILE="/var/run/openvpn_${CONFIG_FILE}.pid"
PID=$(cat $PIDFILE 2>/dev/null)
VPN_COMMAND="/usr/sbin/openvpn --daemon --cd ${HOME}/.openvpn/ --config ${CONFIG_FILE} --writepid ${PIDFILE}"
VPN_NAME="${VPN_NAME-VPN '${CONFIG_FILE}'}"
 
case $1 in
  start)
    if [ "${PID}" ]; then
      echo "ERROR - This tunnel is already running!"
      exit 1
    else
      sudo ${VPN_COMMAND}
      echo "Started OpenVPN tunnel ${VPN_NAME}"
    fi
  ;;
  stop)
    if [ "${PID}" ]; then
      echo "Killing OpenVPN tunnel ${VPN_NAME}"
      sudo kill ${PID} && sudo rm ${PIDFILE}
    else
      echo "ERROR - The tunnel is not running!"
      exit 1
    fi
  ;;
  restart)
    $0 stop
    sleep 1
    $0 start
  ;;
  status)
    if [ "${PID}" ]; then
      echo "OpenVPN tunnel to ${VPN_NAME}..  [Connected]"
    else
      echo "OpenVPN tunnel to ${VPN_NAME}..  [Disconnected]"
    fi
  ;;
  *)
    echo "Usage: $0 { start | stop | restart | status }"
  ;;
esac

Hierna kunnen OpenVPN beheer-scripts worden geplaatst in de bin directory van onze homedir. Zo'n beheer-script ziet er als volgt uit:

#!/bin/bash
 
# Configuration file to use, this should be in ~/.openvpn/
CONFIG_FILE="maxwell.conf"
 
# Name of the VPN destination, for status printing purposes
VPN_NAME="Maxwell"
 
# Run Tunnel Builder script with above configuration
. ~/.openvpn/tunnel_builder.sh

Wanneer dit script wordt opgeslagen als /home/elmer/bin/vpn_maxwell (en de bin directory in je homedir toegevoegd is aan je PATH en de file executable is), dan is de VPN-verbinding simpel beheerbaar:

vpn_maxwell status|start|stop|restart

Ter voorbeeld:

elmer@Penrose:~$ vpn_maxwell status
OpenVPN tunnel starter to Maxwell..  [Disconnected]
elmer@Penrose:~$ vpn_maxwell start
[sudo] password for elmer: 
Started OpenVPN tunnel
elmer@Penrose:~$ vpn_maxwell status
OpenVPN tunnel starter to Maxwell..  [Connected]
elmer@Penrose:~$ 

Op deze wijze is eenvoudig een ruim aantal VPN verbindingen te beheren en selectief met een of meer VPNs te verbinden. Aanmaken van een beheer-script voor een tweede verbinding is een kwestie van een kopie maken van een bestaand script en twee variabelen aanpassen.

OpenVPN via network-manager

Ubuntu, Mint en enkele andere populaire linux-distributies voor de desktop worden geleverd met Gnome Network-Manager. Dit is een tool die voor een groot deel het netwerk-beheer bij de gebruiker uit handen neemt, en dit integreert in te grafische omgeving. OpenVPN verbindingen kunnen hier ook mee beheert worden, mits we daarvoor het juiste pakket software installeren:

sudo apt-get install network-manager-openvpn

Hierna is het installeren van een VPN verbinding kinderspel, aangenomen dat we het configuratiebestand uit de #Client-configuratie bij de hand hebben:

Naderhand is het VPN configuratiebestand niet meer nodig voor Network-Manager. De certificaten en sleutels moeten echter in dezelfde directory blijven staan wil de VPN verbinding opnieuw opgezet kunnen worden. Wanneer deze toch verhuist moeten worden, dient de VPN configuratie in Network-Manger te worden aangepast. Deze optie is de vinden in het venster bij stap 1.

VPN's afhankelijk van de situatie inschakelen

nmcli

Afbeelding Anoniem.png Fludizz
Fludizz Rol: deelnemer Deskundig met: GL-Inet, Glasvezel lassen, Iptables, Linux, Netwerken, Nftables, OpenVPN, Python, RaspberryPi, Software Beginnend met: ENC28J60 Werkt aan: Geen projecten :(

connect met VPN naar huis toe, dus als

Afbeelding Anoniem.png Fludizz
Fludizz Rol: deelnemer Deskundig met: GL-Inet, Glasvezel lassen, Iptables, Linux, Netwerken, Nftables, OpenVPN, Python, RaspberryPi, Software Beginnend met: ENC28J60 Werkt aan: Geen projecten :(

thuis is hoeft de VPN niet aan logischerwijs. Network-Manager levert hier geen opties voor vanuit de GUI. Gelukkig komt Network-Manager met een commandline tool nmcli. Deze tool is bedoelt voor powerusers en scripting, als uitbreiding op de GUI. Verder heeft Network-Manager een "on connect" getriggerde map beschikbaar, alle scripts die hier staan worden op volgorde uitgevoerd: /etc/NetworkManager/dispatcher.d/

Dit is te misbruiken door nmcli in een script te verwerken en in die map te zetten. nmcli kan werken met behulp van network 'uuid', deze kan je opvragen voor alle geconfigureerde netwerken met het commando nmcli con. In deze lijst zoek je je eigen (vertrouwde) UUID's op en de UUID van je VPN verbinding. Als je deze vervolgens in het onderstaande script verwerkt, en dat script opslaat als /etc/NetworkManager/dispatcher.d/20autovpn.sh connect hij automatisch indien hij op onbekende netwerken verbonden is:

#!/bin/sh
# This script can be placed in your network-manager dispatcher to autostart VPN.
 
# The wlan UUID of your home connection...
HOMEUUID=abcd-1234-bcda
# A possible alternative wlan UUID for your home in case you have more
ALTUUID=abcd-4567-bcda
# The UUID for your VPN connection
VPNUUID=abcd-0987-dcba
 
# Your home network's broadcast address. This works for me but you might want to pick
# a different parameter shown in `nmcli dev list` (DHCP[4] options)
HOMEBRDCST=192.168.123.255
 
 
HOMEACT=`/usr/bin/nmcli con status | /bin/grep -c $HOMEUUID`
ALTACT=`/usr/bin/nmcli con status | /bin/grep -c $ALTUUID`
VPNACT=`/usr/bin/nmcli con status | /bin/grep -c $VPNUUID`
CURBRDCST=`/usr/bin/nmcli dev list iface eth0 | /bin/grep -c $HOMEBRDCST`
 
if [ $HOMEACT = '0' ] && [ $ALTACT = '0' ] && [ $VPNACT = '0' ] && [ $CURBRDCST = '0' ]
then
  /usr/bin/nmcli con up uuid $VPNUUID
fi