IPSec VPNs or really any site-to-site VPN works best when at least one of the sides or better yet both have Public IP addresses.  But what if one is behind NAT, or even both?  It gets increasing tricky to configure the correct IP addresses for authentication, and forward correct ports on protocols.  As I recently discovered, using IKEv2 and/or GRE further complicates things.  Consider this setup:

IPSecVPNsBehindNATs

Both routers are behind NAT/PAT firewalls without static 1-to-1 NATs configured.  There are still some requirements though:

  • Both firewalls must allow for protocol 50 passthrough for IPSec, or protocol 47 passthough if using GRE, which most do
  • At least one side must be forwarding ports udp/500 (isakmp) and udp/4500 (nat-t) to the router’s internet-facing interface so the connection can be established
  • Both routers need crypto ipsec nat-transparency udp-encapsulation enabled, which is the default setting

Let’s look at sample configs for each scenario.  These assume 1921 ISR G2 routers but IOS-XE configs should be exactly the same.

IPSec with ISAKMP / IKEv1

The is the simplest way to do it since only public IPs need to be referenced.

1) The ISAKMP portion:

! Send keepalives every 10 seconds
crypto isakmp invalid-spi-recovery
crypto isakmp keepalive 10 5
crypto isakmp nat keepalive 10

! Policy supporting strong encryption
crypto isakmp policy 100
 encr aes 256               ! 256-bit AES encryption
 hash sha384                ! SHA-384 hashing
 authentication pre-share   ! Using pre-shared keys
 lifetime 28800             ! 28000 seconds = 8 hours
 group 14                   ! group 14 = 2048 bit key
! Backup policy supporting weaker encryption support for older devices
crypto isakmp policy 200
 encr aes                   ! 128-bit AES encryption
 hash sha                   ! SHA-1 hashing
 authentication pre-share   ! Using pre-shared keys
 lifetime 28800             ! 28000 seconds = 8 hours
 group 2                    ! group 2 = 1024 bit key

! FYI - default values are still des, sha, rsa-sig, 86400, group 1 :-O

2) And then pre-shared keys:

! Key for site 1 router
crypto keyring Site2
  local-address GigabitEthernet0/0
  pre-shared-key address 203.0.113.222 key 0 MySecretKey

! Key for site 2 router
crypto keyring Site1
 local-address GigabitEthernet0/0
 pre-shared-key address 198.51.100.111 key 0 MySecretKey

! Can also use "crypto isakmp key 0 MySecretKey address 1.2.3.4"

3) IPSec parameters.  For encryption, I like to just use 128-bit AES with either SHA-256 or SHA-1 signing with a group 2 (1024-bit) key to make the tunnel negotiation quick as possible.

! Create some IPSec Transform sets for ESP & 128-bit AES
crypto ipsec transform-set ESP_AES128_SHA256_TUNNEL esp-aes esp-sha256-hmac 
 mode tunnel
crypto ipsec transform-set ESP_AES128_SHA1_TUNNEL esp-aes esp-sha-hmac 
 mode tunnel

! Create IPSec profile
crypto ipsec profile MY_IPSEC_PROFILE
 set transform-set ESP_AES128_SHA256_TUNNEL ESP_AES128_SHA1_TUNNEL 
 set pfs group2    ! group 2 = 1024-bit key

Optional step: since the “client” side isn’t reachable on port udp/500, the “server” side may be configured as a responder.  This cuts down superfluous traffic, especially when the client is unreachable.

crypto ipsec profile MY_IPSEC_PROFILE
 responder-only

5) The last step is build the tunnel interfaces.  For the “client” side:

interface Tunnel1000
 ip address 169.254.0.1 255.255.255.252
 ip tcp adjust-mss 1379
 keepalive 10 3
 tunnel source GigabitEthernet0/0
 tunnel mode ipsec ipv4
 tunnel destination 203.0.113.222
 tunnel protection ipsec profile MY_IPSEC_PROFILE

Server side is exactly the same but with different IP addresses:

