network:vpn_-_strongswan
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
network:vpn_-_strongswan [2019/11/30 19:17] – removed peter | network:vpn_-_strongswan [2020/07/23 01:11] (current) – old revision restored (2016/07/04 10:36) 158.69.243.99 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Networks - VPN - StrongSwan ====== | ||
+ | |||
+ | To set up an IPSEC VPN server on Ubuntu 15.10 using StrongSwan as the IPsec server and for authentication. | ||
+ | |||
+ | ===== Why a VPN ===== | ||
+ | |||
+ | More than ever, your freedom and privacy when online is under threat. | ||
+ | |||
+ | A VPN (virtual private network) creates a secure, encrypted tunnel through which all of your online data passes back and forth. | ||
+ | |||
+ | IPSEC encrypts your IP packets to provide encryption and authentication, | ||
+ | |||
+ | This VPN setup is called a road-warrior setup, because clients can connect from anywhere. | ||
+ | |||
+ | To work trough this tutorial you should have: | ||
+ | |||
+ | * 1 Ubuntu 15.10 server with at least 1 public IP address and root access. | ||
+ | * 1 (or more) clients running an OS that support IPsec IKEv2 vpns (Ubuntu, Mac OS, Windows 7+, Android 4+). | ||
+ | * Ports 4500/UDP, 500/UDP, 51/UDP and 50/UDP opened in the firewall. | ||
+ | |||
+ | ===== No L2TP ===== | ||
+ | |||
+ | A few of the previous tutorials used L2TP to set up the VPN tunnel and use IPSEC only for the encryption. | ||
+ | |||
+ | |||
+ | ===== Overview ===== | ||
+ | |||
+ | The tutorial consists out of the following steps: | ||
+ | |||
+ | * Install packages | ||
+ | * Generate certificates | ||
+ | * Configure IPSEC | ||
+ | * Configure Firewall | ||
+ | * Android and Windows client configuration is covered at the end of the tutorial. | ||
+ | |||
+ | ===== Install Strongswan ===== | ||
+ | |||
+ | StrongSwan is a descendant of FreeS/WAN, just like Openswan or LibreSwan. | ||
+ | |||
+ | <code bash> | ||
+ | apt-get install strongswan strongswan-plugin-af-alg strongswan-plugin-agent strongswan-plugin-certexpire strongswan-plugin-coupling strongswan-plugin-curl strongswan-plugin-dhcp strongswan-plugin-duplicheck strongswan-plugin-eap-aka strongswan-plugin-eap-aka-3gpp2 strongswan-plugin-eap-dynamic strongswan-plugin-eap-gtc strongswan-plugin-eap-mschapv2 strongswan-plugin-eap-peap strongswan-plugin-eap-radius strongswan-plugin-eap-tls strongswan-plugin-eap-ttls strongswan-plugin-error-notify strongswan-plugin-farp strongswan-plugin-fips-prf strongswan-plugin-gcrypt strongswan-plugin-gmp strongswan-plugin-ipseckey strongswan-plugin-kernel-libipsec strongswan-plugin-ldap strongswan-plugin-led strongswan-plugin-load-tester strongswan-plugin-lookip strongswan-plugin-ntru strongswan-plugin-pgp strongswan-plugin-pkcs11 strongswan-plugin-pubkey strongswan-plugin-radattr strongswan-plugin-sshkey strongswan-plugin-systime-fix strongswan-plugin-whitelist strongswan-plugin-xauth-eap strongswan-plugin-xauth-generic strongswan-plugin-xauth-noauth strongswan-plugin-xauth-pam strongswan-pt-tls-client | ||
+ | </ | ||
+ | |||
+ | ===== Certificates ===== | ||
+ | |||
+ | The VPN server will identify itself with a certificate to the clients. | ||
+ | |||
+ | On Android with the StrongSwan Application you can just import the **.p12** we are going to create later on. OS X and iOS from 10.10 and 9 upwards also support this authentication method. | ||
+ | |||
+ | You might want to install **haveged** to speed up the key generation process: | ||
+ | |||
+ | <code bash> | ||
+ | apt-get install haveged | ||
+ | systemctl enable haveged | ||
+ | systemctl start haveged | ||
+ | </ | ||
+ | |||
+ | Haveged provides a constant source of entropy and randomness. | ||
+ | |||
+ | Start by creating a self singed root CA private key: | ||
+ | |||
+ | <code bash> | ||
+ | cd / | ||
+ | mkdir private | ||
+ | mkdir cacerts | ||
+ | mkdir certs | ||
+ | mkdir p12 | ||
+ | ipsec pki --gen --type rsa --size 4096 --outform der > private/ | ||
+ | chmod 600 private/ | ||
+ | </ | ||
+ | |||
+ | Generate a self signed root CA certificate of that private key: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --self --ca --lifetime 3650 --in private/ | ||
+ | </ | ||
+ | |||
+ | You can view the certificate properties with the following command: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --print --in cacerts/ | ||
+ | </ | ||
+ | |||
+ | Example output: | ||
+ | |||
+ | < | ||
+ | cert: X509 | ||
+ | subject: | ||
+ | issuer: | ||
+ | validity: | ||
+ | not after Dec 17 08:12:27 2025, ok (expires in 3649 days) | ||
+ | serial: | ||
+ | flags: | ||
+ | authkeyId: d1: | ||
+ | subjkeyId: d1: | ||
+ | pubkey: | ||
+ | keyid: | ||
+ | subjkey: | ||
+ | </ | ||
+ | |||
+ | Generate the VPN Host key. This is the keypair the VPN server host will use to authenticate itself to clients. | ||
+ | |||
+ | First the private key: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --gen --type rsa --size 4096 --outform der > private/ | ||
+ | chmod 600 private/ | ||
+ | </ | ||
+ | |||
+ | Generate the public key and use our earlier created root ca to sign the public key: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --pub --in private/ | ||
+ | </ | ||
+ | |||
+ | The domain name or IP address of your VPN server, which is later entered in the clients connection properties, MUST be contained either in the subject Distinguished Name (CN) and/or in a subject Alternative Name (**--san**). | ||
+ | |||
+ | The built in Windows 7 VPN client needs the **serverAuth** extended key usage flag in your host certificate as shown above, or the client will refuse to connect. | ||
+ | |||
+ | We add the IP address twice, one with an **@** in front so that it gets added as an **subjectAltName** of the **DNSName** type and one of the **IPAddess** type. | ||
+ | |||
+ | Let's view the certificate: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --print --in certs/ | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | < | ||
+ | cert: X509 | ||
+ | subject: | ||
+ | issuer: | ||
+ | validity: | ||
+ | not after Dec 19 08:15:22 2017, ok (expires in 729 days) | ||
+ | serial: | ||
+ | altNames: | ||
+ | flags: | ||
+ | authkeyId: d1: | ||
+ | subjkeyId: 27: | ||
+ | pubkey: | ||
+ | keyid: | ||
+ | subjkey: | ||
+ | </ | ||
+ | |||
+ | You can also use OpenSSL to see the contents, here is an excerpt: | ||
+ | |||
+ | <code bash> | ||
+ | openssl x509 -inform DER -in certs/ | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | < | ||
+ | Certificate: | ||
+ | Data: | ||
+ | Version: 3 (0x2) | ||
+ | Serial Number: 12263773464207966557 (0xaa31acfd4bfa415d) | ||
+ | Signature Algorithm: sha1WithRSAEncryption | ||
+ | Issuer: C=NL, O=Example Company, CN=strongSwan Root CA | ||
+ | Validity | ||
+ | Not Before: Dec 20 07:15:22 2015 GMT | ||
+ | Not After : Dec 19 07:15:22 2017 GMT | ||
+ | Subject: C=NL, O=Example Company, CN=vpn.example.org | ||
+ | Subject Public Key Info: | ||
+ | Public Key Algorithm: rsaEncryption | ||
+ | Public-Key: (4096 bit) | ||
+ | [...] | ||
+ | Exponent: 65537 (0x10001) | ||
+ | X509v3 extensions: | ||
+ | X509v3 Authority Key Identifier: | ||
+ | keyid: | ||
+ | |||
+ | X509v3 Subject Alternative Name: | ||
+ | DNS: | ||
+ | X509v3 Extended Key Usage: | ||
+ | TLS Web Server Authentication, | ||
+ | Signature Algorithm: sha1WithRSAEncryption | ||
+ | </ | ||
+ | |||
+ | The private key (**/ | ||
+ | |||
+ | ===== Client certificate ===== | ||
+ | |||
+ | Any client will require a personal certificate in order to use the VPN. The process is analogous to generating a host certificate, | ||
+ | |||
+ | We create a keypair for the example user " | ||
+ | |||
+ | Private key: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --gen --type rsa --size 2048 --outform der > private/ | ||
+ | chmod 600 private/ | ||
+ | </ | ||
+ | |||
+ | Public key, signed by our root ca we generated: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec pki --pub --in private/ | ||
+ | </ | ||
+ | |||
+ | A VPN client needs a client certificate, | ||
+ | |||
+ | Convert the required keys to PEM formt before converting to a .p12: | ||
+ | |||
+ | <code bash> | ||
+ | openssl rsa -inform DER -in private/ | ||
+ | |||
+ | openssl x509 -inform DER -in certs/ | ||
+ | |||
+ | openssl x509 -inform DER -in cacerts/ | ||
+ | Construct the .p12: | ||
+ | |||
+ | openssl pkcs12 -export -inkey private/ | ||
+ | </ | ||
+ | |||
+ | Enter a passphrase twice, then you have a .p12. You can send **John.p12** and its export paraphrase to the person who is going to install it onto the client. | ||
+ | |||
+ | Transport this **John.p12** file and the password over separate channels to a client. | ||
+ | |||
+ | If you need any more user certificates, | ||
+ | |||
+ | ===== Revoking a certificate ===== | ||
+ | |||
+ | If a certificate is lost or stolen, it must be revoked so nobody can use it to connect to your VPN server. | ||
+ | |||
+ | <code bash> | ||
+ | cd / | ||
+ | ipsec pki --signcrl --reason key-compromise --cacert cacerts/ | ||
+ | </ | ||
+ | |||
+ | Restart ipsec afterwards: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec restart | ||
+ | </ | ||
+ | |||
+ | This generates the new certificate revocation list (CRL) **crls/ | ||
+ | |||
+ | < | ||
+ | 04[CFG] using trusted certificate "C=NL, O=Example Company, CN=strongSwan Root CA" | ||
+ | 04[CFG] | ||
+ | 04[CFG] certificate was revoked on Dec 20 14:51:24 UTC 2015, reason: key compromise | ||
+ | </ | ||
+ | |||
+ | To add another revoked certificate to the same list, we need to copy the existing list into a temporary file: | ||
+ | |||
+ | <code bash> | ||
+ | cd / | ||
+ | cp crls/ | ||
+ | ipsec pki --signcrl --reason key-compromise --cacert cacerts/ | ||
+ | rm crl.der.tmp | ||
+ | </ | ||
+ | |||
+ | Restart ipsec afterwards: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec restart | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== IPSEC Configuration ===== | ||
+ | |||
+ | The main **ipsec** configuration file is located in **/ | ||
+ | |||
+ | <code bash> | ||
+ | vim / | ||
+ | </ | ||
+ | |||
+ | Place the following contents: | ||
+ | |||
+ | <code vi> | ||
+ | # ipsec.conf - strongSwan IPsec configuration file | ||
+ | |||
+ | config setup | ||
+ | charondebug=" | ||
+ | |||
+ | conn %default | ||
+ | keyexchange=ikev2 | ||
+ | ike=aes128-sha1-modp1024, | ||
+ | esp=aes128-aes256-sha1-sha256-modp2048-modp4096-modp1024, | ||
+ | dpdaction=clear | ||
+ | dpddelay=300s | ||
+ | authby=pubkey | ||
+ | left=%any | ||
+ | leftid=vpn.example.org | ||
+ | leftsubnet=0.0.0.0/ | ||
+ | leftcert=vpnHostCert.der | ||
+ | leftsendcert=always | ||
+ | right=%any | ||
+ | rightsourceip=10.42.42.0/ | ||
+ | rightdns=8.8.8.8, | ||
+ | |||
+ | conn IPSec-IKEv2 | ||
+ | keyexchange=ikev2 | ||
+ | auto=add | ||
+ | </ | ||
+ | |||
+ | Remove the **/ | ||
+ | |||
+ | <code bash> | ||
+ | rm / | ||
+ | ln -s / | ||
+ | </ | ||
+ | |||
+ | The configuration has settings for IKEv2 + RSA certificates. | ||
+ | |||
+ | Apple added support for IKEv2 in iOS 8, but it needs to be configured using a custom configuration profile [https:// | ||
+ | |||
+ | Beginning with iOS 9, IKEv2 connections are natively supported. | ||
+ | |||
+ | For iOS 9+ and OS X 10.10+ you need to make sure the **leftid=** is the same as the **CN** in your certificate. | ||
+ | |||
+ | Android 4+ and Windows 7+ support IKEv2. | ||
+ | |||
+ | Clients will get the Google DNS servers and an IP address in the **10.42.42.0/ | ||
+ | |||
+ | The **leftcert=vpnHostCert.der** expands to the path **/ | ||
+ | |||
+ | |||
+ | ===== Firewall & Packet Routing ===== | ||
+ | |||
+ | Configure the iptables firewall to allow vpn traffic and to forward packets: | ||
+ | |||
+ | <code bash> | ||
+ | # for ISAKMP (handling of security associations) | ||
+ | iptables -A INPUT -p udp --dport 500 --j ACCEPT | ||
+ | # for NAT-T (handling of IPsec between natted devices) | ||
+ | iptables -A INPUT -p udp --dport 4500 --j ACCEPT | ||
+ | # for ESP payload (the encrypted data packets) | ||
+ | iptables -A INPUT -p esp -j ACCEPT | ||
+ | # for the routing of packets on the server | ||
+ | iptables -t nat -A POSTROUTING -j SNAT --to-source %SERVERIP% -o eth+ | ||
+ | </ | ||
+ | |||
+ | Replace %SERVERIP% with the external IP of your VPS. If your external interface is not named ethX (+ is a wildcard) then rename appropriately. | ||
+ | |||
+ | Execute the below commands to enable kernel IP packet forwarding and disable ICP redirects. | ||
+ | |||
+ | <code bash> | ||
+ | echo " | ||
+ | echo " | ||
+ | echo " | ||
+ | echo " | ||
+ | echo " | ||
+ | echo " | ||
+ | echo " | ||
+ | </ | ||
+ | |||
+ | Set these settings for other network interfaces: | ||
+ | |||
+ | <code bash> | ||
+ | for vpn in / | ||
+ | </ | ||
+ | |||
+ | Apply them: | ||
+ | |||
+ | <code bash> | ||
+ | sysctl -p | ||
+ | </ | ||
+ | |||
+ | Persistent settings via / | ||
+ | |||
+ | To make sure this keeps working at boot you might want to add the following to / | ||
+ | |||
+ | <code bash / | ||
+ | for vpn in / | ||
+ | iptables -t nat -A POSTROUTING -j SNAT --to-source %SERVERIP% -o eth+ | ||
+ | iptables -A INPUT -p udp --dport 500 --j ACCEPT | ||
+ | iptables -A INPUT -p udp --dport 4500 --j ACCEPT | ||
+ | iptables -A INPUT -p esp -j ACCEPT | ||
+ | </ | ||
+ | |||
+ | Add it before the **exit 0** line and replace %SERVERIP% with the external IP of your server. | ||
+ | |||
+ | |||
+ | ===== Start the VPN ===== | ||
+ | |||
+ | All the configuration on the server is now done. Enable the VPN at startup: | ||
+ | |||
+ | <code bash> | ||
+ | systemctl enable strongswan | ||
+ | </ | ||
+ | |||
+ | And start it: | ||
+ | |||
+ | <code bash> | ||
+ | systemctl start strongswan | ||
+ | </ | ||
+ | |||
+ | If you get a permission denied error, stroke the files with apparmor: | ||
+ | |||
+ | <code bash> | ||
+ | apparmor_parser -R / | ||
+ | apparmor_parser -R / | ||
+ | </ | ||
+ | |||
+ | Check the status of the service: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec status | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | < | ||
+ | Security Associations (0 up, 0 connecting): | ||
+ | none | ||
+ | </ | ||
+ | |||
+ | And a more elaborate status: | ||
+ | |||
+ | <code bash> | ||
+ | ipsec statusall | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | |||
+ | < | ||
+ | Status of IKE charon daemon (strongSwan 5.1.2, Linux 4.2.0-21-generic, | ||
+ | uptime: 4 minutes, since Dec 20 15:51:48 2015 | ||
+ | malloc: sbrk 1814528, mmap 266240, used 758000, free 1056528 | ||
+ | worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 0 | ||
+ | loaded plugins: charon test-vectors curl unbound ldap pkcs11 aes rc2 sha1 sha2 md4 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp sshkey ipseckey pem gcrypt af-alg fips-prf gmp agent xcbc cmac hmac ctr ccm gcm ntru attr kernel-netlink resolve socket-default farp stroke updown eap-identity eap-aka eap-aka-3gpp2 eap-gtc eap-mschapv2 eap-dynamic eap-radius eap-tls eap-ttls eap-peap xauth-generic xauth-eap xauth-pam xauth-noauth tnc-imc tnc-tnccs tnccs-20 tnccs-11 tnccs-dynamic dhcp whitelist lookip error-notify certexpire led duplicheck radattr addrblock | ||
+ | Virtual IP pools (size/ | ||
+ | 10.42.42.0/ | ||
+ | 2002: | ||
+ | Listening IP addresses: | ||
+ | 85.222.224.56 | ||
+ | Connections: | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | Security Associations (0 up, 0 connecting): | ||
+ | none | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Client Configuration ===== | ||
+ | |||
+ | This VPN will therefore not work out of the box on older operating systems. | ||
+ | |||
+ | See the Strongswan Wiki [https:// | ||
+ | |||
+ | |||
+ | ===== References ===== | ||
+ | |||
+ | https:// | ||
+ | https:// | ||
network/vpn_-_strongswan.1575141461.txt.gz · Last modified: 2020/07/15 09:30 (external edit)