DEV Community

Quinn
Quinn

Posted on • Originally published at hello-vpn.com

Site-to-site IPSec VPN between strongSwan(AWS) and Cisco Router(On-premise)

Introduction

strongSwan is an open source project, which was launched in 2005 as a fork of the discontinued FreeS/WAN open source project.

The strongSwan VPN suite uses the native IPsec stack in the standard Linux kernel. It supports both the IKEv1 and IKEv2 protocols.

It is a comprehensive implementation of the Internet Key Exchange (IKE) protocols that allows securing IP traffic in policy- and route-based IPsec scenarios from simple to very complex.

In this post, we connect strongSwan on AWS with on-premise Cisco router. I think it\'s an interesting scenario, because first, it applies to many companies who have their IT infrastructures on AWS; Second, there are very few tutorials cover this topic.

As well, most existing strongSwan examples online are using the deprecated ipsec.conf method. We will use the recommended swanctl method.

We use IKEv1 in this tutorial, because despite it is officially deprecated recently, it\'s still the de-facto set up nowadays.

We will show IKEv2 examples in the future posts.

Network diagram

The left side(mumbai) is using strongSwan hosted on AWS, and the right side(france) is using on-premise Cisco router. There is also NAT configured, because site-to-site VPN between different companies usually require the encryption domain to use public IP address.

network diagram

IP Info Left side(mumbai) Right side(france)
VPN device/sw strongSwan 5.9.8 /Debian 12 Cisco C931-4P
VPN GW IP 35.154.207.104 31.xxx.xxx.48
Encryption Domain (VPN host or subnet) 3.6.74.40 (NAT to 192.168.0.88) 31.xxx.xxx.89 (NAT to 192.168.1.2)

IPSec parameters

Phase I Settings 
Authentication Method Pre-Shared
Diffie-Helman Group 2 (Mod1024)
Encryption Algorithm AES256
Hash Algorithm SHA-1
SA Timeout 28800
NAT-T Enabled
Phase II Settings 
Encapsulation ESP (encrypted)
Perfect Forward Secrecy (PFS) NO PFS
Encryption Algorithm AES256
Hash Algorithm SHA-1
Lifetime (In Seconds) 3600 (Default)

Notes for AWS

IP address

We need to keep in mind that an AWS instance does not know the Elastic IP associated with its network interface. It only knows the internal IP inside the subnet that the network interface belongs to.

Therefore, in our example, strongSwan instance is only aware of IP 192.168.0.33.

Disable Src/Dest check

For strongSwan instance, disable src/dest check on it\'s main network interface.

The reason? Check below quote from AWS doc:

You can enable or disable source/destination checks, which ensure that the instance is either the source or the destination of any traffic that it receives. Source/destination checks are enabled by default.

You must disable source/destination checks if the instance runs services such as network address translation, routing, or firewalls.

Security group

The security group of strongSwan instance need to have below 2 rules enabled:

  • allow incoming from 0.0.0.0 to UDP port 4500
  • allow incoming from 0.0.0.0 to UDP port 500

Installation(mumbai site)


apt install strongswan charon-systemd
Enter fullscreen mode Exit fullscreen mode

Set linux kernel parameters(mumbai site)

Edit /etc/sysctl.conf

# /etc/sysctl.conf

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0

# Do not send ICMP redirects (we are not a router)
#net.ipv4.conf.all.send_redirects = 0

### also add below two lines, otherwise ping test will not work, replace enX0 with your own interface
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.enX0.send_redirects = 0
Enter fullscreen mode Exit fullscreen mode

Disable the send_redirect on the affected network interface is important, because without it, the ping test will not work.

Below is the explanation from strongSwan doc:

If the VPN gateway is not the default gateway of the LAN, ICMP redirects might get returned to hosts if they send traffic destined for the remote hosts/subnets to the VPN gateway, directing them to the default gateway of the LAN (which probably doesn’t work and otherwise might get that traffic out unencrypted). To avoid this, disable sending such ICMP messages by setting

net.ipv4.conf.all.send_redirects=0 net.ipv4.conf.default.send_redirects=0

If the latter option is not set before the network interface comes up, also set the option for the individual interface

net.ipv4.conf.<iface>.send_redirects=0

load the new setting

root@ip-192-168-0-33:~# sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.enX0.send_redirects = 0
Enter fullscreen mode Exit fullscreen mode

Configure NAT (Network Address Translation)

First, create the file to define network rules.

iptables-save > /etc/iptables.rules

Then add below rules in /etc/iptables.rules

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -d 3.6.74.40/32 -m comment --comment incoming-from-remote-host -j DNAT --to-destination 192.168.0.88
-A POSTROUTING -s 192.168.0.88/32 -d 31.xxx.xxx.89/32 -m comment --comment outgoing-to-remote-host -j SNAT --to-source 3.6.74.40
Enter fullscreen mode Exit fullscreen mode

Run below command to update iptables

iptables-restore < /etc/iptables.rules