interface Tunnel1000
 ip address 169.254.0.2 255.255.255.252
 tunnel destination 198.51.100.111

Doing debug crypto isakmp on the server side while the tunnels come up shows the public IP address of the client.  Note the client’s random source ports.

ISAKMP (0): received packet from 198.51.100.111 dport 500 sport 14972 Global (R) MM_SA_SETUP
ISAKMP (1003): received packet from 198.51.100.111 dport 4500 sport 51597 Global (R) MM_KEY_EXCH
ISAKMP (1003): received packet from 198.51.100.111 dport 4500 sport 51597 Global (R) MM_KEY_EXCH
ISAKMP:(1003):SA has been authenticated with 198.51.100.111
ISAKMP:(1003):Detected port floating to port = 51597

We never see client’s private IP, but we do see the server side’s private IP at the end when the SA is finally built:

ISAKMP:(1003): Process initial contact,
bring down existing phase 1 and 2 SA's with local 192.168.2.222 remote 198.51.100.111 remote port 51597
ISAKMP: Trying to insert a peer 192.168.2.222/198.51.100.111/51597/, and inserted successfully

Can also see the other site’s private IP by examining the SAs once built:

Site1#show crypto isakmp peers 203.0.113.222
Peer: 203.0.113.222 Port: 4500 Local: 192.168.1.111
Phase1 id: 192.168.2.222

Site2#show crypto isakmp peers 198.51.100.111
Peer: 198.51.100.111 Port: 51597 Local: 192.168.2.222
Phase1 id: 192.168.1.111

 

IPSec with IKEv2

IKEv2 is new to me, but it was a surprise to see slightly different behavior when using NAT. Run through of the configuration:

1) Set some global IKEv2 parameters

crypto logging ikev2
crypto ikev2 nat keepalive 30
! NAT keepalives are enabled by default w/ 10 sec interval

2) Create and IKEv2 Proposal and Policy for encryption settings

3) Keys are defined in the IKEv2 keyring, which has each site’s public IP address:

crypto ikev2 keyring MY_IKEV2_KEYRING
 ! Use this on site 1 router
 peer Site2
  address 203.0.113.222
  pre-shared-key MySecretKey1234    ! Must be 16 chars or longer
 ! Use this on site 2 router
 peer Site1
  address 198.51.100.111
  pre-shared-key MySecretKey1234    ! Must be 16 chars or longer

4) Create IKEv2 Profile

crypto ikev2 profile MY_IKEV2_PROFILE
 match address local interface GigabitEthernet0/0
 match identity remote address 192.168.0.0 255.255.0.0
 authentication remote pre-share
 authentication local pre-share
 keyring local MY_IKEV2_KEYRING
 dpd 20 2 periodic

This is where is gets weird because the “remote address” parameter needs to match the internal IP address(es) of the other sides.  The simple and lazy approach is use 0.0.0.0 since that will match anything.  The other option is use a different profile for each peer.

5) Add IKEv2 profile to the existing IPSec profile.  Note that doing so shouldn’t break IKEv1 clients as the IKEv2 stuff should just be ignored.

crypto ipsec profile MY_IPSEC_PROFILE
 set transform-set ESP_AES128_SHA256_TUNNEL ESP_AES128_SHA1_TUNNEL 
 set pfs group2
 set ikev2-profile MY_IKEV2_PROFILE

In the SAs, we can see our private IP,  but not the other side’s:

Site1#show crypto ikev2 sa remote 203.0.113.222
Tunnel-id Local                 Remote                fvrf/ivrf            Status
1         192.168.1.111/4500    203.0.113.222/4500    none/none            READY  
      Encr: AES-CBC, keysize: 128, Hash: SHA256, DH Grp:14, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/30 sec

Site2#sh crypto ikev2 sa remote 198.51.100.111      
Tunnel-id Local                 Remote                fvrf/ivrf            Status 
1         192.168.2.222/4500    198.51.100.111/51597  none/none            READY  
      Encr: AES-CBC, keysize: 128, Hash: SHA256, DH Grp:14, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/71 sec
Advertisements