Skip to content

Virtual Private Network (IPsec)

The following instructions will deploy a virtual machine acting as an edge VPN endpoint for IPsec site to site connection. It is based on StrongSwan which is a complete IPsec solution providing encryption and authentication to servers and clients. It can be used to secure communications with remote networks, so that connecting remotely is the same as connecting locally.

The full documentation is available here.

VPN example1 VPN example2

These 2 Public Cloud examples can be partly deployed using these two HEAT templates : vpn_simple.yaml & node.yaml

Once downloaded on your computer run this OpenStack command adjusting the parameters accordingly to your environment:

$ openstack stack create -t vpn_simple.yaml --parameter  key_name=yubikey-taylor test --wait
2022-04-19 07:18:37Z [test]: CREATE_IN_PROGRESS  Stack CREATE started
2022-04-19 07:18:37Z [test.dmz_security_group]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:38Z [test.dmz_security_group]: CREATE_COMPLETE  state changed
2022-04-19 07:18:38Z [test.random_password]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:38Z [test.random_password]: CREATE_COMPLETE  state changed
2022-04-19 07:18:39Z [test.dmz_router]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:40Z [test.nodes_net]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:40Z [test.nodes_net]: CREATE_COMPLETE  state changed
2022-04-19 07:18:40Z [test.nodes_subnet]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:41Z [test.nodes_group]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:41Z [test.nodes_group]: CREATE_COMPLETE  state changed
2022-04-19 07:18:41Z [test.nodes_subnet]: CREATE_COMPLETE  state changed
2022-04-19 07:18:42Z [test.sg_nodes]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:42Z [test.sg_nodes]: CREATE_COMPLETE  state changed
2022-04-19 07:18:42Z [test.sg_nodes_rule_dmz]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:42Z [test.sg_nodes_rule_udp]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:42Z [test.nodes]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:42Z [test.sg_nodes_rule_tcp]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:43Z [test.sg_nodes_rule_dmz]: CREATE_COMPLETE  state changed
2022-04-19 07:18:43Z [test.sg_nodes_rule_udp]: CREATE_COMPLETE  state changed
2022-04-19 07:18:43Z [test.sg_nodes_rule_tcp]: CREATE_COMPLETE  state changed
2022-04-19 07:18:43Z [test.dmz_net]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:43Z [test.dmz_net]: CREATE_COMPLETE  state changed
2022-04-19 07:18:43Z [test.dmz_subnet]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:43Z [test.dmz_router]: CREATE_COMPLETE  state changed
2022-04-19 07:18:43Z [test.dmz_router_nodes_patch]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:44Z [test.dmz_subnet]: CREATE_COMPLETE  state changed
2022-04-19 07:18:44Z [test.dmz_router_dmz_patch]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:47Z [test.dmz_router_nodes_patch]: CREATE_COMPLETE  state changed
2022-04-19 07:18:47Z [test.dmz_router_dmz_patch]: CREATE_COMPLETE  state changed
2022-04-19 07:18:47Z [test.dmzhost_port]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:49Z [test.dmzhost_port]: CREATE_COMPLETE  state changed
2022-04-19 07:18:49Z [test.dmzhost_port_floating_ip]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:52Z [test.dmzhost_port_floating_ip]: CREATE_COMPLETE  state changed
2022-04-19 07:18:52Z [test.sg_dmz_rule_self]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:52Z [test.dmzhost]: CREATE_IN_PROGRESS  state changed
2022-04-19 07:18:52Z [test.sg_dmz_rule_self]: CREATE_COMPLETE  state changed
2022-04-19 07:19:06Z [test.nodes]: CREATE_COMPLETE  state changed
2022-04-19 07:19:08Z [test.dmzhost]: CREATE_COMPLETE  state changed
2022-04-19 07:19:08Z [test]: CREATE_COMPLETE  Stack CREATE completed successfully
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| id                  | 8af838ef-8ddf-46fe-8c0c-6f794cf8e96a |
| stack_name          | test                                 |
| description         | No description                       |
| creation_time       | 2022-04-19T07:18:36Z                 |
| updated_time        | None                                 |
| stack_status        | CREATE_COMPLETE                      |
| stack_status_reason | Stack CREATE completed successfully  |
+---------------------+--------------------------------------+

Once the stack is created you can retrieve the vpn IP using for example this command:

