IKEv2 VPN v cloudu snadno a rychle

Publikováno: 28.9.2020

Ukázali jsme, jak zprovoznit proxy na Digital Ocean, jak na L2TP VPN v AWS a dnes se podíváme na IKEv2.

Celý článek

Text vyšel původně na autorově webu.

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 sslip.io (lze použít i obdobné služby nip.io nebo xip.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.sslip.io.

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

#cloud-config
packages:
 - firewalld

write_files:
  - path: /etc/strongswan/ipsec.conf
    content: |
      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
        ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024!
        esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1!



  - 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 https://tools.lynt.cz/ip.php?raw)
        certbot certonly --standalone -n -m $MAIL -d $IP.sslip.io --agree-tos
        ln -s /etc/letsencrypt/live/$IP.sslip.io/fullchain.pem /etc/strongswan/ipsec.d/certs/fullchain.pem
        ln -s /etc/letsencrypt/live/$IP.sslip.io/privkey.pem /etc/strongswan/ipsec.d/private/privkey.pem
        sed -i "s/leftid=.*/leftid=$IP.sslip.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

  - path: /etc/systemd/system/vpn.service
    content: |
      [Unit]
      Description=strongSwan IPsec IKEv1/IKEv2 daemon
      After=network-online.target
      
      [Service]
      ExecStart=/usr/sbin/strongswan start --nofork
      StandardOutput=syslog
      Restart=on-abnormal
      
      [Install]
      WantedBy=multi-user.target

runcmd:
  - RELEASE=$(rpm -E %{rhel}) && rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-$RELEASE.noarch.rpm
  - yum install wget 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="{myip}" accept'
  - firewall-offline-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" 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 --remove-service=ssh
  - firewall-offline-cmd --zone=public --add-masquerade
  - firewall-offline-cmd --zone=public --add-interface=eth0
  - systemctl start vpn firewalld
  - systemctl enable vpn firewalld

Cloud Init na GitHubu.

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 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. Vultr s cloud-init skripty experimentoval, ale zdá se, že je nakonec produkčně nenasadil. Výhodou poskytovatele Vultr je poměrně široká nabídka datacenter, kde naleznete i například Austrálii nebo Japonsko.

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/8, 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 .sslip.io.

V mém případě by to tedy bylo 45.32.153.0.sslip.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žití 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ě:

Nebo můžete jednoduše použít PowerShell příkaz:

Add-VpnConnection -Name "TEST - IKEv2" -ServerAddress {ip_serveru}.sslip.io -TunnelType IKEv2 -RememberCredential 

Nastavení na MacOS:

Nastavení na iOS:

Nastavení na Androidu pomocí StrongSwan:

Závěr

S tímto návodem 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. Pomocí uvedeného skriptu dokážete nakonfigurovat i předem nainstalovaný stroj, na jehož IP je nasměrován DNS záznam.

Nahoru
Tento web používá k poskytování služeb a analýze návštěvnosti soubory cookie. Používáním tohoto webu s tímto souhlasíte. Další informace