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