strongSwan VPN configuration(mumbai site)

/etc/swanctl/swanctl.conf

# default settings for all conns (e.g cert, IP pools)
conn-defaults {
      version = 1
      reauth_time = 28800
      proposals = aes256-sha1-modp1024
}

# default settings for all child configs (e.g. traffic selectors)
child-defaults {
      mode = tunnel
      start_action = trap|start
      rekey_time = 3600
}

connections {
   mumbai-france : conn-defaults {
      local_addrs  = 192.168.0.33
      remote_addrs = 31.xxx.xxx.48
      proposals = aes256-sha1-modp1024

      local {
         auth = psk
         id = 35.154.207.104
      }
      remote {
         auth = psk
         id = 31.xxx.xxx.48
      }
      children {
         mumbai-france1 : child-defaults {
            local_ts  = 3.6.74.40/32
            remote_ts = 31.xxx.xxx.89/32
        start_action = trap|start
            esp_proposals = aes256-sha1
         }
      }
   }

}

secrets {
   ike-1 {
      # a - local, b - remote
      id-1b = 31.xxx.xxx.48
      secret = ANsvU5WIwmQ6
   }
}
Enter fullscreen mode Exit fullscreen mode

Note:

  • local_addrs = 192.168.0.33, remember AWS instance does not know it\'s own Elastic IP address, therefore here we put the internal IP

Cisco VPN configuration (france on-premise)

crypto isakmp policy 100
 encr aes 256
 authentication pre-share
 group 2
crypto isakmp key ANsvU5WIwmQ6
!
crypto ipsec transform-set vpn-sha1-aes256 esp-aes 256 esp-sha-hmac
 mode tunnel
!
crypto map francemap 2 ipsec-isakmp
 set peer 35.154.207.104
 set transform-set vpn-sha1-aes256
 match address TEST-MUMBAI-SS
!
ip nat inside source static 192.168.1.2 31.xxx.xxx.89
!
ip access-list extended TEST-MUMBAI-SS
 permit ip host 31.xxx.xxx.89 host 3.6.74.40
Enter fullscreen mode Exit fullscreen mode

strongSwan start daemon

systemctl start strongswan

# for each modification on the connection, run below two command
swanctl --load-all #load preshared key and conn
swanctl --initiate --child mumbai-france1
Enter fullscreen mode Exit fullscreen mode

The output of --initiate command is something like below if it\'s successful:

swanctl --initiate --child mumbai-france1
[ENC] generating QUICK_MODE request 2568099685 [ HASH SA No ID ID ]
[NET] sending packet: from 192.168.0.33[4500] to 31.xxx.xxx.48[4500] (172 bytes)
[NET] received packet: from 31.xxx.xxx.48[4500] to 192.168.0.33[4500] (204 bytes)
[ENC] parsed QUICK_MODE response 2568099685 [ HASH SA No ID ID N((24576)) ]
[CFG] selected proposal: ESP:AES_CBC_256/HMAC_SHA1_96/NO_EXT_SEQ
[IKE] CHILD_SA mumbai-france1{54} established with SPIs c21634ca_i 8dbd1a12_o and TS 3.6.74.40/32 === 31.xxx.xxx.89/32
[ENC] generating QUICK_MODE request 2568099685 [ HASH ]
[NET] sending packet: from 192.168.0.33[4500] to 31.xxx.xxx.48[4500] (60 bytes)
initiate completed successfully
Enter fullscreen mode Exit fullscreen mode

Verify VPN Status

Verify strongSwan config

swanctl --list-conns

mumbai-france: IKEv1, reauthentication every 28800s
  local:  192.168.0.33
  remote: 31.xxx.xxx.48
  local pre-shared key authentication:
    id: 35.154.207.104
  remote pre-shared key authentication:
    id: 31.xxx.xxx.48
  mumbai-france1: TUNNEL, rekeying every 3600s
    local:  3.6.74.40/32
    remote: 31.xxx.xxx.89/32
Enter fullscreen mode Exit fullscreen mode

Verify strongSwan VPN status