openstack stack show test
+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| Field                 | Value                                                                                                                                            |
+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| id                    | 8af838ef-8ddf-46fe-8c0c-6f794cf8e96a                                                                                                             |
| stack_name            | test                                                                                                                                             |
| description           | No description                                                                                                                                   |
| creation_time         | 2022-04-19T07:18:36Z                                                                                                                             |
| updated_time          | None                                                                                                                                             |
| stack_status          | CREATE_COMPLETE                                                                                                                                  |
| stack_status_reason   | Stack CREATE completed successfully                                                                                                              |
| parameters            | OS::project_id: f8e2d506252c4961ad0fa321abf1f1b5                                                                                                 |
|                       | OS::stack_id: 8af838ef-8ddf-46fe-8c0c-6f794cf8e96a                                                                                               |
|                       | OS::stack_name: test                                                                                                                             |
|                       | dmz_flavor: a1-ram2-disk20-perf1                                                                                                                 |
|                       | key_name: yubikey-taylor                                                                                                                         |
|                       | nodes_flavor: a2-ram4-disk50-perf1                                                                                                               |
|                       | nodes_image: Debian 11.3 bullseye                                                                                                                |
|                       | public_network: ext-floating1                                                                                                                    |
|                       |                                                                                                                                                  |
| outputs               | - description: Floating IP of the VPN host                                                                                                       |
|                       |   output_key: dmz_public_ip                                                                                                                      |
|                       |   output_value: 195.15.246.193                                                                                                                   |
|                       | - description: For Windows servers only, login password                                                                                          |
|                       |   output_key: admin_pass                                                                                                                         |
|                       |   output_value:                                                                                                                                  |
|                       |   - ikP4NYAk                                                                                                                                     |
|                       |   - usns10xz                                                                                                                                     |
|                       | - description: Nodes ip addresses                                                                                                                |
|                       |   output_key: nodes_ips                                                                                                                          |
|                       |   output_value:                                                                                                                                  |
|                       |   - 10.0.0.137                                                                                                                                   |
|                       |   - 10.0.0.250                                                                                                                                   |
|                       |                                                                                                                                                  |
| links                 | - href: https://api.pub1.infomaniak.cloud/orchestration-api/v1/f8e2d506252c4961ad0fa321abf1f1b5/stacks/test/8af838ef-8ddf-46fe-8c0c-6f794cf8e96a |
|                       |   rel: self                                                                                                                                      |
|                       |                                                                                                                                                  |
| deletion_time         | None                                                                                                                                             |
| notification_topics   | []                                                                                                                                               |
| capabilities          | []                                                                                                                                               |
| disable_rollback      | True                                                                                                                                             |
| timeout_mins          | None                                                                                                                                             |
| stack_owner           | PCU-XDS7FSZ                                                                                                                                      |
| parent                | None                                                                                                                                             |
| stack_user_project_id | 78f32027adf44cf29e1303b1b12b1995                                                                                                                 |
| tags                  | []                                                                                                                                               |
|                       |                                                                                                                                                  |
+-----------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+

Now you can jump to the step 7 (7-configure-strongswan) for the example1 or to the step 4 (configure-the-windows-10-vpn) for the example 2

Example 1 : Site to site connection

In this example we will expose the private subnet 10.0.0.0/24 located inside the Public Cloud to an external server through an IPsec connection.

VPN example1

Create the network architecture required for this tutorial

1. Create the VPN network, subnet and router

taylor@laptop:~$ openstack router create vpn-router
taylor@laptop:~$ openstack network create vpn-network
taylor@laptop:~$ openstack subnet create vpn-subnet   --network vpn-network   --subnet-range 192.168.0.0/24   --gateway 192.168.0.1   --dns-nameserver 83.166.143.51   --dns-nameserver 83.166.143.52
taylor@laptop:~$ openstack router add subnet vpn-router vpn-subnet

2. connect the router VPN router to the internet

taylor@laptop:~$ openstack router set --external-gateway ext-floating1 vpn-router

3. Create the VM that will be the infomaniak VPN endpoint

taylor@laptop:~$ openstack server create --flavor  a2-ram4-disk20-perf1 --key-name yubikey-taylor --network vpn-network --image "Debian 11 bullseye" vpn

4. Create a Security Group and remove the default one

taylor@laptop:~$ openstack security group create vpn-securitygroup
taylor@laptop:~$ openstack security group rule create --protocol tcp --dst-port 22 --ethertype IPv4  vpn-securitygroup
taylor@laptop:~$ openstack security group rule create --protocol udp --dst-port 500 --ethertype IPv4  vpn-securitygroup
taylor@laptop:~$ openstack security group rule create --protocol udp --dst-port 4500 --ethertype IPv4  vpn-securitygroup
taylor@laptop:~$ openstack security group rule create --protocol esp --ethertype IPv4  vpn-securitygroup
taylor@laptop:~$ openstack server add security group vpn vpn-securitygroup
taylor@laptop:~$ openstack server remove security group vpn default

5. Add a Floating IP to the VPN VM

