OpenVpn: installazione e configurazione in modalità bridge

Quest’articolo, per fruibilità, l’ho diviso nelle seguenti parti:

L’intera guida è orientata verso un S.O. Debian e Debian-like.
Ho impiegato tre giorni per scrivere questa guida, il motivo per cui l’ho scritta e che in internet si trovano tantissime guide sull’argomento, ma nessuna specifica che spiega per bene come integrare il servizio openvpn, configurato come bridge, con il demone dhcp.
Inoltre molte guide sono obsolete o con informazioni alle volte contraddittorie, per cui spero che possa essere utile a qualcuno. 🙂

Installiamo dei pacchetti necessari

sudo su
apt-get install openvpn bridge-utils

Creare i certificati usando il tool easy-rsa

Eseguite una copia dei file del tool easy-rsa:

mkdir /etc/openvpn/easy-rsa/
cp -R /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/

Settiamo il tool modificando il file vars:

nano /etc/openvpn/easy-rsa/vars

Modificare i campi:

export KEY_COUNTRY=""		# il vostro STATO
export KEY_PROVINCE=""		# la vostra PROVINCIA
export KEY_CITY=""		# la vostra città
export KEY_ORG=""		# la vostra organizzazione
export KEY_EMAIL=""		# il vostro indirizzo di posta elettronica
export KEY_SIZE=2048		# Diffie-Hellman
export KEY_NAME="server"        # X509 Subject Field

Certificati del Server

cd /etc/openvpn/easy-rsa/
source vars
./clean-all			# Cancella tutti i certificati e le chiavi presenti nella cartella /etc/openvpn/easy-rsa/keys
./build-ca			# Crea il certificato di ROOT della Certification Authority
./build-key-server server	# Crea il certificato e la chiave privata del server

Cambiate “server” con il nome che ritenete più opportuno.
All’esecuzione dell’ultimo comando vi verrà chiesto di inserire una password.
1. Inserite una password sicura e accertatevi di non perderla.
2. Alla richiesta di firmare il certificato rispondete di si.
3. Alla richiesta di eseguire il commit rispondete si.

Creiamo i parametri DIFFIE-HELLMAN necessari per il server per la connessione SSL/TSL

./build-dh

Tutti i certificati e le chiavi sono stati generati nella sottocartella “/etc/openvpn/vars/keys”
Se volete attivare il protocollo TSL dovete generare la key corrispondente:

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

Wiki: http://it.wikipedia.org/wiki/Transport_Layer_Security

Mettiamo i file creati nella cartella del programma:

cp server.crt server.key ca.crt dh2048.pem ta.key /etc/openvpn/

Certificati del Client

sudo su
cd /etc/openvpn/vars
source vars
./build-key nome_del_pc_client

I certificati e le chiavi del client vengono sempre creati nella cartella “/etc/openvpn/easy-rsa/keys”

Il file che il client ha bisogno per effettuare la connessione con il server sono:

ca.crt				# Certificato di Root della CA
nome_del_pc_client.crt		# Certificato del client
nome_del_pc_client.key		# Chiave privata del client
ta.key				# TSL key

Copiate questi file all’interno della cartella /etc/openvpn/ del client.

Configurazione del server

tun (routing) o tap (bridging) ?

Il device TAP è una scheda di rete virtuale, mentre il dispositivo TUN è un collegamento IP virtuale da punto a punto (point-to-point).

Vantaggi e svantaggi: http://openvpn.net/index.php/open-source/faq/community-software-general/309-what-is-the-difference-between-bridging-and-routing.html

Se si utilizza bridging Ethernet (tap), è necessario utilizzare i parametri dev tap e server-bridge invece dei parametri dev tun e server.

Gli indirizzi utilizzati nella rete del server e nella rete locale del client non devono fare parte della stessa sottorete, altrimenti vi ritroverete con un loop nel routing dei pacchetti.

Es:

dev tap0
server-bridge

Altrimenti:

dev tun
server

L’istruzione server-bridge senza parametri, implica che il rilascio degli indirizzi ip per i client venga fornito dal demone dhcpd (isc-dhcp-server o dnsmasq) e non da openvpn.

Un motivo valido per cui si vuole usare dhcpd del proprio server piuttosto che openvpn e la possibilità che il proprio server abbia un dns (bind) installato e che il demone dhcp annunci i nuovi pc che si collegano alla rete al dns.

Questo aspetto è poco documentato e le informazioni al riguardo sono contraddittorie:

http://openvpn.net/index.php/open-source/faq/community-software-server/323-i-want-to-set-up-an-ethernet-bridge-on-the-1921681024-subnet-existing-dhcp.html

