OpenVPN


Giacomo Vercesi
1vercesig@gmail.com


Perchè usare una VPN?

  • Per connettersi a internet in modo sicuro
    • Permette di evitare l'intercettazione di dati su connessioni poco sicure (es. WiFi Pubbliche)
    • Permette la connessione su tutte le porte anche su reti con firewall restrittivi
  • Esporre tutte le risorse di una rete remota (es. ufficio) in modo efficente
    • L'autenticazione alla VPN puo essere piu sicura rispetto ad altre implementazioni
  • Per creare una connessione sicura tra due server
  • Per esporre tutte le porte di un server in modo facile pur mantendo un livello di sicurezza alto

Progetto opensource iniziato nel 2001 per creare un'alternativa a IPsec che fosse affidabile e che offrisse protocolli di crittografia robusti. Utilizza come backend crittografico OpenSSL, è estendibile tramite plugin e script e permette il tunnelling sia in Layer 2 che in Layer 3
OpenVPN nasce come software molto flessibile per la creazione di VPN. Infatti se andiamo su https://openvpn.net/man.html troviamo questo:
openvpn [ --askpass [file] ] [ --auth-nocache ] [ --auth-retry type ] [ --auth-user-pass-verify script ] [ --auth-user-pass up ] [ --auth alg ] [ --bcast-buffers n ] [ --ca file ] [ --ccd-exclusive ] [ --cd dir ] [ --cert file ] [ --chroot dir ] [ --cipher alg ] [ --client-cert-not-required ] [ --client-config-dir dir ] [ --client-connect script ] [ --client-disconnect ] [ --client-to-client ] [ --client ] [ --comp-lzo ] [ --comp-noadapt ] [ --config file ] [ --connect-freq n sec ] [ --connect-retry n ] [ --crl-verify crl ] [ --cryptoapicert select-string ] [ --daemon [progname] ] [ --dev-node node ] [ --dev-type device-type ] [ --dev tunX | tapX | null ] [ --dev tunX | tapX ] [ --dh file ] [ --dhcp-option type [parm] ] [ --dhcp-release ] [ --dhcp-renew ] [ --disable-occ ] [ --disable ] [ --down-pre ] [ --down cmd ] [ --duplicate-cn ] [ --echo [parms...] ] [ --engine [engine-name] ] [ --explicit-exit-notify [n] ] [ --fast-io ] [ --float ] [ --fragment max ] [ --genkey ] [ --group group ] [ --hand-window n ] [ --hash-size r v ] [ --help ] [ --http-proxy-option type [parm] ] [ --http-proxy-retry ] [ --http-proxy-timeout n ] [ --http-proxy server port [authfile] [auth-method] ] [ --ifconfig-noexec ] [ --ifconfig-nowarn ] [ --ifconfig-pool-linear ] [ --ifconfig-pool-persist file [seconds] ] [ --ifconfig-pool start-IP end-IP [netmask] ] [ --ifconfig-push local remote-netmask ] [ --ifconfig l rn ] [ --inactive n ] [ --inetd [wait|nowait] [progname] ] [ --ip-win32 method ] [ --ipchange cmd ] [ --iroute network [netmask] ] [ --keepalive n m ] [ --key-method m ] [ --key file ] [ --keysize n ] [ --learn-address cmd ] [ --link-mtu n ] [ --local host ] [ --log-append file ] [ --log file ] [ --suppress-timestamps ] [ --lport port ] [ --management-hold ] [ --management-log-cache n ] [ --management-query-passwords ] [ --management IP port [pw-file] ] [ --max-clients n ] [ --max-routes-per-client n ] [ --mktun ] [ --mlock ] [ --mode m ] [ --mssfix max ] [ --mtu-disc type ] [ --mtu-test ] [ --mute-replay-warnings ] [ --mute n ] [ --nice n ] [ --no-iv ] [ --no-replay ] [ --nobind ] [ --ns-cert-type client|server ] [ --passtos ] [ --pause-exit ] [ --persist-key ] [ --persist-local-ip ] [ --persist-remote-ip ] [ --persist-tun ] [ --ping-exit n ] [ --ping-restart n ] [ --ping-timer-rem ] [ --ping n ] [ --pkcs12 file ] [ --plugin module-pathname init-string ] [ --port port ] [ --proto p ] [ --pull ] [ --push-reset ] [ --push "option" ] [ --rcvbuf size ] [ --redirect-gateway ["local"] ["def1"] ] [ --remap-usr1 signal ] [ --remote-random ] [ --remote host [port] ] [ --reneg-bytes n ] [ --reneg-pkts n ] [ --reneg-sec n ] [ --replay-persist file ] [ --replay-window n [t] ] [ --resolv-retry n ] [ --rmtun ] [ --route-delay [n] [w] ] [ --route-gateway gw ] [ --route-method m ] [ --route-noexec ] [ --route-up cmd ] [ --route network [netmask] [gateway] [metric] ] [ --rport port ] [ --secret file [direction] ] [ --secret file ] [ --server-bridge gateway netmask pool-start-IP pool-end-IP ] [ --server network netmask ] [ --service exit-event [0|1] ] [ --setenv name value ] [ --shaper n ] [ --show-adapters ] [ --show-ciphers ] [ --show-digests ] [ --show-engines ] [ --show-net-up ] [ --show-net ] [ --show-tls ] [ --show-valid-subnets ] [ --single-session ] [ --sndbuf size ] [ --socks-proxy-retry ] [ --socks-proxy server [port] ] [ --status file [n] ] [ --status-version n ] [ --syslog [progname] ] [ --tap-sleep n ] [ --tcp-queue-limit n ] [ --test-crypto ] [ --tls-auth file [direction] ] [ --tls-cipher l ] [ --tls-client ] [ --tls-exit ] [ --tls-remote x509name ] [ --tls-server ] [ --tls-timeout n ] [ --tls-verify cmd ] [ --tmp-dir dir ] [ --tran-window n ] [ --tun-ipv6 ] [ --tun-mtu-extra n ] [ --tun-mtu n ] [ --txqueuelen n ] [ --up-delay ] [ --up-restart ] [ --up cmd ] [ --user user ] [ --username-as-common-name ] [ --verb n ] [ --writepid file ]
#OK rallentiamo un secondo

