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!