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:
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 126.96.36.199"
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
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
BTW, if NAT-T has been disabled but is required by the other end, debug crypto ikev2 will show this:
Oct 12 19:53:08.620: IKEv2-ERROR:(SESSION ID = 1075,SA ID = 2): NAT is found but it is not supported.: NAT-T disabled via cli Oct 12 19:53:08.620: IKEv2-ERROR:(SESSION ID = 1075,SA ID = 2):: NAT-T disabled via cli