ATTENZIONE: La direttiva “server” con “dev tap” non deve essere usata come è suggerito dalla faq del sito openvpn, usate “server-bridge”:

  1. senza parametri se volete che sia il vostro server dhcp a rilasciare gli indirizzi
  2. con parametri opportunamente settati se volete che la gestione degli indirizzi ip sia lasciata al server openvpn.
    In questo caso c’è molta documentazione valida a riguardo.

Tuttavia è importante fare notare che il server dhcp non deve fornire ai client vpn il gateway di default della rete in cui è presente il server openvpn, pena la perdita di connessione da parte dei client remoti ad internet.

1. Creare un bridge su server

Configurazione di esempio della mia macchina (file: /etc/network/interfaces)

iface eth0 inet manual
iface eth1 inet manual
iface eth2 inet manual
iface eth3 inet manual
iface eth4 inet manual
iface wlan0 inet manual

auto br0
iface br0 inet static
	bridge_ports eth0 eth1 eth2 eth3 eth4 wlan0 tap0
	address 172.16.0.10
	netmask 255.255.0.0
	network 172.16.0.0
	broadcast 172.16.255.255
	gateway 172.16.0.1
	# dns-* options are implemented by the resolvconf package, if installed
	dns-nameservers 172.16.0.10 172.16.0.1 8.8.8.8
	dns-search example.org

Le istruzioni:

iface br0 inet static
	bridge_ports eth0 eth1 eth2 eth3 eth4 wlan0 tap0

permettono la creazione di un bridge di rete di nome br0, con configurazione di rete statica, di cui fanno parte le periferiche fisiche:

eth0 eth1 eth2 eth3 eth4 wlan0

e la periferica virtuale

tap0

L’indirizzo di rete del bridge e le varie altre impostazioni vengono settate dalle istruzioni successive.

Una volta modificata la vostra configurazione di rete in relazione alle vostre esigenze potete riavviare il servizio di networking col comando:

sudo /etc/init.d/networking restart

2. Configurare il demone dhcpd, nel caso specifico “isc-dhcp-server”.

Questo è un cat parziale del mio file del mio file di configurazione /etc/dhcp/dhcpd.conf del mio server:

...

# Definizioni delle classi

class "local" {
	match pick-first-value (option dhcp-client-identifier, hardware);
}

class "ospiti" {
	match pick-first-value (option dhcp-client-identifier, hardware);
}

class "vpn" {	
	match if (substring(hardware, 1, 2) = 00:FF );
}

# MAC address delle macchine

subclass "ospiti" 1:00:01:AA:BB:CC:DD;
subclass "ospiti" 1:00:02:AA:BB:CC:DD;

subclass "local" 1:00:03:AA:BB:CC:DD;
subclass "local" 1:00:04:AA:BB:CC:DD;

# Definizione della subnet

subnet 172.16.0.0 netmask 255.255.0.0 {
    allow duplicates;
    default-lease-time 86400;
    max-lease-time 86400;				# 24h
    option domain-name "example.org";
    option subnet-mask 255.255.0.0;
    option broadcast-address 172.16.255.255;
    option domain-name-servers 172.16.0.10;
    option ntp-servers 172.16.0.10;

    # Local					172.16.0.50-89
    pool {
	allow members of "local";
	range 172.16.0.50 172.16.0.89;
	option routers 172.16.0.1;		# gateway della rete locale
	ddns-updates on;
    }

    # Ospiti					172.16.10.0/24
    pool {
        allow members of "ospiti";
       	range 172.16.10.1 172.16.10.254;
	default-lease-time 43200;
	max-lease-time 43200;			# 12h
	option routers 172.16.0.1;		# gateway della rete locale
	ddns-updates on;
    }

    # VPN					172.16.20.0/24
    pool {
	allow members of "vpn";
	range 172.16.20.1 172.16.20.254;
	ddns-updates on;
    }
}

Questa è la definizione del mio pool di indirizzi nel mio server.

Per la sottoclasse VPN l’opzione “option routers 172.16.0.10;” è mancante ne è presente nella definizione generale del range:

subnet 172.16.0.0 netmask 255.255.0.0 {
	...

Tanto basta per evitare che venga fornito ai client vpn un gateway che incasini l’instradamento di default dei client vpn verso internet.
Tuttavia è d’obbligo indicare l’opzione “option routers 172.16.0.10;” in tutti gli altri pool della subnet.

Per assicurarsi che tutti i client vpn finiscano nel pool corretto bisogna indicare come regola “allow members of “vpn”;” nel pool e creare una classe con questa regola qui:

class "vpn" {
        match if (substring(hardware, 1, 2) = 00:FF );
}

La regola funziona perché ogni client che si collega tramite openvpn avrà sempre come MAC address iniziale i valori: 00:FF
Tutti gli altri pool definiti nella subnet hanno regole differenti che non coincidono con la regola della classe vpn.

E’ importante accertarsi che nessuno dei client vpn possa finire in un pool di indirizzi in cui è definita la regola “option routers”, sopratutto se in quest’ultima regola è definito il gateway della rete del server vpn.

E’ possibile instradare tutto il traffico del client vpn verso la rete del server, ma in quel caso bisogna specificare come indirizzo ip quello del server vpn. Es:

option routers 172.16.0.10

Gli altri valori del MAC Address dei client vpn varieranno casualmente ad ogni connessione a meno che non si specificano esplicitamente tramite l’istruzione:

lladdr 00:ff:00:00:00:0d

per le macchine linux e nelle proprietà del device tap0 per le macchine windows.
Nelle macchine windows l’istruzione “lladdr 00:ff:00:00:00:0d” non è riconosciuta.

3. Configurazione del servizio OpenVpn

Nella cartella di configurazione del demone openvpn non sono presenti i file di configurazione per cui bisogna metterceli a mano:

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
gzip -d /etc/openvpn/server.conf.gz
rm /etc/openvpn/server.conf.gz

Una configurazione di esempio del file del server.conf è la seguente:

# Quale indirizzo ip dovrebbe rimanere in ascolto OpenVPN?
local 172.16.0.10		# Indirizzo ip del bridge br0

port 1194			# Porta
proto udp			# Protocollo

dev tap0
server-bridge

ca		ca.crt		# Certificato di Root della CA
cert		server.crt	# Certificato del Server
key		server.key	# Chiave privata del Server
dh		dh2048.pem	# Diffie Hellman parameters
tls-auth	ta.key 0	# This file is secret (0 = server)

comp-lzo			# algoritmo di compressione per la connessione
client-to-client
keepalive 10 120

user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log

daemon
verb 3
chroot jail

Anche qui ho omesso i commenti presenti nel file di configurazione di esempio.

Configurazione di un client

Il client ha anche lui bisogno del suo file di configurazione per cui, se non ne avete uno già pronto potete copiare quello di default:

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/

Esempio di configurazione per un client linux.
E’ stata omessa la documentazione presente nel file di configurazione di esempio.

script-security 2

client
dev tap
proto tcp

remote vpn.example.org 1194	# Indirizzo del vostro server vpn

lladdr 00:ff:00:00:00:0d	# Indirizzo MAC del client

resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun

ca ca.crt			# Certificato radice della CA
cert client.crt			# certificato del client
key client.key			# chiave privata del client

ns-cert-type server

tls-auth ta.key 1		# File condiviso con il server (1 = client)
comp-lzo
verb 3

chroot

Per maggiorni informazioni in merito al chroot si può controllare questa pagina della wiki http://it.wikipedia.org/wiki/Chroot

mkdir /etc/openvpn/jail
nano /etc/openvpn/server.conf

Alla fine del file aggiungere l’istruzione:

chroot jail

e salvare.

chroot jail e syslog

Il problema è semplice, alla rotazione giornaliera dei log del sistema il servizio rsyslog viene riavviato dalla macchina facendo perdere la connessione alla socket “/dev/log” da parte del servizio openvpn.
Infatti la socket AF_UNIX “/dev/log” viene terminata e ricreata al riavvio del servizio rsyslog.
Il servizio openvnp, essendo bloccato dentro la cartella “/etc/openvpn/jail” non può più accedere alla socket del demone rsyslog che si torva fuori dalla cartella “jail” (ovvero “/dev/log”).

Per ovviare al problema bisogna creare la cartella dev dentro jail:

mkdir /etc/openvpn/jail/dev

e modificare la configurazione del demone rsyslog creando un nuovo file dentro la cartella “/etc/rsyslog.d” e aggiungere lì la configurazione del nuovo socket per il demone openvpn. Ovvero:

nano /etc/rsyslog.d/openvpn.conf

E aggiungere la seguente istruzione:

$AddUnixListenSocket /etc/openvpn/jail/dev/log

e salvare e riavviare il servizio.

service rsyslog restart

Race condition tra Upstart e Samba se nel pc è presente un interfaccia bridge

Vengo subito al dunque, dopo un recente aggiornamento del pacchetto samba ho cominciato ad avere problemi ad accedere alle mie cartelle condivise sul mio ubuntu server 10.04.
Nella mia macchina è presente un bridge di rete che collega la mia interfaccia ethernet su cavo (eth0) con quella wifi (wlan0):

router <= eth0 (0.0.0.0) => br0 (192.168.1.10) <= wlan0 (0.0.0.0) => altri pc.

Il problema si risolveva se, dopo l’avvio della macchina, riavviavo il servizio samba.

Per trovare l’origine del problema ho controllato i file di log di samba:

[2010/09/17 08:39:56, 0] lib/util_sock.c:938(open_socket_in)
bind failed on port 445 socket_addr = fe80::201:2eff:fe2f:d55%br0.
Error = Cannot assign requested address
[2010/09/17 08:39:56, 0] smbd/server.c:457(smbd_open_one_socket)
smbd_open_once_socket: open_socket_in: Cannot assign requested address
[2010/09/17 08:39:56, 0] lib/util_sock.c:938(open_socket_in)
bind failed on port 139 socket_addr = fe80::201:2eff:fe2f:d55%br0.
Error = Cannot assign requested address
[2010/09/17 08:39:56, 0] smbd/server.c:457(smbd_open_one_socket)
smbd_open_once_socket: open_socket_in: Cannot assign requested address

La mia configurazione di rete di samba è la seguente:

interfaces = 127.0.0.0/8 192.168.1.0/24 br0
bind interfaces only = yes

In pratica samba pubblica le sue sockets nell’interfaccia di rete br0 e loopback.

Il problema si presenta perché upstart non aspetta che il bridge di rete sia attivo prima di avviare il servizio samba. Il bridge impiega circa 15 secondi ad avviarsi, nel mentre samba pubblica le sue sockets solo nelle interfacce di rete attive  in quel momento, essendo l’interfaccia bridge ancora non attiva, samba fallisce la pubblicazione del servizio sul bridge impedendo così l’accesso da un computer remoto.
La conferma mi è stata data dal comando netstat -an.

Prima del riavvio del servizio samba:

tcp 0 0 127.0.0.1:139 0.0.0.0:* LISTEN
...
tcp 0 0 127.0.0.1:445 0.0.0.0:* LISTEN

Dopo il riavvio del servizio samba:

tcp 0 0 127.0.0.1:139 0.0.0.0:* LISTEN
tcp 0 0 192.168.1.10:139 0.0.0.0:* LISTEN
...
tcp 0 0 127.0.0.1:445 0.0.0.0:* LISTEN
tcp 0 0 192.168.1.10:445 0.0.0.0:* LISTEN

La soluzione al problema è modificare lo script di avvio di samba di upstart.
Ovvero:

sudo nano /etc/init/smbd.conf

e cambiare la linea:

start on local-filesystems

in

start on (local-filesystems and net-device-up IFACE=br0)

Ovviamente se la vostra interfaccia bridge ha un nome diverso da br0 cambiatelo opportunamente.

In questo modo obbligherete upstart ad aspettare che il bridge sia attivo prima di avviare il demone samba.

Errori simili posso verificarsi se sulla vostra macchina viene eseguito il demone dhcp3-server configurato per fornire indirizzi ip sull’interfaccia bridge.

Race condiction analogo per dhcpd

(!sic) Ho risolto il problema con il servizio dhcp3 editando il file:

sudo nano /etc/init/rc-sysinit.conf

e cambiando la linea

start on filesystem and net-device-up IFACE=lo

in

start on filesystem and net-device-up IFACE=br0

For more info about this problem see:
https://bugs.launchpad.net/ubuntu/+source/dhcp3/+bug/580319

tftpd-hpa

Problemi anche con lui. il più delle volte si avvia e pubblica le sue socket sull’interfaccia bridge correttamente, tuttavia, sporadicamente fallisce.
Quindi forziamo lo script di avvio, del servizio tftp-hpa, ad attendere la disponibilità del bridge prima di avviare il demone:

nano /etc/init/tftpd-hpa.conf

e cambiare la riga:

start on (filesystem and net-device-up IFACE!=lo)

in

start on (filesystem and net-device-up IFACE=br0)

La condizione IFACE!=lo è sicuramente più furba tra tutte la condizioni di avvio riscontrate nei precedenti file di configurazione (dhcpd e samba), tuttavia non è sufficiente se nella vostra macchina avete più di un interfaccia di rete (es. tunnel ipv6). Il bridge è un interfaccia lenta e il servizio in questione finisce col pubblicare le proprie socket sulle altre interfacce di rete attive ma non sul bridge.

Giacché sono in tema…
Dato che in internet non ho visto molti esempi corretti di configurazioni (per debian) di interfacce bridge, riporto la mia configurazione di rete:

/etc/network/interfaces

auto lo
iface lo inet loopback

iface eth0 inet manual

iface wlan0 inet manual

auto br0
iface br0 inet static
	bridge_ports eth0 wlan0
	address 192.168.1.10
	network 192.168.1.0
	netmask 255.255.255.0
	gateway 192.168.1.1
	broadcast 192.168.1.255

Per esempi di configurazione diversi e più completi vi rimando alla pagina, in inglese, della wiki di debian.