Use the native IPsec stack to connect multiple networks over the internet.
I will connect three different networks over the internet using IPsec tunnels.
Hostname | IP address | Network |
---|---|---|
antioch | 192.0.2.10 | 172.16.32.0/20 |
cadmus | 192.0.2.20 | 172.16.30.0/23 |
ignotus | 192.0.2.30 | 172.16.48.0/20 |
Requirements
Install the strongSwan package.
$ sudo apt install strongswan
Remember to allow traffic on port 500 protocol UDP between above-mentioned nodes.
Generate secrets
I am using the OpenSSL utility to generate a base64-encoded secret.
$ openssl rand -base64 64 | paste --delimiters '' --serial FITSy9dGK9BlOOrOqOi3xRaWjMPgR9KQtT0GaPiBaKQ7LcYniHsdsSA78iEy8BmOGAXpkVi7Imp9dZeHfJPptA==
This solution is beautiful in its simplicity.
Store secrets
Define left (local) and right (remote) IP addresses and a secret for each tunnel. Notice that the secret needs to be the same on both sides.
antioch
connects to ignotus
and cadmus
.
antioch$ sudo cat /etc/ipsec.secrets
# This file holds shared secrets or RSA private keys for authentication. # RSA private key for this host, authenticating it to any other host # which knows the public part. 192.0.2.10 192.0.2.30 : PSK "CfSzOwEc7A/IMg1AZnFG5ynMlm2cFL0Gy8Jt3K67edaPv2s5Zq+Zg4Lc+kaI7+0NygIkeXgYxe/XqXf1u8aXVQ==" 192.0.2.10 192.0.2.20 : PSK "Qc8okLcA28CLIx0ZKvRCznqpFKc2iHxqX9sMIe0hXV9HHgF9xRWzqm/pzKbZbwnajaOrqeKt5eAQ6Q6LjtqGVw=="
cadmus
connects to antioch
and ignotus
.
cadmus$ sudo cat /etc/ipsec.secrets
# This file holds shared secrets or RSA private keys for authentication. # RSA private key for this host, authenticating it to any other host # which knows the public part. 192.0.2.20 192.0.2.10 : PSK "Qc8okLcA28CLIx0ZKvRCznqpFKc2iHxqX9sMIe0hXV9HHgF9xRWzqm/pzKbZbwnajaOrqeKt5eAQ6Q6LjtqGVw==" 192.0.2.20 192.0.2.30 : PSK "nJ3FlzqXFPwmlQAEK71jjfI6ynFGuzJbd+IAWYgl/rXs6s4+4ECgsJjPn0PH0BlAovQuJEY5p5WnrxRoix/6UQ=="
ignotus
connects to antioch
and cadmus
.
ignotus$ sudo cat /etc/ipsec.secrets
# This file holds shared secrets or RSA private keys for authentication. # RSA private key for this host, authenticating it to any other host # which knows the public part. 192.0.2.30 192.0.2.10 : PSK "CfSzOwEc7A/IMg1AZnFG5ynMlm2cFL0Gy8Jt3K67edaPv2s5Zq+Zg4Lc+kaI7+0NygIkeXgYxe/XqXf1u8aXVQ==" 192.0.2.30 192.0.2.20 : PSK "nJ3FlzqXFPwmlQAEK71jjfI6ynFGuzJbd+IAWYgl/rXs6s4+4ECgsJjPn0PH0BlAovQuJEY5p5WnrxRoix/6UQ=="
IPsec configuration
Define left (local) and right (remote) IP addresses and corresponding subnets.
antioch
connects to ignotus
and cadmus
.
antioch$ sudo cat /etc/ipsec.conf
conn antioch-to-ignotus authby=secret auto=route left=192.0.2.10 leftsubnet=172.16.32.1/20 right=192.0.2.30 rightsubnet=172.16.48.1/20 mobike=no conn antioch-to-cadmus authby=secret auto=route left=192.0.2.10 leftsubnet=172.16.32.1/20 right=192.0.2.20 rightsubnet=172.16.30.1/23 mobike=no
cadmus
connects to antioch
and ignotus
.
cadmus$ sudo cat /etc/ipsec.conf
conn cadmus-to-antioch authby=secret auto=route left=192.0.2.20 leftsubnet=172.16.30.1/23 right=192.0.2.10 rightsubnet=172.16.32.1/20 mobike=no conn cadmus-to-ignotus authby=secret auto=route left=192.0.2.20 leftsubnet=172.16.30.1/23 right=192.0.2.30 rightsubnet=172.16.48.1/20 mobike=no
ignotus
connects to antioch
and cadmus
.
ignotus$ sudo cat /etc/ipsec.conf
conn ignotus-to-antioch authby=secret auto=route left=192.0.2.30 leftsubnet=172.16.48.1/20 right=192.0.2.10 rightsubnet=172.16.32.1/20 mobike=no conn ignotus-to-cadmus authby=secret auto=route left=192.0.2.30 leftsubnet=172.16.48.1/20 right=192.0.2.20 rightsubnet=172.16.30.1/23 mobike=no
Manage IPsec service
Start and enable service on each node.
$ systemctl enable --now strongswan-starter.service Created symlink /etc/systemd/system/multi-user.target.wants/strongswan-starter.service → /lib/systemd/system/strongswan-starter.service.
Inspect service status.
ignotus$ sudo systemctl status strongswan-starter.service ● strongswan-starter.service - strongSwan IPsec IKEv1/IKEv2 daemon using ipsec.conf Loaded: loaded (/lib/systemd/system/strongswan-starter.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2020-11-26 21:09:25 UTC; 45s ago Main PID: 3955246 (starter) Tasks: 18 (limit: 38404) Memory: 4.4M CGroup: /system.slice/strongswan-starter.service ├─3955246 /usr/lib/ipsec/starter --daemon charon --nofork └─3955264 /usr/lib/ipsec/charon Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] IKE_SA ignotus-to-cadmus[3] established between 192.0.2.30[192.0.2.30]...192.0.2.20[192.0.2.20] Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] IKE_SA ignotus-to-cadmus[3] established between 192.0.2.30[192.0.2.30]...192.0.2.20[192.0.2.20] Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] scheduling reauthentication in 10050s Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] maximum IKE_SA lifetime 10590s Nov 26 21:10:04 ignotus charon[3955264]: 15[CFG] selected proposal: ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] CHILD_SA ignotus-to-cadmus{5} established with SPIs c3331638_i c7020e9a_o and TS 172.16.48.0/20 === 172.16.30.0/23 Nov 26 21:10:04 ignotus charon[3955264]: 15[IKE] CHILD_SA ignotus-to-cadmus{5} established with SPIs c3331638_i c7020e9a_o and TS 172.16.48.0/20 === 172.16.30.0/23 Nov 26 21:10:04 ignotus charon[3955264]: 15[ENC] generating IKE_AUTH response 1 [ IDr AUTH SA TSi TSr N(AUTH_LFT) ] Nov 26 21:10:04 ignotus charon[3955264]: 15[NET] sending packet: from 192.0.2.30[500] to 192.0.2.20[500] (208 bytes)
Done.
Additional notes
Use ipsec
utility to inspect and manage IPsec tunnels.
ignotus$ ipsec --help ipsec command [arguments] Commands: start|restart [arguments] update|reload|stop up|down|route|unroute <connectionname> down-srcip <start> [<end>] status|statusall [<connectionname>] listalgs|listpubkeys|listcerts [--utc] listcacerts|listaacerts|listocspcerts [--utc] listacerts|listgroups|listcainfos [--utc] listcrls|listocsp|listplugins|listall [--utc] listcounters|resetcounters [name] leases [<poolname> [<address>]] rereadsecrets|rereadcacerts|rereadaacerts rereadocspcerts|rereadacerts|rereadcrls|rereadall purgecerts|purgecrls|purgeike|purgeocsp scepclient|pki stroke version Refer to the ipsec(8) man page for details. Some commands have their own man pages, e.g. pki(1) or scepclient(8).
Inspect each connection as an example.
ignotus$ sudo ipsec statusall Status of IKE charon daemon (strongSwan 5.8.2, Linux 5.4.0-54-generic, x86_64): uptime: 91 seconds, since Nov 26 21:09:25 2020 malloc: sbrk 2703360, mmap 0, used 725472, free 1977888 worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 7 loaded plugins: charon aesni aes rc2 sha2 sha1 md5 mgf1 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem openssl fips-prf gmp agent xcbc hmac gcm drbg attr kernel-netlink resolve socket-default connmark stroke updown eap-mschapv2 xauth-generic counters Listening IP addresses: 192.0.2.30 172.16.48.1 Connections: ignotus-to-antioch: 192.0.2.30...192.0.2.10 IKEv1/2 ignotus-to-antioch: local: [192.0.2.30] uses pre-shared key authentication ignotus-to-antioch: remote: [192.0.2.10] uses pre-shared key authentication ignotus-to-antioch: child: 172.16.48.0/20 === 172.16.32.0/20 TUNNEL ignotus-to-cadmus: 192.0.2.30...192.0.2.20 IKEv1/2 ignotus-to-cadmus: local: [192.0.2.30] uses pre-shared key authentication ignotus-to-cadmus: remote: [192.0.2.20] uses pre-shared key authentication ignotus-to-cadmus: child: 172.16.48.0/20 === 172.16.30.0/23 TUNNEL Routed Connections: ignotus-to-cadmus{2}: ROUTED, TUNNEL, reqid 2 ignotus-to-cadmus{2}: 172.16.48.0/20 === 172.16.30.0/23 ignotus-to-antioch{1}: ROUTED, TUNNEL, reqid 1 ignotus-to-antioch{1}: 172.16.48.0/20 === 172.16.32.0/20 Security Associations (2 up, 0 connecting): ignotus-to-cadmus[3]: ESTABLISHED 52 seconds ago, 192.0.2.30[192.0.2.30]...192.0.2.20[192.0.2.20] ignotus-to-cadmus[3]: IKEv2 SPIs: 25288d3b98dde4d6_i f88d38bed2635b45_r*, pre-shared key reauthentication in 2 hours ignotus-to-cadmus[3]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_AES128_XCBC/ECP_256 ignotus-to-cadmus{5}: INSTALLED, TUNNEL, reqid 2, ESP SPIs: c3331638_i c7020e9a_o ignotus-to-cadmus{5}: AES_CBC_128/HMAC_SHA2_256_128, 58309 bytes_i (368 pkts, 0s ago), 166072 bytes_o (420 pkts, 0s ago), rekeying in 42 minutes ignotus-to-cadmus{5}: 172.16.48.0/20 === 172.16.30.0/23 ignotus-to-antioch[1]: ESTABLISHED 90 seconds ago, 192.0.2.30[192.0.2.30]...192.0.2.10[192.0.2.10] ignotus-to-antioch[1]: IKEv2 SPIs: d4ae22aaf88b0bab_i e8a8007af4fdcb26_r*, pre-shared key reauthentication in 2 hours ignotus-to-antioch[1]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_AES128_XCBC/ECP_256 ignotus-to-antioch{3}: INSTALLED, TUNNEL, reqid 1, ESP SPIs: cc91bd1d_i c64aaa36_o ignotus-to-antioch{3}: AES_CBC_128/HMAC_SHA2_256_128, 1550 bytes_i (20 pkts, 2s ago), 13783 bytes_o (27 pkts, 2s ago), rekeying in 40 minutes ignotus-to-antioch{3}: 172.16.48.0/20 === 172.16.32.0/20
Inspect routes.
$ ip r get 172.16.32.1 172.16.32.1 via 192.0.2.10 dev eth0 table 220 src 172.16.48.1 uid 0 cache
$ ip r show table 220 172.16.30.0/23 via 192.0.2.20 dev eth0 proto static src 172.16.48.1 172.16.32.0/20 via 192.0.2.10 dev eth0 proto static src 172.16.48.1