# How to configure strongSwan client on headless Debian-based Linux computer
## Requirements
- [Self-hosted hardened strongSwan IKEv2/IPsec VPN server](../how-to-self-host-hardened-strongswan-ikev2-ipsec-vpn-server-for-ios-and-macos) 📦
- Linux or macOS computer (referred to as “certificate authority computer”)
- Debian-based Linux computer (referred to as “client computer”)
## Caveats
- When copy/pasting commands that start with `$`, strip out `$` as this character is not part of the command
- When copy/pasting commands that start with `cat << "EOF"`, select all lines at once (from `cat << "EOF"` to `EOF` inclusively) as they are part of the same (single) command
## Guide
### Step 1: create client certs using certificate authority from [How to self-host hardened strongSwan IKEv2/IPsec VPN server for iOS and macOS](../how-to-self-host-hardened-strongswan-ikev2-ipsec-vpn-server-for-ios-and-macos) (using certificate authority computer).
#### Navigate to `strongswan-certs` folder
```shell
cd ~/Desktop/strongswan-certs
```
#### Set client common name
```shell
STRONGSWAN_CLIENT_COMMON_NAME=bob@vpn-server.com
```
#### Update OpenSSL config file
```shell
cat << EOF > openssl.cnf
[ req ]
distinguished_name = req_distinguished_name
attributes = req_attributes
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
countryName_default = US
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Self-hosted strongSwan VPN
commonName = Common Name (eg, fully qualified host name)
commonName_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[ ca ]
subjectKeyIdentifier = hash
basicConstraints = critical, CA:true
keyUsage = critical, cRLSign, keyCertSign
[ server ]
authorityKeyIdentifier = keyid
subjectAltName = DNS:vpn-server.com
extendedKeyUsage = serverAuth, 1.3.6.1.5.5.8.2.2
[ client ]
authorityKeyIdentifier = keyid
subjectAltName = email:$STRONGSWAN_CLIENT_COMMON_NAME
extendedKeyUsage = serverAuth, 1.3.6.1.5.5.8.2.2
EOF
```
#### Generate client cert
```
$ openssl genrsa -out bob.key 4096
Generating RSA private key, 4096 bit long modulus
..............................++
....................................................................................................++
e is 65537 (0x10001)
$ openssl req -new -config openssl.cnf -extensions client -key bob.key -subj "/C=US/O=Self-hosted strongSwan VPN/CN=$STRONGSWAN_CLIENT_COMMON_NAME" -out bob.csr
$ openssl x509 -req -extfile openssl.cnf -extensions client -in bob.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out bob.crt
Signature ok
subject=/C=US/O=Self-hosted strongSwan VPN/CN=bob@vpn-server.com
Getting CA Private Key
```
### Step 2: log in to client computer
Replace `pi@10.0.1.69` with SSH destination of client computer and `~/.ssh/pi` with path to associated private key.
```shell
ssh pi@10.0.1.69 -i ~/.ssh/pi
```
### Step 3: switch to root
```shell
su -
```
### Step 4: configure iptables
> Heads-up: input rules are likely already configured (run `iptables-save` and `ip6tables-save` to check).
#### Configure IPv4 rules
```shell
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p udp --dport 500 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp --dport 4500 -m state --state NEW -j ACCEPT
```
#### Configure IPv6 rules (if network is dual stack)
```shell
ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p udp --dport 500 -m state --state NEW -j ACCEPT
ip6tables -A OUTPUT -p udp --dport 4500 -m state --state NEW -j ACCEPT
```
#### Make iptables rules persistent
```shell
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
```
### Step 5: update APT index
```shell
apt update
```
### Step 6: install strongSwan
If you are shown an “Old runlevel management superseded” warning, answer “Ok”.
```shell
apt install -y strongswan libcharon-extra-plugins
```
### Step 7: configure strongSwan
#### Backup and override `/etc/ipsec.conf`
Replace `185.193.126.203` with IP of server.
```shell
cp /etc/ipsec.conf /etc/ipsec.conf.backup
cat << EOF > /etc/ipsec.conf
conn ikev2
auto=start
ike=aes256gcm16-prfsha512-ecp384!
esp=aes256gcm16-ecp384!
dpdaction=restart
closeaction=restart
keyingtries=%forever
leftid=bob@vpn-server.com
leftsourceip=%config
leftauth=eap-tls
leftcert=bob.crt
right=185.193.126.203
rightid=vpn-server.com
rightsubnet=0.0.0.0/0
rightauth=pubkey
EOF
```
#### Backup and override `/etc/ipsec.secrets`
```shell
cp /etc/ipsec.secrets /etc/ipsec.secrets.backup
cat << "EOF" > /etc/ipsec.secrets
: RSA bob.key
EOF
```
#### Disable unused plugins
```shell
cd /etc/strongswan.d/charon
sed -i 's/load = yes/load = no/' ./*.conf
sed -i 's/load = no/load = yes/' ./eap-tls.conf ./aes.conf ./dhcp.conf ./farp.conf ./gcm.conf ./hmac.conf ./kernel-netlink.conf ./nonce.conf ./openssl.conf ./pem.conf ./pgp.conf ./pkcs12.conf ./pkcs7.conf ./pkcs8.conf ./pubkey.conf ./random.conf ./revocation.conf ./sha2.conf ./socket-default.conf ./stroke.conf ./x509.conf
cd -
```
### Step 8: copy/paste content of `ca.crt`, `bob.key` and `bob.crt` to server and make private key root-only.
On certificate authority computer: run `cat ca.crt`
On client computer: run `vi /etc/ipsec.d/cacerts/ca.crt`, press i, paste output from previous step in window, press esc and press shift+z+z
On certificate authority computer: run `cat bob.key`
On client computer: run `vi /etc/ipsec.d/private/bob.key`, press i, paste output from previous step in window, press esc and press shift+z+z
On certificate authority computer: run `cat bob.crt`
On client computer: run `vi /etc/ipsec.d/certs/bob.crt`, press i, paste output from previous step in window, press esc and press shift+z+z
On client computer: run `chmod -R 600 /etc/ipsec.d/private`
### Step 9: restart strongSwan
```shell
systemctl restart strongswan
```
### Step 10: confirm strongSwan client is connected
```shell
$ ipsec status
Security Associations (1 up, 0 connecting):
ikev2[1]: ESTABLISHED 3 minutes ago, 10.0.1.69[bob@vpn-server.com]...185.193.126.203[vpn-server.com]
ikev2{1}: INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c3fcabed_i c2b0c4cd_o
ikev2{1}: 10.0.2.199/32 === 0.0.0.0/0
```
ESTABLISHED
đź‘Ť
> Heads-up: use following steps to assign static IP to strongSwan client
### Step 11: log in to server
Replace `185.193.126.203` with IP of server.
```shell
ssh vpn-server-admin@185.193.126.203 -i ~/.ssh/vpn-server
```
### Step 12: switch to root
```shell
su -
```
### Step 13: get virtual MAC address assigned to strongSwan client
> Heads-up: run `ipsec status` as root on headless Debian-based Linux computer to see which IP was assigned to strongSwan client (`10.0.2.199` in the following example).
```shell
$ cat /var/lib/misc/dnsmasq.leases | grep "10.0.2.199" | awk '{print $2}'
7a:a7:3b:4b:77:16
```
### Step 14: assign static IP to strongSwan client
```shell
echo "dhcp-host=7a:a7:3b:4b:77:16,10.0.2.2" >> /etc/dnsmasq.d/01-dhcp-strongswan.conf
```
### Step 15: restart dnsmasq
```shell
systemctl restart dnsmasq
```
### Step 16: log in to client computer
Replace `pi@10.0.1.69` with SSH destination of client computer and `~/.ssh/pi` with path to associated private key.
```shell
ssh pi@10.0.1.69 -i ~/.ssh/pi
```
### Step 17: switch to root
```shell
su -
```
### Step 18: restart strongSwan
```shell
systemctl restart strongswan
```
### Step 19: confirm strongSwan client has IP `10.0.2.2`
```shell
$ ipsec status
Security Associations (1 up, 0 connecting):
ikev2[1]: ESTABLISHED 3 minutes ago, 10.0.1.69[bob@vpn-server.com]...185.193.126.203[vpn-server.com]
ikev2{1}: INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: c3fcabed_i c2b0c4cd_o
ikev2{1}: 10.0.2.5/32 === 0.0.0.0/0
```
10.0.2.2/32
đź‘Ť