OpenVPN config-Fu

Tutti i parametri di OpenVPN possono essere passati tramite file di configurazione omettendo le '--'.
Un file di configurazione minimale (e poco sicura!) lato server può essere qualcosa di simile a questo:

dev tun
proto udp
server 10.8.0.0 255.255.255.0
secret secret.key
						
Mentre per il client:

dev tun
proto udp
client
remote example.org
secret secret.key
						
I file di configurazione sono passati a OpenVPN con l'opzione --config

openvpn --config client.conf
						

dev

Permette di scegliere il tipo di dispositivo da utilizzare per la trasmissione dei dati

dev tun|tap|tunX|tapX
							
TUN/TAP è il nome di una tipologia di interfacce virtuali utlizzate da OpenVPN, entrambe appaiono ai programmi come un'interfaccia di rete, tuttavia ci sono nette differenze tra di esse.
Di default openvpn crea l'interfaccia dinamicamente se si usa "tun" o "tap" come parametro, tuttavia si può creare un'interfaccia persistente con il comando:

openvpn --mktun --dev tun0
							

Layers Modello OSI

TAP

TAP viene utilizzato con il layer 2, quindi si comporta come una vera e propia scheda di rete.
Pro:
  • Permette alcune feature più particolari rispetto a TUN (es. messaggi broadcast, protocolli non-IP, bridging)
  • è un'interfaccia di rete "full-fledged"
Contro:
  • Overhead maggiore rispetto a TUN

TUN

TUN invece opera in layer 3 e permette il transito di pacchetti IPV4/6
Pro:
  • Ha un overhead minore dato che non deve mandare frame ethernet ma pacchetti IP
  • Mantiene comunque le possibilità di routing con iptables
  • Utilizzato nella maggior parte dei casi a meno di condizioni particolari
Contro:
  • Vedi vantaggi TUN

Proto

Proto specifica il protocollo da utilizzare per la connessione

proto udp|tcp-server|tcp-client|udp6|tcp6
							
  • TCP
    • Connessione di tipo stateful
    • Permette di utilizzare OpenVPN in un tunnel SSH
    • Consente di condividere la porta con altre applicazioni
    • Comporta enormi ritardi se la rete non è stabile (Vedi qui)
  • UDP
    • Connessione Stateless, quindi con meno overhead
    • Performa meglio di TCP in caso di connessioni poco stabili

Server/Remote

  • server: Crea un pool di indirizzi ip da assegnare ai client che si connettono
    
    server 192.168.2.0 255.255.255.0
    								
  • remote: Permette di connettersi ad un server OpenVPN, più di un remote può essere messo per avere fallback in caso di connessione fallita
    
    remote 198.51.100.99
    remote pippo.example.org
    								

Secret

Specifica la chiave condivisa da utilizzare per cifrare la connessione

La chiave può essere generata utilizzando il comando


openvpn --genkey --secret secret.key
							

NB: La configurazione con chiave precondivisa è scosigliabile per motivi di sicurezza, tuttavia bisogna sempre utilizzare il buon senso e considerare le necessità specifiche della situazione

#Altre opzioni utili

Push

Push permette di inviare impostazioni ai client che si connettono, in questo modo si possono colmunicare informazioni su:

  • rotte
  • ping di keepalive
  • se utilizzare o meno la compressione

N.B.: i client che si connettono devono avere l'opzione --pull(o --client) per ricevere le configurazioni tramite push

Cosa sono le rotte?

Esempio


push "route 192.168.0.0 255.255.255.0 10.7.0.1"
						

redirect-gateway/comp-lzo

  • redirect-gateway: è una direttiva che redirige tutto il traffico sulla vpn, questo lo fa in 3 passi:
    1. creare una rotta statica per il server remoto al gateway di default
    2. cancellare la rotta al default gateway
    3. mettere l'ip del server vpn come gateway di default
  • comp-lzo: abilita la compressione per risparmiare banda aggiungendo dell'overhead e sacrificando un po' di RAM e CPU (tipo 0.1%)
