Zavolat Další kontakty >
E-mail Kontakty

Lynt na zimních konferencích: 16.2. Jakub Kašparů na PPC Masters v Berlíně, 18.2. Vláďa Smitka na WordCampu v Praze

IKEv2 VPN v cloudu snadno a rychle

Návod jak zprovoznit v současnosti nejlepší typ VPN na virtuálním serveru v cloudu Amazonu, Digital Ocean, ale třeba i ve Vultr.com.

V článku o zprovoznění L2TP jsem zmiňoval, že osobně považuji IKEv2, za nejlepší současnou volbu pro VPN. Je tomu tak z několika z několika důvodů:

  • je v základu podporovaná na Windows (7+), OSX (10.11+), Linuxu, IOS (9+), Blackberry 10, jen na Androidu je potřeba doinstalovat aplikaci StrongSwan
  • nativně podporuje NAT Traversal
  • podporuje rozšíření MOBIKE (udrží VPN spojení i při přechodu mezi různými sítěmi - to je užitečné především u mobilních zařízení)
  • v případě použití důvěryhodné certifikační autority není potřeba řešit sdílené klíče nebo instalaci certifikátů - uživatel potřebuje jen jméno a heslo

Pro její použití jsou potřeba SSL certifikáty, což může být komplikace. Naštěstí dnes už existuje certifikační autorita Let's Encrypt (dále v textu zkráceně LE), která dovolí proces s certifikáty zautomatizovat a je zajištěna důvěryhodnost CA na straně klienta. Pokud chceme vystavit LE certifikát, tak je ovšem potřeba mít nejprve k dispozici doménové jméno, pro které jej budeme vystavovat. Tento fakt komplikuje automatický deployment na virtuální servery - dopředu nevíme jakou IP adresu server dostane, takže si dopředu ani nemůžeme připravit příslušný DNS záznam. Pro přípravu instalačního skriptu jsem proto využil službu nip.io, která mapuje všechny IP adresy na své doménové jméno - např. IP adresa 8.8.8.8 je dostupná pod jménem 8.8.8.8.nip.io.

Automatická instalace je opět realizována pomocí cloud-init skriptu, do kterého stačí doplnit jen několik vlastních hodnot.

#cloud-config
packages:
 - firewalld