taylor@laptop:~$ openstack floating ip create ext-floating1
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| created_at          | 2021-09-21T11:04:49Z                 |
| description         |                                      |
| dns_domain          | None                                 |
| dns_name            | None                                 |
| fixed_ip_address    | None                                 |
| floating_ip_address | 195.15.244.244                       |
| floating_network_id | 0f9c3806-bd21-490f-918d-4a6d1c648489 |
| id                  | 157f41c9-eea3-4491-a827-63b306d53277 |
| name                | 195.15.244.244                       |
| port_details        | None                                 |
| port_id             | None                                 |
| project_id          | 1cd2e93b8a95454e906ff3bb2f99b103     |
| qos_policy_id       | None                                 |
| revision_number     | 0                                    |
| router_id           | None                                 |
| status              | DOWN                                 |
| subnet_id           | None                                 |
| tags                | []                                   |
| updated_at          | 2021-09-21T11:04:49Z                 |
+---------------------+--------------------------------------+

Associate the floating IP to the VM. Replace 195.15.244.244 accordingly to your setup

taylor@laptop:~$ openstack server add floating ip vpn 195.15.244.244

6. Install and configure StrongSwan

Connect to the VM created previously

taylor@laptop:~$ ssh debian@195.15.244.244
debian@vpn:~$ sudo apt update
debian@vpn:~$ sudo apt upgrade
debian@vpn:~$ sudo apt install strongswan strongswan-pki
debian@vpn:~$ sudo sysctl -w net.ipv4.conf.ens3.send_redirects=1
debian@vpn:~$ echo "1" | sudo tee /proc/sys/net/ipv4/ip_forward

Make the sysctl parameters persistent in case of reboot by editing /etc/sysctl.d/99-sysctl.conf as follow :

root@vpn:~# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 1

7. Configure StrongSwan

Edit the file /etc/ipsec.secrets and choose a strong PSK (Pre Shared Key).

# 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.
infomaniak-endpoint external-endpoint : PSK "Replace This with A very strong and very long string!"

Edit the file /etc/ipsec.conf and replace the IPs accordingly to your setup.

192.168.0.35 = infomaniak vpn VM local IP

195.15.226.142 = IP of the external endpoint

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
        # strictcrlpolicy=yes
        # uniqueids = no

# Add connections here.
conn infomaniak_VPN
    keyexchange=ikev2
    left=192.168.0.35
    leftsubnet=10.0.0.0/24
    leftid=infomaniak-endpoint
    leftfirewall=no
    leftsendcert=never
    right=195.15.226.142
    rightsubnet=10.135.0.0/24
    rightid=external-endpoint
    auto=route
    dpdaction=hold
    dpddelay=30s
    dpdtimeout=120s
    ike=aes128-sha256-modp1536
    ikelifetime=3600s
    esp=aes128-sha256-modp1536
    lifetime=3600s
    type=tunnel
    authby=psk

debian@vpn:~$ sudo ipsec restart
Starting strongSwan 5.9.1 IPsec [starter]...

debian@vpn:~$ sudo ipsec status
Routed Connections:
infomaniak_VPNaaS{1}:  ROUTED, TUNNEL, reqid 1
infomaniak_VPNaaS{1}:   0.0.0.0/32 === 0.0.0.0/32
Security Associations (0 up, 0 connecting):
  none
The connection won't be up until we configure the other side.

8. Configure the other side the same way but inverse left and right entries. Also in the ipsec.secrets

root@external-endpoint-vm:~# cat /etc/ipsec.conf
# ipsec.conf - strongSwan IPsec configuration file

config setup

conn %default
        keylife=20m
        rekeymargin=3m
        keyingtries=1
        mobike=no

# basic configuration
conn infomaniak_VPN
    keyexchange=ikev2
    leftfirewall=no
    left=195.15.226.142
    leftsubnet=10.135.0.0/24
    leftid=external-endpoint
    right=195.15.244.244
    rightsubnet=10.0.0.0/24
    rightid=infomaniak-endpoint
    auto=route
    dpdaction=hold
    dpddelay=30s
    dpdtimeout=120s
    ike=aes128-sha256-modp1536
    ikelifetime=3600s
    esp=aes128-sha256-modp1536
    lifetime=3600s
    type=tunnel
    authby=psk
root@external-endpoint-vm:~# cat /etc/ipsec.secrets
# which knows the public part.
external-endpoint infomaniak-endpoint : PSK "Replace This with A very strong and very long string!"

9. Bring up the VPN connection

debian@vpn:~$ sudo ipsec up infomaniak_VPN

10. We add rule allowing the vpn VM to forward the traffic from the remote subnet

taylor@laptop:~$ VM_PORT=$(openstack port list --server vpn -c id -f value)
taylor@laptop:~$ openstack port set --allowed-address ip-address=10.135.0.0/24 ${VM_PORT}

11. We create a static route on the vpn router so the traffic from the local subnets to the remote subnet goes through the VPN

