Site-to-site IPSec VPN between strongSwan(AWS) and Cisco Router(On-premise)
Published: 2023-12-28 01:27:59

---
title: Site-to-site IPSec VPN between strongSwan(AWS) and Cisco Router(On-premise)
published: true
description:strongSwan is an open source project, which was launched in 2005 as a fork of the discontinued FreeS/WAN open source project. In this post, we connect strongSwan on AWS with on-premise Cisco router.
canonical_url: https://hello-vpn.com/blog/site-to-site-ipsec-vpn-between-strongswan-aws-and-cisco-router-on-premise
series: "site-to-site IPSec VPN"
---

## 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](https://wp.hello-vpn.com/wp-content/uploads/2023/12/image-1024x441.png) 

| **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
```

## 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
```

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
```

### 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
```

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
   }
}
```

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
```

## 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
```

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
```

## 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
```

### 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
````

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
```

### 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
```

## 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
```

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
```

## 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
```

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
```

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>
```

## 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)](https://www.cisco.com/c/en/us/support/docs/ip/internet-key-exchange-ike/117258-config-l2l.html)

[strongSwan official doc example of site-to-site IKEv1](https://www.strongswan.org/testing/testresults/ikev1/net2net-psk/)

[Migrate from ipsec.conf to swanctl.conf](https://wiki.strongswan.org/projects/strongswan/wiki/Fromipsecconf)

[https://techtalksecurity.blogspot.com/2022/12/configure-ipsec-site-to-site-vpn-in.html?m=1](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/](https://www.tecmint.com/setup-ipsec-vpn-with-strongswan-on-debian-ubuntu/)