write_files:
  - path: /etc/strongswan/ipsec.conf
    content: |
      config setup
        protostack=netkey
        nhelpers=0

      conn IKEv2-EAP
        keyexchange=ikev2
        leftid=%any
        leftcert=fullchain.pem
        leftsubnet=0.0.0.0/0
        right=%any
        rightsourceip=10.0.1.0/24
        rightdns=8.8.8.8
        dpdaction=clear
        dpddelay=30s
        dpdtimeout=1800s
        fragmentation=yes
        auto=add
        rekey=no
        leftsendcert=always
        rightauth=eap-mschapv2
        eap_identity=%identity


  - path: /etc/strongswan /ipsec.secrets
    content: |       
      : RSA privkey.pem
      {jmeno} : EAP "{heslo}"

  - path: /etc/sysctl.conf
    content: |
      net.ipv4.ip_forward = 1
      net.ipv4.conf.all.rp_filter = 0
      net.ipv4.conf.default.rp_filter = 0
      net.ipv4.conf.eth0.rp_filter = 0
      net.ipv4.conf.all.send_redirects = 0
      net.ipv4.conf.default.send_redirects = 0
      net.ipv4.conf.all.accept_redirects = 0
      net.ipv4.conf.default.accept_redirects = 0

  - path: /etc/cron.daily/update.sh
    content: |
      #!/bin/bash
      /usr/bin/yum -y update
      /usr/bin/certbot renew -q

  - path: /usr/local/bin/register-le-cert.sh
    content: |
      #!/bin/bash
      MAIL={mail}
      DOMAIN=
      if [ -z "$DOMAIN" ]
      then
        IP=$(curl -s http://tools.lynt.cz/ip.php?raw)
        certbot certonly --standalone -n -m $MAIL -d $IP.nip.io --agree-tos
        ln -s /etc/letsencrypt/live/$IP.nip.io/fullchain.pem /etc/strongswan/ipsec.d/certs/fullchain.pem
        ln -s /etc/letsencrypt/live/$IP.nip.io/privkey.pem /etc/strongswan/ipsec.d/private/privkey.pem
        sed -i "s/leftid=.*/leftid=$IP.nip.io/g" /etc/strongswan/ipsec.conf
      else
        certbot certonly --standalone -n -m $MAIL -d $DOMAIN --agree-tos
        ln -s /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/strongswan/ipsec.d/certs/fullchain.pem
        ln -s /etc/letsencrypt/live/$DOMAIN/privkey.pem /etc/strongswan/ipsec.d/private/privkey.pem
        sed -i "s/leftid=.*/leftid=$DOMAIN/g" /etc/strongswan/ipsec.conf
      fi

runcmd:
  - rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
  - yum install certbot strongswan -y
  - sysctl -p /etc/sysctl.conf
  - chmod a+x /etc/cron.daily/update.sh
  - chmod a+x /usr/local/bin/register-le-cert.sh
  - wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem -O /etc/strongswan/ipsec.d/cacerts/lets-encrypt-x3-cross-signed.pem
  - register-le-cert.sh
  - firewall-offline-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="{ip}" accept'
  - firewall-offline-cmd --zone=public --add-port=500/udp
  - firewall-offline-cmd --zone=public --add-port=4500/udp
  - firewall-offline-cmd --zone=public --add-port=443/tcp
  - firewall-offline-cmd --zone=public --add-port=80/tcp
  - firewall-offline-cmd --zone=public --remove-service-from-zone=ssh
  - firewall-offline-cmd --zone=public --add-masquerade
  - firewall-offline-cmd --zone=public --add-interface=eth0
  - systemctl start strongswan firewalld
  - systemctl enable strongswan firewalld

Ve skriptu je třeba upravit následující čtyři hodnoty:

{jmeno} - uživatelské jméno do VPN

{heslo} - heslo do VPN

{ip} - vaše IP adresa pro přístup k SSH (pro samotné zprovoznění není potřeba, bude se hodit až pro budoucí správu)

{mail} - vaše e-mailová adresa pro registraci LE certifikátu

 

V cloud-init skriptu si pomáhám vytvořením a následným spuštěním bash skriptu, který z naší služby zjistí veřejnou IP adresu virtuálu a podle ní registruje LE certifikát. Dále pak podle domény upraví konfiguraci IPsec (to je nutné pro podporu IOS).

Detailní postup jak spustit stroj s cloud-init skriptem v Amazon AWS naleznete v článku se zprovozněním L2TP, jak to samé udělat na Digital Ocean (v linku je referral, díky kterému získáte 10$ na testy) zase v článku s nastavením Squid Proxy.

Dále jsem se rozhodl cloud-init skripty přepsat i do běžného bash skriptu, díky kterému můžete VPN nainstalovat na již existující stroj. Hodí se i v případě, že poskytovatel nepodporuje cloud-init, ale umí po startu virtuálu vykonat skript.

To je příklad poskytovatele Vultr.com (tímto referral odkazem získáte startovací kredit 20$ = 4 měsíce provozu nejmenší instance). Vultr experimentálně podporuje i cloud-init skripty (je potřeba si o zapnutí požádat podporu), ale zatím v nich vše nefunguje.

Skript je k dispozici mém GitHubu (naleznete zde i do bashe přepsané cloud-init skripty z předchozích dílů).

Postup vytvoření virtuálního na Vultr.com je následující:

1. je potřeba vytvořit startovací skript (je to možné provést i během tvorby nového stroje) - pojmenoval jsem ho IKEv2. Ve skriptu je potřeba doplnit v záhlaví vlastní hodnoty - jméno a heslo do VPN, vaši IP adresu pro správu a e-mailovou adresu pro registraci SSL certifikátu.

2. Vytvořit si virtuální stroj s Centos 7, minimální instance je dostatečná:

3. Vybrat vytvořený startovací skript:

Po několika minutách (stáhnou a nainstalovat závislosti pro LE chvilku trvá) bude stroj připraven. Stačí pak již nakonfigurovat klienta podobným způsobem jako v případě L2TP, pouze se vybere IKEv2 a nezadává se sdílené heslo. Jako server je třeba zadat adresu <IP>.nip.io.

V mém případě by to tedy bylo 45.32.153.0.nip.io. Skript počítá i s tím, že budete chtít použít vlastní doménu - stačí ji vyplnit do proměnné DOMAIN. Doména však musí být již nasměrována na IP adresu severu, jinak se nepodaří registrace LE certifikátu. Pro toto použií je optimální postup nejprve nainstalovat čistý virtuál, na přidělenou IP nasměrovat DNS záznam a následně z příkazové řádky spustit instalační skript.

Nastavení klienta ve Windows 10 vypadá následovně:

 

Nastavení na IOS pak takto:

 

S tímto návodem tady již zvládnete připravit server s moderním typem VPN IKEv2 s certifikáty od certifikační autority Let's Encrypt. A to jak na službách podporujících cloud-init skripty, tak na službách podporujících spuštění obecného bash skriptu. S tímto skriptem dokážete nakonfigurovat i předem nainstalovaný stroj, na jehož IP je nasměrován DNS záznam.

Vše si můžete vyzkoušet v trial verzi Amazon AWS, na Digital Ocean s 10$ kreditem, nebo na Vultr.com s kreditem 20$ (v rámci letní akce).

Komentáře (2)

Přidat komentář

napsáno 6. 1. 23:16
I'm glad my script helped you.

The purpose of this line is to deny public access to ssh (it is allowed from your ip via the rich rule). If you have dynamic ip please remove the rich rule and the rule removes ssh service from the zone.

You can put the following command to the remote console to allow ssh again:
firewall-cmd --zone=public --add-service=ssh --pernament

In case of dynamic IP I recommend you to change ssh listen port from 22 to anything else, e.g. 7022.

firewall-cmd --zone=public --add-port=7022/tcp --permanent
/etc/ssh/sshd_config - Port 7022
systemctl restart sshd

It is security by obscurity, but it prevents dumb bots from bruteforcing at least. Another solution is to use VPN itself to the ssh access.
napsáno 6. 1. 22:13
Your script has been very useful to make to get my VPN working. Thank you

BUT: I can't access to my server through SSH anymore because my connection has a dynamic IP.

What was the aim of "- firewall-offline-cmd --zone=public --remove-service-from-zone=ssh". It broke my server....