#OpenVPN con Autenticazione a Chiave Pubblica

Perché utilizzare l'autenticazione con certificato?

  • È un sistema più robusto dal punto di vista della sicurezza
  • Ogni utente è identificato da un certificato
  • È possibile revocare i certificati individualmente
  • Si possono creare delle CA intermedie

Come funziona una PKI?

Creare una PKI con Easy-Rsa

EasyRSA era una collezione di script sviluppata di pari passo a OpenVPN per facilitare la creazione di una PKI senza dover approfondire troppo le propie competenze né negli internals di OpenSSL né nello standard X.509

EasyRSA 3 è la versione più recente nella quale i vari script sono stati riuniti in un unico script che funziona con comandi. Per esempio un comando che appare in molte documentazioni è


./build-ca
								

Che nella nuova versione si traduce in:


./easyrsa build-ca
									

EasyRSA Quickstart

Sfortunatamente i pacchetti easyrsa di molte distro linux sono fermi alla versione 2.2.2 (di 3 anni fa).

Git to the rescue!
Cloniamo la repo di easyrsa con il comando

git clone https://github.com/OpenVPN/easy-rsa.git
cd easy-rsa/easyrsa3
								

N.B.: In alcune slide si userà ... per indicare la cartella contenente lo script easyrsa

Configurare una PKI, Parte 1

Prima di tutto dobbiamo inizializzare la PKI con il comando init-pki


./easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/Giacomo/easy-rsa/easyrsa3/pki
								

Creiamo un certificato di root con build-ca


./easyrsa build-ca

Generating a 2048 bit RSA private key
writing new private key to '.../pki/private/ca.key.mAWiQlaAWe'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Common Name (eg: your user) [Easy-RSA CA]:CA_test
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/home/Giacomo/easy-rsa/easyrsa3/pki/ca.crt
								
N.B: build-ca creerà un file private/ca.key, quando si è finiti di creare i certificati è consigliabile riporre il file in un storage sicuro (es. chiavetta)

Configurare una PKI, Parte 2

Continuiamo creando un certificato per il server


./easyrsa build-server-full server

Generating a 2048 bit RSA private key
writing new private key to '.../pki/private/server.key.56TeNVLfcg'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Enter pass phrase for /home/Giacomo/easy-rsa/easyrsa3/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :T61STRING:'server'
Certificate is to be certified until Apr 17 13:26:12 2026 GMT (3650 days)
								
Analogamente usiamo ./easyrsa build-client-full client per creare un certificato per il server

Concludiamo creando i parametri per lo scambio di chiavi Diffie-Helman


./easyrsa gen-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...
DH parameters of size 2048 created at /home/Giacomo/easy-rsa/easyrsa3/pki/dh.pem
								

Dove metto cosa?


pki
|-- ca.crt
|-- dh.pem
|-- issued
|   |-- client.crt
|   `-- server.crt
`-- private
    |-- ca.key
    |-- client.key
    `-- server.key
						
  • ca.crt può essere dato a chiunque dato che serve per verificare la catena di certificati (serve sia al server che al client)
  • client.key, client.crt vanno dati al client (reminder: ogni client ha bisogno del propio certificato!)
  • server.key, server.crt, dh.pem servono al server
  • ca.key deve essere riposto al sicuro

Configurazione con certificati

Per utilizzare l'autenticazione con certificati servono cambiamenti minimi al file di configurazione.
Al lato server:

ca ca.crt
cert server.crt
key server.key
dh dh.pem
							
Mentre al lato client:

ca ca.crt
cert client.crt
key client.key
							

Redirigere tutto il traffico nella VPN

Potrebbe essere comodo redirigere tutto il traffico attraverso la VPN, come nel caso d'utilizzo di una rete poco sicura (es. WiFi Pubbliche).
Per fare ciò occorre apportare un paio di modifiche. Nella configurazione OpenVPN del server c'è da aggiungere

push "redirect-gateway def1"
							
E poi da shell

# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -I FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
# iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# iptables -t nat -I POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
							

Bridging di OpenVPN con la rete di casa

Creiamo un'interfaccia tap persistente con


openvpn --mktun --dev tap0
							

e settiamo dev tap0 nella configurazione di openvpn e procediamo alla connessione

infine creiamo il bridge e lo connettiamo all'interfaccia eth0


ip link add name br0 type bridge
ip link set br0 up
ip link set eth0 master br0
ip link set tap0 master br0
							

nell'esempio si usa ip tuttavia esistono altre utility come brctl e ifconfig per creare bridge.

Fonti e link utili



Personal Computer, Exploded 5.svg by Gustavb under cc-by 2.5
OSA Icon Library used under cc-by-sa 3.0

Grazie per l'attenzione!

Queste slides sono sotto licenza Creative Commons Attribution-ShareAlike 3.0 Unported http://creativecommons.org/licenses/by-sa/3.0/

https://www.poul.org/