<pre class="wp-block-code" has-small-font-size="">```


swanctl --list-sas
mumbai-france: #53, ESTABLISHED, IKEv1, 99405922d34109cd_i b9f401ec6e3f603c_r*
  local  '35.154.207.104' @ 192.168.0.33[4500]
  remote '31.xxx.xxx.48' @ 31.xxx.xxx.48[4500]
  AES_CBC-256/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
  established 8915s ago, reauth in 18254s
  mumbai-france1: #54, reqid 2, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-256/HMAC_SHA1_96
    installed 984s ago, rekeying in 2412s, expires in 2976s
    in  c21634ca,   2940 bytes,    35 packets,    34s ago
    out 8dbd1a12,   2940 bytes,    35 packets,    34s ago
    local  3.6.74.40/32
    remote 31.xxx.xxx.89/32


Enter fullscreen mode Exit fullscreen mode

We can also use below command to request detailed information about the IPsec SAs and policies installed in the kernel.



ip -s xfrm state
ip -s xfrm policy


Enter fullscreen mode Exit fullscreen mode

Verify Cisco VPN status



# show crypto isakmp sa
IPv4 Crypto ISAKMP SA
dst             src             state          conn-id status
35.154.207.104  31.xxx.xxx.48     QM_IDLE           1223 ACTIVE
31.xxx.xxx.48     35.154.207.104  QM_IDLE           1224 ACTIVE


# show crypto session brief
Status: A- Active, U - Up, D - Down, I - Idle, S - Standby, N - Negotiating
        K - No IKE
ivrf = (none)
Peer            I/F          Username        Group/Phase1_id          Uptime   Status
35.154.207.104  Gi4                          35.154.207.104           00:22:41 UA
35.154.207.104  Gi4                          35.154.207.104           00:22:41 UA


Enter fullscreen mode Exit fullscreen mode

Routing

The hosts behind the VPN GW need to route remote host\'s IP via the VPN GW.

On the left side (mumbai), the host app-L will add route like this:



ip route add 31.xxx.xxx.89 via 192.168.0.33


Enter fullscreen mode Exit fullscreen mode

And on the right side (france), host app-R has route like this:



ip route add 3.6.74.40 via 192.168.1.1


Enter fullscreen mode Exit fullscreen mode

Test

We will ping from app-L (192.168.0.88) to app-R (192.168.1.2)



ping 31.xxx.xxx.89
PING 31.xxx.xxx.89 (31.xxx.xxx.89) 56(84) bytes of data.
64 bytes from 31.xxx.xxx.89: icmp_seq=1 ttl=62 time=152 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=2 ttl=62 time=152 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=3 ttl=62 time=152 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=4 ttl=62 time=152 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=5 ttl=62 time=152 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=6 ttl=62 time=153 ms
64 bytes from 31.xxx.xxx.89: icmp_seq=7 ttl=62 time=152 ms


Enter fullscreen mode Exit fullscreen mode

To verify that those traffic are indeed getting encrypted and decrypted via the VPN tunnel, we can check the counter on both strongSwan and Cisco.

on strongSwan instance, run swanctl --list-sas, and observe the number of in and out packets, it should increase while doing the ping test.



swanctl --list-sas
mumbai-france: #53, ESTABLISHED, IKEv1, 99405922d34109cd_i b9f401ec6e3f603c_r*
  local  '35.154.207.104' @ 192.168.0.33[4500]
  remote '31.xxx.xxx.48' @ 31.xxx.xxx.48[4500]
  AES_CBC-256/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_1024
  established 8915s ago, reauth in 18254s
  mumbai-france1: #54, reqid 2, INSTALLED, TUNNEL-in-UDP, ESP:AES_CBC-256/HMAC_SHA1_96
    installed 984s ago, rekeying in 2412s, expires in 2976s
    in  c21634ca,   2940 bytes,    35 packets,    34s ago
    out 8dbd1a12,   2940 bytes,    35 packets,    34s ago
    local  3.6.74.40/32
    remote 31.xxx.xxx.89/32


Enter fullscreen mode Exit fullscreen mode

On Cisco side, observe as well the Inbound and Outbound packets increase.



# show crypto session detail

Interface: GigabitEthernet4
Uptime: 00:19:19
Session status: UP-ACTIVE
Peer: 35.154.207.104 port 4500 fvrf: (none) ivrf: (none)
      Phase1_id: 35.154.207.104
      Desc: (none)
  Session ID: 0
  IKEv1 SA: local 31.xxx.xxx.48/4500 remote 35.154.207.104/4500 Active
          Capabilities:N connid:1223 lifetime:21:28:43
  Session ID: 0
  IKEv1 SA: local 31.xxx.xxx.48/4500 remote 35.154.207.104/4500 Active
          Capabilities:N connid:1224 lifetime:06:17:20
  IPSEC FLOW: permit ip host 31.xxx.xxx.89 host 3.6.74.40
        Active SAs: 4, origin: crypto map
       <strong> Inbound:  #pkts dec'ed 2121 drop 0 life (KB/Sec) 4344779/2452
        Outbound: #pkts enc'ed 2121 drop 0 life (KB/Sec) 4344779/2452</strong>


Enter fullscreen mode Exit fullscreen mode

Conclusion

It\'s relatively easy to create a standard site-to-site IPSec VPN using strongSwan if you check documentation carefully.

Cost-wise, this is a very interesting option for small companies who only require VPN connection occasionally for some projects.

References

Cisco document: example config between strongSwan and Cisco router (IKEv1 and IKEv2)

strongSwan official doc example of site-to-site IKEv1

Migrate from ipsec.conf to swanctl.conf

https://techtalksecurity.blogspot.com/2022/12/configure-ipsec-site-to-site-vpn-in.html?m=1

https://www.tecmint.com/setup-ipsec-vpn-with-strongswan-on-debian-ubuntu/

Top comments (0)