strongSwan to ASA Site-Site VPN

I wanted to write this one up more for memory but I think also good to share as I have looked at guides and they all seem incomplete.

So, let's look at the network layout:

So servers 1 and 2 are from some cheap hosting providers, and apart from the public IP address being closed, they don't share any network connection.

Then, at home, I have my network with an ASA firewall with a few different networks, but for now, I am only showing the production network, which we are worried about.

So what are we trying to achieve, simply have server 1 and server 2 be apart of the production network securely.

Server 1 Setup

Ubuntu 24.04.1 LTS
strongSwan swanctl 5.9.13 (wont go into detail of install, just the config)

strongSwan Config:

connections {
    asa {
        version = 2
        proposals = aes256-sha256-modp2048
        local_addrs = 198.20.10.1  # Public IP of server1
        remote_addrs = 10.10.10.1  # ASA firewall public IP

        local {
            auth = psk
            id = server1.domain.com
        }
        remote {
            auth = psk
                id = 10.10.10.1
        }

        children {
            net {
                local_ts = 192.168.70.102/32
                remote_ts = 192.168.30.0/24
                esp_proposals = aes256-sha256-modp2048
            }
        }
    }
}

secrets {
    ike-1 {
        id = server1.domain.com
        secret = YOUR_SHARED_SECRET_12345
    }
}

Network Config:

---
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
        addresses:
        - 198.20.10.1/24
        - 192.168.70.102/24
        nameservers:
            addresses:
            - 8.8.4.4
            - 1.1.1.1
            - 9.9.9.9
            search:
            - localhost
        routes:
        -   to: default
            via: 192.20.10.254
        set-name: eth0

Routes on server 1:

To get it out of the road, I added a static route to the server; I thought the VPN should have done this, and maybe it was just my configuration issue.

The command I run to add the route

ip route add 192.168.30.0/24 via 198.20.10.1

That's it. The config on server 1 and server 2 is pretty much the same and straightforward.

ASA Config

The fun part! Most of this I have been able to piece together from different sites and ChatGPT. (Side note: ChatGPT will take you down some wild rabbit holes, so watch out).

ASA firewall version is 9.8(2) on a ASA5506

First, let's look at the interfaces:

interface GigabitEthernet1/1
 nameif outside
 security-level 0
 ip address dhcp setroute
!
interface GigabitEthernet1/2.30
 vlan 30
 nameif production
 security-level 100
 ip address 192.168.30.200 255.255.255.0
!

Now we configure the VPN IKEv2 settings:

ASA(config)# crypto ikev2 policy 10
ASA(config-ikev2-policy)# encryption aes-256
ASA(config-ikev2-policy)# group 14
ASA(config-ikev2-policy)# prf sha
ASA(config-ikev2-policy)# lifetime seconds 86400

Next, we will do the IPsec settings:

ASA(config)# crypto ipsec ikev2 ipsec-proposal SERVER1_PROPOSAL
ASA(config-ipsec-proposal)# protocol esp encryption aes-256
ASA(config-ipsec-proposal)# protocol esp integrity sha-256

Now let's config an ACL

ASA(config)# access-list SERVER1_VPN extended permit ip 192.168.30.0 255.255.255.0 192.168.70.0 255.255.255.0

Let's combine it all together in a crypto map

ASA(config)# crypto map SERVER1_MAP 1 match address server1_vpn
ASA(config)# crypto map SERVER1_MAP 1 set peer 198.20.10.1
ASA(config)# crypto map SERVER1_MAP 1 set ikev2 ipsec-proposal SERVER1_PROPOSAL
ASA(config)# crypto map SERVER1_MAP interface outside

All this does is combine all the settings. Next, we have to set up the tunnel group and the authentication.

ASA(config)# tunnel-group 198.20.10.1 type ipsec-l2l
ASA(config)# tunnel-group 198.20.10.1 ipsec-attributes
ASA(config-tunnel-ipsec)# ikev2 local-authentication pre-shared-key YOUR_SHARED_SECRET_12345
ASA(config-tunnel-ipsec)# ikev2 remote-authentication pre-shared-key YOUR_SHARED_SECRET_12345

The second last thing to do is enable VPN on the interface.

ASA(config)# crypto ikev2 enable outside

At this point, everything told me to add a route to the firewall. I did that, and it never worked; I could never get the tunnel to come up. Then, I would see the following errors in the log:

Asymmetric NAT rules matched for forward and reverse flows; Connection for icmp src outside:192.168.70.102 dst production:192.168.30.103 (type 8, code 0) denied due to NAT reverse path failure

So what I figured out was that I applied the following NAT rule

object network server1 
  host 192.168.70.102
object network production_network 
  subnet 192.168.30.0 255.255.255.0
!
nat (outside,production) source static server1 server1 destination static production_network production_network no-proxy-arp

When I do a ping it doesn't work but I no longer get any errors.

So, back to server 1, and I run the --initiate command for strongSwan swanctl

swanctl --initiate --child net

Now the ping works!