In mod traditional pentru schimbul de informatii considerate sensibile intre doua companii, indiferent de aplicatie, se stabileste o conexiune IPSec (da, stiu ca mai exista si OpenVPN dar nu se pune ca nu este suportat comercial pentru interoperare). Si treaba asta merge OK cand ai nu numar rezonabil de parteneri, dupa aia nu mai este chiar asa distractiv.
Cand ai o companie mare cu multe locatii, atunci se ajunge la configuratii de tipul Hub-and-Spoke fie configurate manual fie automat folosind DMVPN/GETVPN in functie de necesitati si situatie individuala.
Acum, cum impaci capra cu varza, sa ai o configuratia din asta dar intre companii, un fel de serviciu de IPSec-as-a-Service, ceva de genul:
Unde VPN HUB este un la “provider” iar gateway-urile de VPN sunt la “clienti”. Si asta se poate extinde pana terminam alfabetul si o luam cu VPN Gateway AA pana la VPN Gateway ZZZZZ.
Cum ar functiona toata treaba asta fara sa se strice si sa fie scalabila? Teoretic ar fi in felul urmator:
- IPSec intre capete
- GRE over IPSec
- BGP over GRE
- se accepta doar adrese de IP sau subnet-uri “publice”
De ce BGP? Pai pentru ca:
- permite o filtrare mult mai buna a rutelor si a anunturilor, astfel incat sa nu se poata anunta prefixe inexistente sau sa se poata face hijacking
- pot anunta sau importa selectiv prefixe
- pot folosi si pentru IPv4 cat si pentru IPv6
- este mult mai scalabil decat OSPF care este folosit in mod traditional pentru “route based VPNs”
Ideea de baza ar fi in felul urmator:
- Vreau sa comunic securizat cu un numar oarecare de entitati cu care am treaba insa nu vreau sa fac tunele VPN cu fiecare in parte
- Prefer sa am un singur tunel facut care sa-mi dea acces la restul de tunele
- Sa pot publica servicii “secure only” accesibile doar celor din clubul asta
- Sa fie greu de detectat de catre o entitate ostila cine cu cine discuta si cat de mult
Pentru validare mi-am facut un setup de test care arata cam asa:
Setarile sunt facute astfel:
- vpn-hub
- eth0: 10.15.0.1/24
- internet-router
- eth0: 10.16.0.1/24
- eth1: 10.15.0.2/24
- vpn-gw-a
- eth0: 10.16.0.2/24
- eth1: 172.16.1.1/24
- vpn-gw-b
- eth0: 10.16.0.3/24
- eth1: 172.16.2.1/24
- vpn-gw-c
- eth0: 10.16.0.4/24
- eth1: 172.16.3.1/24
internet-router este o masina care sa simuleze “internetul” in sensul de un hop intermediar intre gateway-urile de VPN si concentrator.
Prima oara am setat tunele VPN (pentru test le-am facut cu PSK ca e mai usor):
- vpn-hub /etc/ipsec.conf
conn to-vpn-gw-a authby=secret auto=start type=transport left=10.15.0.1 leftnexthop=10.15.0.2 right=10.16.0.2 rightnexthop=10.16.0.1
conn to-vpn-gw-b authby=secret auto=start type=transport left=10.15.0.1 leftnexthop=10.15.0.2 right=10.16.0.3 rightnexthop=10.16.0.1
conn to-vpn-gw-c authby=secret auto=start type=transport left=10.15.0.1 leftnexthop=10.15.0.2 right=10.16.0.4 rightnexthop=10.16.0.1
- vpn-hub /etc/ipsec.secrets
10.15.0.1 10.16.0.2: PSK "supersecret" 10.15.0.1 10.16.0.3: PSK "supersecret" 10.15.0.1 10.16.0.4: PSK "supersecret"
- vpn-gw-a /etc/ipsec.conf
conn to-vpn-hub authby=secret auto=start type=transport left=10.16.0.2 leftnexthop=10.16.0.1 right=10.15.0.1 rightnexthop=10.15.0.2
- vpn-gw-a /etc/ipsec.secrets
10.16.0.2 10.15.0.1: PSK "supersecret"
- vpn-gw-b /etc/ipsec.conf
conn to-hub authby=secret auto=start type=transport right=10.15.0.1 rightnexthop=10.15.0.2 left=10.16.0.3 leftnexthop=10.16.0.1
- vpn-gw-b /etc/ipsec.secrets
10.16.0.3 10.15.0.1: PSK "supersecret"
- vpn-gw-c /etc/ipsec.conf
conn to-hub authby=secret auto=start type=transport right=10.15.0.1 rightnexthop=10.15.0.2 left=10.16.0.4 leftnexthop=10.16.0.1
- vpn-gw-c /etc/ipsec.secrets
10.16.0.4 10.15.0.1: PSK "supersecret"
- vpn-hub ipsec status
stats db_ops: {curr_cnt, total_cnt, maxsz} :context={0,0,0} trans={0,0,0} attrs={0,0,0} "to-vpn-gw-a": 10.15.0.1<10.15.0.1>[+S=C]---10.15.0.2...10.16.0.1---10.16.0.2<10.16.0.2>[+S=C]; erouted; eroute owner: #2 "to-vpn-gw-a": myip=unset; hisip=unset; "to-vpn-gw-a": ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0; nat_keepalive: yes "to-vpn-gw-a": policy: PSK+ENCRYPT+PFS+UP+IKEv2ALLOW+SAREFTRACK+lKOD+rKOD; prio: 32,32; interface: eth0; "to-vpn-gw-a": dpd: action:clear; delay:0; timeout:0; "to-vpn-gw-a": newest ISAKMP SA: #16; newest IPsec SA: #2; "to-vpn-gw-a": IKE algorithm newest: AES_CBC_128-SHA1-MODP2048 "to-vpn-gw-b": 10.15.0.1<10.15.0.1>[+S=C]---10.15.0.2...10.16.0.1---10.16.0.3<10.16.0.3>[+S=C]; erouted; eroute owner: #7 "to-vpn-gw-b": myip=unset; hisip=unset; "to-vpn-gw-b": ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0; nat_keepalive: yes "to-vpn-gw-b": policy: PSK+ENCRYPT+PFS+UP+IKEv2ALLOW+SAREFTRACK+lKOD+rKOD; prio: 32,32; interface: eth0; "to-vpn-gw-b": dpd: action:clear; delay:0; timeout:0; "to-vpn-gw-b": newest ISAKMP SA: #18; newest IPsec SA: #7; "to-vpn-gw-b": IKE algorithm newest: AES_CBC_128-SHA1-MODP2048 "to-vpn-gw-c": 10.15.0.1<10.15.0.1>[+S=C]---10.15.0.2...10.16.0.1---10.16.0.4<10.16.0.4>[+S=C]; erouted; eroute owner: #11 "to-vpn-gw-c": myip=unset; hisip=unset; "to-vpn-gw-c": ike_life: 3600s; ipsec_life: 28800s; rekey_margin: 540s; rekey_fuzz: 100%; keyingtries: 0; nat_keepalive: yes "to-vpn-gw-c": policy: PSK+ENCRYPT+PFS+UP+IKEv2ALLOW+SAREFTRACK+lKOD+rKOD; prio: 32,32; interface: eth0; "to-vpn-gw-c": dpd: action:clear; delay:0; timeout:0; "to-vpn-gw-c": newest ISAKMP SA: #17; newest IPsec SA: #11; "to-vpn-gw-c": IKE algorithm newest: AES_CBC_128-SHA1-MODP2048 #2: "to-vpn-gw-a":500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 19862s; newest IPSEC; eroute owner; isakmp#1; idle; import:admin initiate #2: "to-vpn-gw-a" [email protected] [email protected] ref=0 refhim=4294901761 #16: "to-vpn-gw-a":500 STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 211s; newest ISAKMP; lastdpd=-1s(seq in:0 out:0); idle; import:admin initiate #4: "to-vpn-gw-b":500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 19643s; isakmp#3; idle; import:admin initiate #4: "to-vpn-gw-b" [email protected] [email protected] ref=0 refhim=4294901761 #15: "to-vpn-gw-b":500 STATE_MAIN_R3 (sent MR3, ISAKMP SA established); EVENT_SA_REPLACE in 393s; lastdpd=-1s(seq in:0 out:0); idle; import:not set #7: "to-vpn-gw-b":500 STATE_QUICK_R2 (IPsec SA established); EVENT_SA_REPLACE in 20348s; newest IPSEC; eroute owner; isakmp#6; idle; import:not set #7: "to-vpn-gw-b" [email protected] [email protected] ref=0 refhim=4294901761 #18: "to-vpn-gw-b":500 STATE_MAIN_R3 (sent MR3, ISAKMP SA established); EVENT_SA_REPLACE in 3022s; newest ISAKMP; lastdpd=-1s(seq in:0 out:0); idle; import:not set #10: "to-vpn-gw-c":500 STATE_QUICK_R2 (IPsec SA established); EVENT_SA_REPLACE in 21719s; isakmp#9; idle; import:not set #10: "to-vpn-gw-c" [email protected] [email protected] ref=0 refhim=4294901761 #17: "to-vpn-gw-c":500 STATE_MAIN_I4 (ISAKMP SA established); EVENT_SA_REPLACE in 1169s; newest ISAKMP; lastdpd=-1s(seq in:0 out:0); idle; import:admin initiate #11: "to-vpn-gw-c":500 STATE_QUICK_I2 (sent QI2, IPsec SA established); EVENT_SA_REPLACE in 21348s; newest IPSEC; eroute owner; isakmp#8; idle; import:admin initiate #11: "to-vpn-gw-c" [email protected] [email protected] ref=0 refhim=4294901761
type=transport din /etc/ipsec.conf pentru fiecare conexiune in parte inseamna ca o “conexiune” IPSec se va stabili doar intre IP-urile gateway-urilor.
Acum ca totul e OK la partea de criptare, se seteaza tunelele GRE intre gatewa-uri si hub:
- vpn-gw-a
ip tunnel add to-hub mode gre remote 10.15.0.1 local 10.16.0.2 ttl 255 ip addr add 192.168.168.2/30 peer 192.168.168.1/30 dev to-hub ip link set to-hub up
- vpn-gw-b
ip tunnel add to-hub mode gre remote 10.15.0.1 local 10.16.0.3 ttl 255 ip addr add 192.168.168.2/30 peer 192.168.168.1/30 dev to-hub ip link set to-hub up
- vpn-gw-c
ip tunnel add to-hub mode gre remote 10.15.0.1 local 10.16.0.4 ttl 255 ip addr add 192.168.168.2/30 peer 192.168.168.1/30 dev to-hub ip link set to-hub up
- vpn-hub
ip tunnel add to-gw-a mode gre remote 10.16.0.2 local 10.15.0.1 ttl 255 ip addr add 192.168.168.1/30 peer 192.168.168.2/30 dev to-gw-a ip link link set to-gw-a up ip tunnel add to-gw-b mode gre remote 10.16.0.3 local 10.15.0.1 ttl 255 ip addr add 192.168.168.5/30 peer 192.168.168.6/30 dev to-gw-b ip link link set to-gw-b up ip tunnel add to-gw-c mode gre remote 10.16.0.4 local 10.15.0.1 ttl 255 ip addr add 192.168.168.9/30 peer 192.168.168.10/30 dev to-gw-c ip link link set to-gw-c up
Tunelele GRE sunt necesare pentru a putea ruta peste orice avem nevoie fara a crea SA-uri suplimentare in IPSec pentru fiecare subnet sau adresa IP individuala si abstractizeaza partea de transport. Din punct de vedere IP un gateway are conexiune directa cu hub-ul si atat.
Ultima partea este configurarea Quagga pentru a avea partea de BGP functionala.
- vpn-hub /etc/quagga/bgpd.conf
router bgp 4200000000 bgp router-id 192.168.168.9 neighbor 192.168.168.2 remote-as 4200000001 neighbor 192.168.168.2 next-hop-self neighbor 192.168.168.10 remote-as 4200000003 neighbor 192.168.168.10 next-hop-self
- vpn-gw-a /etc/quagga/bgpd.conf
router bgp 4200000001 bgp router-id 192.168.168.2 network 172.16.1.0/24 neighbor 192.168.168.1 remote-as 4200000000
- vpn-gw-c
router bgp 4200000003 bgp router-id 192.168.168.10 network 172.16.3.0/24 neighbor 192.168.168.9 remote-as 4200000000
Configurarea de pe vpn-gw-b lipseste ca mi-am dat seama in timp ce scriam ca de fapt este OK de demonstrat si cu doar doua gateway-uri :)
- vpn-gw-c sh ip bgp
BGP table version is 0, local router ID is 192.168.168.10 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 172.16.1.0/24 192.168.168.9 0 4200000000 4200000001 i *> 172.16.3.0/24 0.0.0.0 0 32768 i Total number of prefixes 2
- vpn-gw-a sh ip bgp
BGP table version is 0, local router ID is 192.168.168.2 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 172.16.1.0/24 0.0.0.0 0 32768 i *> 172.16.3.0/24 192.168.168.1 0 4200000000 4200000003 i Total number of prefixes 2
- vpn-hub sh ip bgp
BGP table version is 0, local router ID is 192.168.168.9 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path *> 172.16.1.0/24 192.168.168.2 0 0 4200000001 i *> 172.16.3.0/24 192.168.168.10 0 0 4200000003 i Total number of prefixes 2
Daca de pe vpn-gw-a dau un ping spre vpn-gw-c (ping 172.16.3.1 -I172.16.1.1) in tcpdump pe vpn-hub am sa vad urmatoarele:
20:03:55.112851 IP 10.16.0.2 > 10.15.0.1: ESP(spi=0xbe68e78f,seq=0x338), length 132 20:03:55.112906 IP 10.15.0.1 > 10.16.0.4: ESP(spi=0xac29a868,seq=0x30f), length 132 20:03:55.113404 IP 10.16.0.4 > 10.15.0.1: ESP(spi=0xfdb78f7d,seq=0x2b7), length 132 20:03:55.113434 IP 10.15.0.1 > 10.16.0.2: ESP(spi=0xc07aaa19,seq=0x370), length 132
Adica ajunge pachetul de la vpn-gw-a la vpn-hub, vpn-hub il trimite la vpn-gw-c, vpn-gw-c raspunde la vpn-hub si vpn-hub da mai departe la vpn-gw-a.
Adica merge cum trebuie toata jucaria :)
Ce mai am de studiat, ca inca mi-o iau in freza:
- sa folosesc un singur ASN. Am incercat tot felul de combinatii sa fac gateway-urile RR Client pentru vpn-hub insa n-a vrut sa schimbe next-hop nici batut. Nici macar pus in mod explicit cu neighbor X:X:X:X next-hop-self. Ca sa nu incalec ce este acum, am dat-o pe ASN-uri de 32biti reservate, ca alea ar ajunge sa conectez tot internetul la un mega VPN :))
- sa trec prin IPSec doar GRE, dar din pacate ii da cu virgula lui OpenSWAN daca ii zic rightprotoport=47 (cu asta nu vrea nici batut) sau rightprotoport=47/%any (moare cu un mesaj dubios legat de “unable to route”)
Alte chestii mai putin importante:
- sa vad cum trebuie salvate setarile corect cum vrea CentOS pentru toate optiunile (interfete, GRE, OpenSWAN, Quagga)
- trecut pe certificate digitale pentru autentificarea gateway-urilor si IKEv2 pentru schimbul de chei cu niste algoritmi de criptare bine definiti
- experimentat si un pic cu IPSec pentru IPv6, dar la cum arata acum parca vad ca o sa trec IPv6-le peste GRE-ul deja existent si scap usor (sper)
- sa conving o multime de oameni sa-mi dea bani sa le fiu broker de VPN :))
PS:
- am uitat o caruta de chestii, ma uitam (si in continuare ma uit) ca vaca la OpenSWAN si nu mai stiam (stiu) de unde sa-l iau
- ce misto e sa ai mult RAM in laptop, poti sa-ti faci maisini virtuale pana te ia plictisul
Dupa ce-o sa-mi treaca durerea de cap de o am, o sa sap mai cu talent in OpenSWAN sa vad cum il fac sa mearga cat mai sigur si cat mai simplu, eventual automatizat un pic.