taylor@laptop:~$ openstack router add route --route destination=10.135.0.0/24,gateway=192.168.0.35 vpn-router

At this point the private VM should be accessible from the external endpoint.

12. Exposing a private subnet to the VPN

In this example the subnet 10.0.0.0/24 will be accesible from the external-endpoint. Let's create it and also create a VM on this subnet to confirm it works.

taylor@laptop (pub1|taylor):~$ openstack network create ik-private-net-1
taylor@laptop (pub1|taylor):~$ openstack subnet create ik-private-subnet-1   --network ik-private-net-1   --subnet-range 10.0.0.0/24   --gateway 10.0.0.1   --dns-nameserver 83.166.143.51   --dns-nameserver 83.166.143.52
taylor@laptop (pub1|taylor):~$ openstack router add subnet vpn-router  ik-private-subnet-1
taylor@laptop (pub1|taylor):~$ openstack server create --flavor  a2-ram4-disk20-perf1 --key-name yubikey-taylor --network ik-private-net-1 --image "Debian 11 bullseye" ik-private-subnet-1-vm-1
taylor@laptop (pub1|taylor):~$ openstack security group rule create --protocol tcp --dst-port 22 --ethertype IPv4  default
taylor@laptop (pub1|taylor):~$ openstack security group rule create --protocol icmp default

Example 2 : Site to win10 client ikev2 connnection

VPN example2

Assuming you followed step 1 to 6 of the previous Example :

1. Generate the certificates

root@vpn:~# mkdir -p /root/strongswan-pki/{cacerts,certs,private}
root@vpn:~# chmod 600 /root/strongswan-pki/
root@vpn:~# pki --gen --type rsa --size 4096 --outform pem > /root/strongswan-pki/private/ca-key.pem
root@vpn:~# pki --self --ca --lifetime 3650 --in /root/strongswan-pki/private/ca-key.pem --type rsa --dn "CN=StrongSwan VPN root CA" --outform pem > /root/strongswan-pki/cacerts/ca-cert.pem
root@vpn:~# pki --gen --type rsa --size 4096 --outform pem >  /root/strongswan-pki/private/server-key.pem
root@vpn:~# pki --pub --in  /root/strongswan-pki/private/server-key.pem --type rsa | pki --issue --lifetime 1825 \
        --cacert  /root/strongswan-pki/cacerts/ca-cert.pem --cakey  /root/strongswan-pki/private/ca-key.pem \
        --dn "CN=195.15.244.244" --san 195.15.244.244 --san @195.15.244.244 \
        --flag serverAuth --flag ikeIntermediate --outform pem > /root/strongswan-pki/certs/server-cert.pem

Copy the certificates in the /etc/ipsec.d directory

root@vpn:~# cp -r  /root/strongswan-pki/* /etc/ipsec.d/

2. Configure the ikev2 StrongSwan connection

Add this in /etc/ipsec.conf to configure the ikev2 connection. Change the IPs accordingly to your setup

conn ikev2
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=195.15.244.244
    leftcert=server-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightsourceip=10.0.0.0/24
    rightdns=83.166.143.51,83.166.143.52
    rightsendcert=never
    eap_identity=%identity

edit /etc/ipsec.secrets to add the private key name and to add users and passwords, in our case we add the user taylor

: RSA "server-key.pem"
taylor : EAP "My_veRy_Str0NG_paSsword!"
root@vpn:~# ipsec restart

3. Configure iptables

root@vpn# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o ens3 -m policy --pol ipsec --dir out -j ACCEPT
root@vpn# iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o ens3 -j MASQUERADE

4. Configure the Windows 10 VPN

Copy/Paste the full content of /etc/ipsec.d/cacerts/ca-cert.pem somewhere on the win10 client computer for, example C:\ik\ik-vpn-ca-cert.pem

Open an admin powerShell and import the certificate

Import-Certificate  -CertStoreLocation cert:\LocalMachine\Root\  -FilePath C:\ik\ik-vpn-ca-cert.pem

5. Create the VPN connection

Add-VpnConnection -Name "Infomaniak VPN Connection"
    -ServerAddress "195.15.244.244"
    -TunnelType "IKEv2" 
    -AuthenticationMethod "EAP" 
    -EncryptionLevel "Maximum" 
    -RememberCredential

You should see a new VPN connection available. Press WINDOWS+Q and search for VPN settings. You should then see your connection, click conenct and you' ll be prompted for user/password configured earlier.

VPN example1

You might need to adjust the routing on the windows client side, for example

Get the VPN network intefarce ID

PS C:\WINDOWS\system32> Get-NetIPInterface

Then add the route

PS C:\WINDOWS\system32> New-NetRoute -DestinationPrefix "10.0.0.0/24"  -InterfaceIndex 80