Ipsec su Openwert 14.07
Ipsec (strongswan 5.2.2 su openwrt 14.07) puo` essere configurato per lavorare in due modi: usando un helper in userspace che effettua le operazioni crittografiche, o facendole fare al kernel. La soluzione con l'helper funziona bene e presenta all'utente una interfaccia ipsec0 attraverso la quale passa il traffico (cosa per me molto comoda) ma consente di lavorare soltanto con ESP incapsulato in UDP (il modo tipico in cui si effettua il NAT traversal in IPSEC). Se l'altro endpoint non gradisce questo comportamento, questo metodo non funzionera` e occorrera` usare quello in kernel space.
Ipsec in user space
- Installare i pacchetti ip-full e strongswan-default (metapacchetto che si porta dietro un mucchio di roba)
- Configurare il firewall per lasciare passare da fuori a dentro:
- Porta 500 UDP
- Porta 4500 UDP
- Installare il pacchetto strongswan-mod-kernel-libipsec
- Configurare strongswan come necessario
- /etc/strongswan.conf: Central configuration file
- /etc/ipsec.conf: Tunnel definitions
- /etc/ipsec.secrets: List of preshared keys
- /etc/ipsec.d: Folder for certificates
- Creare nel firewall dell' openwrt una "zona" dedicata alla interfaccia ipsec0, ed applicare in essa le regole di forward in modo che la LAN parli con il remoto (e viceversa se lo vogliamo)
- Verificato che funziona tutto, ricordarsi di abilitare l'avvio automatico di ipsec dall'interfaccia web.
Ipsec in kernal space
Questo e` l'esempio piu` bastardo possibile, perche` richiede che noi ci presentiamo al remoto con degli indirizzi (interni al tunnel) che non sono quelli della nostra LAN, e quindi dobbiamo usare alias e NAT per ottenere questo risultato. Se non avessimo bisogno di fare cio`, il nostro lavoro sarebbe leggermente piu` facile.
- Installare i pacchetti ip-full e strongswan-default (metapacchetto che si porta dietro un mucchio di roba)
- Configurare il firewall per lasciare passare da fuori a dentro sull'interfaccia WAN:
- Porta 500 UDP
- Porta 4500 UDP
- Protocollo ESP
modificare il file /etc/init.d/ipsec in modo che esegua un modprobe authenc prima dello start della vpn altrimenti si incorre in errori come questo: received netlink error: No such file or directory (2) - unable to add SAD entry with SPI 4a40a580
- Configurare strongswan come necessario
- /etc/strongswan.conf: Central configuration file
- /etc/ipsec.conf: Tunnel definitions
- /etc/ipsec.secrets: List of preshared keys
- /etc/ipsec.d: Folder for certificates
- Visto che con questo metodo non esiste una interfaccia ipsec0, occorre fare alcune cose:
Se il tunnel richiede di presentarsi alla rete remota con un IP che non e` su nessuna nostra interfaccia, occorre configurare un alias della interfaccia WAN che abbia questo IP. Per esempio, se la nostra WAN ha un ip pubblico 100.1.2.3, la nostra LAN e` 10.0.0.0/24, e il tunnel richiede (perche` lo dice il possessore dell'altro endpoint) che noi ci presentiamo a loro come 172.21.34.0/24, allora dovremo dare alla nostra interfaccia WAN l'alias 172.21.34.1, per esempio. In openwrt il modo piu` immediato di farlo e` aggiungere un ifconfig eth1:0 172.21.34.1 netmask 255.255.255.0 al file /etc/init.d/ipsec in modo che prima dello start venga creato l'alias sulla interfaccia pubblica.
- Configurare delle regole speciali di nat (o di accept se non vogliamo il nat) nella tabella utente di postrouting in modo che i pacchetti che escono dentro al tunnel (che escono sempre dall'interfaccia wan, come quelli che vanno su internet) siano nattati (o non siano nattati) con regole diverse dal resto dei pacchetti che vanno su internet. Ad esempio queste regole nattano i pacchetti destinati all'altro lato della VPN (192.168.216.0 e 238.0) con un indirizzo ip "speciale" (172.21.34.1) che e` un alias (eth1:0) della interfaccia WAN.:
iptables -t nat -A postrouting_wan_rule -j SNAT -s 172.16.30.0/24 -d 192.168.216.0/24 --to 172.21.34.1 iptables -t nat -A postrouting_wan_rule -j SNAT -s 172.16.30.0/24 -d 192.168.238.0/24 --to 172.21.34.1
- Occorre poi considerare che a meno che non si crei una regola speciale il traffico che esce dal router stesso verra` indirizzato verso il remoto attraversando una regola di MASQUERADE (default in openwrt) che ne alterera` l'indirizzo. Occorre pertanto aggiungere un'altra regola che impedisce che questo accada. Seguendo l'esempio di prima, occorre dire al router che il traffico che esce come 172.21.34.1 (alias del router sulla wan destinato a veicolare il traffico ipsec) non deve essere nattato.
iptables -t nat -A postrouting_wan_rule -j ACCEPT -s 172.21.34.1 -d 192.168.216.0/24 iptables -t nat -A postrouting_wan_rule -j ACCEPT -s 172.21.34.1 -d 192.168.238.0/24
- Verificato che funziona tutto, ricordarsi di abilitare l'avvio automatico di ipsec dall'interfaccia web.
Limitazioni
Il caso del NAT degli indirizzi della LAN presentato nell' esempio in kernel space potrebbe essere affrontato in modo piu` intelligente se non fosse che openwrt ha delle limitazioni. Ad esempio non riesco a fare funzionare (non capisco perche`) il target "NETMAP" che mi verrebbe molto utile per nattare tutta la mia LAN (ad esempio 10.0.0.0/24) sulla rete che vuole vedere il remoto (ad esempio 172.21.34.0/24). Sarebbe sufficiente inserire due regole di NETMAP, cosi`:
iptables -t nat -A postrouting_wan_rule -j NETMAP -s 10.0.0.0/24 -d 192.168.216.0/24 --to 172.21.34.0/24 iptables -t nat -A pretrouting_wan_rule -j NETMAP -s 192.168.216.0/24 -d 172.21.34.0/24 --to 10.0.0.0/24
Ma non funziona. iptables si rifiuta di inserire le regole nella catena. Su una macchina Linux Debian "normale" funziona senza problemi.
Cosa fare se il link cade da solo
Se la connessione cade dopo qualche tempo, probabilmente e` dovuto a un bug che fa cadere tutto nel momento in cui dovrebbe avvenire un rekeying. Questo problema puo` essere risolto impostando uno (o tutti e due) di questi parametri in ipsec.conf, nella descrizione della connessione:
dpdaction=restart closeaction=restart
Il primo dovrebbe riavviare la connessione nel caso in cui scatti il meccanismo di Dead Peer Detection. Il secondo invece dovrebbe riavviare la connessione nel caso in cui per qualsiasi motivo (dipendente dal remoto) la connessione venga chiusa.
Debug e controllo dello stato delle connessioni
Qualche comando utile:
- ipsec statusall (elenco delle connessioni stabilite)
- ipsec start/stop/restart/reload (ovvio, no?)
- ip route show table 220 (mostra la tabella di routing 220, che contiene le regole autogenerate da ipsec quando avvia i tunnel)
- ip rule show (per vedere se esiste la table 220)
- ip xfrm state
- ip xfrm policy
- ip xfrm monitor (mostra le variazioni in tempo reale)
Esempi di configurazione
Ecco un esempio di una connessione lan to lan verso un router remoto proprietario con chiave PSK:
- Strongswan.conf, con una configurazione per ridurre il livello di logging perche` altrimenti nel funzionamento normale strongswan monopolizza il log con un sacco di informazioni piu` o meno inutili. I livelli di log vanno da -1 a +5 (se ricordo bene) con default a 1.
# strongswan.conf - strongSwan configuration file # # Refer to the strongswan.conf(5) manpage for details # # Configuration changes should be made in the included files charon { load_modular = yes plugins { include strongswan.d/charon/*.conf } syslog { daemon { ike = 1 knl = 1 net = 0 enc = 0 } } }
- ipsec.secrets, con una configurazione di chiave preshared fra il mio host e il remoto.
# <leftid> <rightid> : PSK "<chiave>" 192.168.1.254 46.100.4.10 : PSK "tarapia tapioca come se fosse antani per due a sinistra"
- ipsec.conf, con le configurazioni dei link
version 2 conn nostrarete-lororete keyexchange=ikev1 left=192.168.1.254 (la mia interfaccia pubblica) right=46.100.4.10 (la loro interfaccia pubblica) leftsubnet=192.168.90.0/24 (la mia rete LAN) leftauth=psk rightauth=psk rightsubnet=172.20.0.0/16 (la rete LAN remota che va routata via il tunnel) auto=start leftid=80.10.9.1 (un "nome" con cui si identifica il mio endpoint, usato per esempio nel file ipsec.secrets. Deve coincidere con quello impostato dall'altro lato) rightid=46.100.4.10 (il nome dell'altro endpoint, come sopra. Usare gli indirizzi ip pubblici come nomi e` pratica comune) # esp=3des-sha1-modp2048 ike=3des-sha1-modp1024 type=tunnel dpdaction=restart closeaction=restart
- un altro esempio di ipsec.conf, dove si stabiliscono diversi tunnel verso un unico endopint remoto. I tunnel sono tutti uguali fra loro, tranne che definiscono diverse "rightsubnet", in quanto in questa configurazione vi sono diverse subnet remote da routare attraverso il tunnel. Non potendo indicare diverse rightsubnet nella stessa connessione, si creano diverse connessioni identiche tranne che per la rightsubnet.
# ipsec.conf - strongSwan IPsec configuration file version 2 conn noi-loro keyexchange=ikev1 left=192.168.1.5 right=13.4.6.2 leftsubnet=172.21.34.0/24 leftauth=psk rightauth=psk rightsubnet=192.168.238.96/28 auto=start leftid=8.7.6.5 rightid=193.13.99.20 ike=3des-sha1-modp1024 type=tunnel dpdaction=restart closeaction=restart conn noi-loro2 keyexchange=ikev1 left=192.168.1.5 right=13.4.6.2 leftsubnet=172.21.34.0/24 leftauth=psk rightauth=psk rightsubnet=192.168.238.0/28 auto=start leftid=8.7.6.5 rightid=193.13.99.20 ike=3des-sha1-modp1024 type=tunnel dpdaction=restart closeaction=restart conn noi-loro3 keyexchange=ikev1 left=192.168.1.5 right=13.4.6.2 leftsubnet=172.21.34.0/24 leftauth=psk rightauth=psk rightsubnet=192.168.238.16/28 auto=start leftid=8.7.6.5 rightid=193.13.99.20 ike=3des-sha1-modp1024 type=tunnel dpdaction=restart closeaction=restart