Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| install_24_4_strongswan [2026/01/11 13:04] – [Install StrongSwan] system | install_24_4_strongswan [2026/01/12 06:08] (current) – [Create PKI] system | ||
|---|---|---|---|
| Line 6: | Line 6: | ||
| * The following instructions should work well on any of the recent versions of StrongSwan | * The following instructions should work well on any of the recent versions of StrongSwan | ||
| + | ----------- | ||
| ===== Install StrongSwan | ===== Install StrongSwan | ||
| * As stated on the StrongSwan Primer wiki page, StrongSwan has gone through an aggressive redesign and you should take care when installing it not to install the older legacy version. | * As stated on the StrongSwan Primer wiki page, StrongSwan has gone through an aggressive redesign and you should take care when installing it not to install the older legacy version. | ||
| Line 51: | Line 52: | ||
| </ | </ | ||
| * As you can see it has the **charon-systemd** program running. | * As you can see it has the **charon-systemd** program running. | ||
| - | |||
| ------ | ------ | ||
| + | ===== Create PKI ===== | ||
| + | * Next we will create the PKI. | ||
| + | * We need to install a helper package that is part of StrongSwan first. | ||
| + | <code bash> | ||
| + | sudo apt-get install strongswan-pki | ||
| + | </ | ||
| + | * We issue the following commands. | ||
| + | <code bash> | ||
| + | mkdir -p ~/ | ||
| + | chmod 700 ~/pki | ||
| + | cd ~/pki | ||
| + | #Create the CA Certificate | ||
| + | pki --gen --type rsa --size 4096 --outform pem > ca/ca.key | ||
| + | pki --self --ca --lifetime 3650 --in ca/ca.key --type rsa --dn " | ||
| + | |||
| + | #Create the server certificate: | ||
| + | pki --gen --type rsa --size 4096 --outform pem > private/ | ||
| + | pki --issue --lifetime 825 --in private/ | ||
| + | |||
| + | #Create a client certificate | ||
| + | pki --gen --type rsa --size 4096 --outform pem > private/ | ||
| + | pki --issue --lifetime 825 --in private/ | ||
| + | |||
| + | #View it | ||
| + | pki --print --in certs/ | ||
| + | |||
| + | </ | ||
| + | <WRAP center round tip 100%> | ||
| + | * StrongSwan has some very good documentation on managing certificates | ||
| + | * https:// | ||
| + | </ | ||
| + | |||
| + | |||
| + | -------- | ||
| + | ===== Configure Swanctl | ||
| + | * The way we configure StrongSwan is again a bit different compared to the ' | ||
| + | * With StrongSwan we have the **/ | ||
| + | * Inside this folder are various sub-folders that are pre-installed. | ||
| + | * This setup relies strong on convention where **swanctl** expect certain items to be located under certain folders. | ||
| + | * We also have the **swanctl.conf** config file which we will cover in this section. | ||
| + | |||
| + | --------- | ||
| + | ==== Config File ==== | ||
| + | * The config file has a JSON like structure. | ||
| + | * Please note that it is not valid JSON but rather a JSON like structure. | ||
| + | * Below is our demo server' | ||
| + | <code JavaScript> | ||
| + | connections { | ||
| + | xfrm-gw { | ||
| + | |||
| + | local_addrs = %any | ||
| + | remote_addrs = %any | ||
| + | pools = rw_pool | ||
| + | # XFRM interface binding - CRITICAL | ||
| + | if_id_in = 100 | ||
| + | if_id_out = 100 | ||
| + | version = 2 | ||
| + | proposals = aes128-sha1-modp2048 | ||
| + | local { | ||
| + | auth = pubkey | ||
| + | certs = server.crt | ||
| + | id = cloud.radiusdesk.com | ||
| + | } | ||
| + | remote { | ||
| + | auth = pubkey | ||
| + | } | ||
| + | children { | ||
| + | xfrm-gw { | ||
| + | local_ts | ||
| + | remote_ts = 0.0.0.0/0 | ||
| + | if_id_in | ||
| + | if_id_out = 100 | ||
| + | esp_proposals = aes128-sha1-modp2048 | ||
| + | start_action = start | ||
| + | dpd_action = restart | ||
| + | } | ||
| + | } | ||
| + | send_cert = always | ||
| + | dpd_delay = 30s | ||
| + | rekey_time = 1h | ||
| + | # | ||
| + | } | ||
| + | } | ||
| + | pools { | ||
| + | rw_pool { | ||
| + | addrs = 10.3.1.0/16 | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ------------ | ||
| + | ==== Cert and Key Files ==== | ||
| + | * As we stated there are some pre-installed sub folders under the **/ | ||
| + | * The following should be used to contain the CA, server cert and server key files. | ||
| + | * Copy the **ca.crt** file to **/ | ||
| + | * Copy the **server.key** file to **/ | ||
| + | * Copy the **server.crt** file to **/ | ||
| + | |||
| + | ---------- | ||
| + | ===== Xfrm Interface Prep ===== | ||
| + | * When a client connects establishes a connection to the StrongSwan server, it is referred to as a Security Association (SA). | ||
| + | * We can use the swanctl command to see if there are any existing SAs. | ||
| + | <code bash> | ||
| + | sudo swanctl --list-sa | ||
| + | xfrm-gw: #11, ESTABLISHED, | ||
| + | local ' | ||
| + | remote ' | ||
| + | AES_CBC-128/ | ||
| + | established 679s ago, rekeying in 2626s | ||
| + | xfrm-gw: #7, reqid 1, INSTALLED, TUNNEL-in-UDP, | ||
| + | installed 1372s ago, rekeying in 2128s, expires in 2588s | ||
| + | in c9f9936f (-|0x00000064), | ||
| + | out c33bfaa6 (-|0x00000064), | ||
| + | local 0.0.0.0/0 | ||
| + | remote 0.0.0.0/0 | ||
| + | </ | ||
| + | * We implement a route based IPsec VPN (The other option is policy based). | ||
| + | * Route based IPsec specify a **if_id_in** and **if_id_out**. | ||
| + | * This is used to tag traffic inside a SA. | ||
| + | * With Wireguard, you can have multiple instances running on different ports. | ||
| + | * With StrongSwan there is one instance, but you can have multiple connections defined in the config file each using a unique **if_id_in** and **if_id_out**. | ||
| + | * The **if_id_in** and **if_if_out** in tern have to terminate into a **xfrm** interface. | ||
| + | * We will create a startup script that prepare this interface for us **BEFORE** we start StrongSwan. | ||
| + | * Create the file **/ | ||
| + | * We assume eth0 is the interface name where the server gets it Internet from. Please adapt if your server is different. | ||
| + | <code bash> | ||
| + | #!/bin/sh | ||
| + | set -e | ||
| + | # | ||
| + | IFACE=xfrm0 | ||
| + | IF_ID=100 | ||
| + | ADDR=10.3.0.1/ | ||
| + | SUBNET=10.3.0.0/ | ||
| + | |||
| + | # Create XFRM interface | ||
| + | ip link show " | ||
| + | ip link add " | ||
| + | |||
| + | # Assign IP | ||
| + | ip addr show " | ||
| + | ip addr add " | ||
| + | |||
| + | # Bring interface up | ||
| + | ip link set " | ||
| + | |||
| + | # Route for remote side | ||
| + | ip route show " | ||
| + | ip route add " | ||
| + | |||
| + | # ---- NAT via nftables ---- | ||
| + | |||
| + | # Create table if missing | ||
| + | nft list table ip nat >/ | ||
| + | nft add table ip nat | ||
| + | |||
| + | # Create postrouting chain if missing | ||
| + | nft list chain ip nat postrouting >/ | ||
| + | nft add chain ip nat postrouting { type nat hook postrouting priority 100\; } | ||
| + | |||
| + | # Add SNAT/ | ||
| + | nft list chain ip nat postrouting | grep -q " | ||
| + | nft add rule ip nat postrouting oifname " | ||
| + | nft add rule ip nat postrouting oifname " | ||
| + | |||
| + | </ | ||
| + | * Create a startup script called **/ | ||
| + | <code bash> | ||
| + | [Unit] | ||
| + | Description=XFRM Interface xfrm0 | ||
| + | Before=strongswan.service | ||
| + | Wants=network-online.target | ||
| + | After=network-online.target | ||
| + | |||
| + | [Service] | ||
| + | Type=oneshot | ||
| + | ExecStart=/ | ||
| + | RemainAfterExit=yes | ||
| + | |||
| + | [Install] | ||
| + | WantedBy=multi-user.target | ||
| + | </ | ||
| + | * Enable the startup script and start it up | ||
| + | <code bash> | ||
| + | systemctl enable xfrm0 | ||
| + | systemctl start xfrm0 | ||
| + | </ | ||
| + | * Everything is now prepared on the server side. | ||
| + | * We can now configure clients in APdesk and MESHdesk to route certain traffic through the IPsec tunnel. | ||
| + | * These are covered in a dedicated Wiki page. | ||