Policy-Based VPNs on Cisco ISRs when behind NAT

A couple years ago I wrote a post about route-based IPSec VPNs involving NAT-T on Cisco Routers. However today I had to setup a lab environment using policy-based VPNs. This was a real blast from past as I hadn’t done a policy-based VPN on a Cisco router since the late 1990s :-O

VPN Parameters:

  • Local side, private IP of external interface of router: 192.0.2.2
  • Local side, private IP subnet 192.168.100.0/24
  • Local side, public IP address: 198.18.51.78
  • Remote side, public IP address: 203.0.113.161
  • Remote side, private IP subnet: 10.13.0.0/16
  • Pre-shared key: MySecretKey1234
  • Phase 1 encryption and lifetime: AES-256, SHA-384, Group 14, 1 day
  • Phase 2 encryption and lifetime: AES-128, SHA-1, Group 2, 1 hour

With both IKEv1 or v2, you’ll want to start by verifying NAT-T is enabled, which is the default setting. This will allow the router to detect behind behind NAT and tunnel traffic on udp/4500 rather than using regular ESP (protocol 50):

crypto ipsec nat-transparency udp-encapsulation

If the other side is expecting or requiring NAT-T and it’s been disabled, Cisco IOS will log this warning:

%IKEV2-3-NEG_ABORT: Negotiation aborted due to ERROR: NAT-T disabled via cli

IKEv1

As with route-based VPN, I start by setting some global ISAKMP parameters:

crypto isakmp disconnect-revoked-peers
crypto isakmp invalid-spi-recovery
crypto isakmp keepalive 30 2 on-demand
crypto isakmp nat keepalive 900

The ISAKMP policy defines global encryption and authentication settings.

! 256-bit AES + SHA2-384 + PFS Group14 (2048-bit key)
crypto isakmp policy 100
 encr aes 256
 hash sha384
 authentication pre-share
 group 14
 lifetime 86400              ! 1 day, which is the default
!

Configure authentication for the peer by defining a keyring, specifying the public IP of the remote side. Then create an ISAKMP profile, again specifying the remote’s public IP and the local’s external interface:

crypto keyring CRYPTO_KEYRING
  local-address GigabitEthernet0/0
  pre-shared-key address 203.0.113.161 key MySecretKey1234
!
crypto isakmp profile ISAKMP_PROFILE
   keyring CRYPTO_KEYRING
   match identity address 203.0.113.161 255.255.255.255 
   local-address GigabitEthernet0/0
!

Now the crypto map, which replaces the crypto ipsec profile of route-based VPNs. I’m just using the typical encryption settings of 128-bit AES/SHA-1/Group2 PFS. The access-list must be defined to match “interesting” traffic to send across the VPN.

! LOCAL = 192.168.100.0/24.   REMOTE = 10.13.0.0/16
access-list 101 permit ip 192.168.100.0 0.0.0.255 10.13.0.0 0.0.255.255
!
crypto ipsec security-association replay window-size 1024
crypto ipsec df-bit clear
!
crypto ipsec transform-set ESP_AES128_SHA esp-aes esp-sha-hmac 
 mode tunnel
!
crypto map CRYPTO_MAP 1 ipsec-isakmp 
 set peer 203.0.113.161
 set security-association lifetime seconds 3600      ! 1 hour, which is the default
 set transform-set ESP_AES128_SHA
 set pfs group2
 match address 101
 reverse-route
!

Finish by applying the crypto map to the external interface:

ip route 0.0.0.0 0.0.0.0 192.0.2.1
!
interface GigabitEthernet0/0
 ip address 192.0.2.2 255.255.255.0
 crypto map CRYPTO_MAP
!
interface GigabitEthernet0/1
 ip address 192.168.100.100 255.255.255.0
!

Send a ping that matches the interesting traffic. Make sure to use an interface that’s with the source IP range specific on the ACL referenced by the Crypto Map.

Router# ping 10.13.113.11 source Gi0/1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.13.113.11, timeout is 2 seconds:
Packet sent with a source address of 192.168.100.100 
.!!!!
Success rate is 80 percent (4/5), round-trip min/avg/max = 68/71/72 ms

Verify IPSEC SAs are up:

Router# show crypto ipsec sa peer 203.0.113.161

interface: GigabitEthernet0/0
    Crypto map tag: CRYPTO_MAP, local addr 192.0.2.2

   protected vrf: (none)
   local  ident (addr/mask/prot/port): (192.168.100.0/255.255.255.0/0/0)
   remote ident (addr/mask/prot/port): (10.13.0.0/255.255.0.0/0/0)
   current_peer 203.0.113.161 port 4500
     PERMIT, flags={origin_is_acl,}
    #pkts encaps: 4, #pkts encrypt: 4, #pkts digest: 4
    #pkts decaps: 4, #pkts decrypt: 4, #pkts verify: 4

IKEv2

I always start IKEv2 configuration with some global settings:

crypto ikev2 nat keepalive 900
crypto ikev2 dpd 30 2 on-demand
crypto logging ikev2

As with route-based VPN, configure an IKEv2 proposal and policy. Here’s a broad one that should match anything with reason:

crypto ikev2 proposal IKEV2_PROPOSAL
 encryption aes-cbc-256 aes-cbc-128 3des
 integrity sha512 sha384 sha256 sha1
 group 21 20 19 16 14 2
!
crypto ikev2 policy IKEV2_POLICY 
 match fvrf any
 proposal IKEV2_PROPOSAL
!

Create a keyring entry for the other side specifying their public IP, then an IKEv2 profile. If the other side is expecting to see the public IP address, configure that with the identity local address option. The match identity remote address must match their IKEv2 remote ID. This usually will be the public IP, but may require the private IP if they are also behind NAT and not overriding.

crypto ikev2 keyring IKEV2_KEYRING
 peer TEST1
  address 203.0.113.161
  pre-shared-key MySecretKey1234
 !
crypto ikev2 profile IKEV2_PROFILE
 match address local interface GigabitEthernet0/0
 match identity remote address 203.0.113.161     ! Other side's remote ID
 identity local address 198.51.100.78            ! My public IP
 authentication local pre-share
 authentication remote pre-share
 keyring local IKEV2_KEYRING
 dpd 60 5 on-demand             ! override global DPD setting, if desired
!

Crypto map is same as IKEv1 (see above), just with the IKEv2 profile specified:

crypto map CRYPTO_MAP 1 ipsec-isakmp 
 set ikev2-profile IKEV2_PROFILE
!

Finally apply crypto map to external interface. The IKEv2 SA should pop up within a few seconds.

*Feb 26 22:07:41 PST: %IKEV2-5-SA_UP: SA UP

Verify details of the IKEv2 SA:

Router# show crypto ikev2 sa remote 203.0.113.161 detailed 
 IPv4 Crypto IKEv2  SA 

Tunnel-id Local                 Remote                fvrf/ivrf            Status 
1         192.0.2.2/4500        203.0.113.161/4500    none/none            READY  
      Encr: AES-CBC, keysize: 256, PRF: SHA384, Hash: SHA384, DH Grp:14, Auth sign: PSK, Auth verify: PSK
      Life/Active Time: 86400/115 sec
      CE id: 1007, Session-id: 4
      Status Description: Negotiation done
      Local spi: 55543FD20BD46FA2       Remote spi: 03B6B07E9090FCF2
      Local id: 192.0.2.2
      Remote id: 10.113.13.2
      Local req msg id:  0              Remote req msg id:  14        
      Local next msg id: 0              Remote next msg id: 14        
      Local req queued:  0              Remote req queued:  14        
      Local window:      5              Remote window:      1         
      DPD configured for 10 seconds, retry 2
      Fragmentation not  configured.
      Extended Authentication not configured.
      NAT-T is detected inside 
      Cisco Trust Security SGT is disabled
      Initiator of SA : No

 IPv6 Crypto IKEv2  SA

As with IKEv1, the final step is verify the IPSEC SA.

Advertisement

FortiGate 60-E not supporting AES-GCM in Hardware

On a previous post I’d recommended using AES-GCM on VPNs to AWS and GCP since it’s generally a more efficient algorithm that offers higher throughput. So it came as a surprised today doing some deep-diving on my Fortigate 60-E today: AES-GCM is supported for Phase 2, it is not supported in hardware on the NPU:

FGT60ETK18XXXXXX # get vpn ipsec tunnel details
 gateway
   name: 'aws1'
   type: route-based
   local-gateway: 198.51.100.78:4500 (static)
   remote-gateway: 3.140.149.245:4500 (static)
   mode: ike-v1
   interface: 'wan1' (5)
   rx  packets: 52  bytes: 6524  errors: 0
   tx  packets: 110  bytes: 6932  errors: 3
   dpd: on-demand/negotiated  idle: 20000ms  retry: 3  count: 0
   nat traversal mode: keep-alive   RFC 3947   interval: 10
   selectors
     name: 'aws1'
     auto-negotiate: disable
     mode: tunnel
     src: 0:0.0.0.0/0.0.0.0:0
     dst: 0:0.0.0.0/0.0.0.0:0
     SA
       lifetime/rekey: 3600/3289   
       mtu: 1438
       tx-esp-seq: 2
       replay: enabled
       qat: 0
       inbound
         spi: 7dbc0283
         enc:  aes-gc  35a72036fa9a87000c90415b1863827652bf9dfd875f28a6d20fd1569e5c0099de639dcc
         auth:   null  
       outbound
         spi: ccdb6ab8
         enc:  aes-gc  21dd5c71a83142b0ecee1efe2c000c0dae586054160eb76df6f338d9071380b12103b0d9
         auth:   null  
       NPU acceleration: none

FGT60ETK18XXXXXX # get vpn ipsec stats crypto
NPU Host Offloading:
     Encryption (encrypted/decrypted)
     null      : 0                0               
     des       : 0                0               
     3des      : 0                0               
     aes-cbc   : 833309           0               
     aes-gcm   : 0                0               
     aria      : 0                0               
     seed      : 0                0               
     chacha20poly1305: 0                0               
     Integrity (generated/validated)
     null      : 0                0               
     md5       : 0                0               
     sha1      : 803671           0               
     sha256    : 29540            0               
     sha384    : 48               0               
     sha512    : 50               0 

Since the hardware offload isn’t occurring, the main CPU is moderately taxed when doing transfers via AES-GCM. Also, the throughput is only ~ 100 Mbps:

Reconfiguring the VPNs to AES-CBC and redoing the transfers, we get lower CPU usage and significantly higher throughput:

CheckPoint SmartView Monitor shows Permanent Tunnels Down, even though they’re up

Being fairly new to CheckPoint, I hadn’t yet used SmartView monitor, which is the windows desktop monitoring application. At first glance it wasn’t very useful. I had terminated several test tunnels to various Cisco, FortiGate, and Palo Alto firewalls, all of which were working fine. But they all showed down in SmartView. What the heck?

Reason: When it comes to monitoring tunnels, CheckPoint by default uses a proprietary protocol they call “tunnel_test” (udp/18234). In order to properly monitor VPN tunnels to Non-CheckPoint Devices, DPD (dead peer detection) must be used.

Here’s how to enable DPD on an interoperable device:

  1. In the CheckPoint SmartConsole folder (usually C:\Program Files (x86)\CheckPoint\SmartConsole), run GuiDBedit.exe
  2. Under Network Objects folder -> network_objects, look for the interoperable device Object. The class name will be “gateway_plain”
  3. Search for Field name tunnel_keepalive_method and change it to dpd
  4. File -> Save All, exit.
  5. Restart SmartConsole and install policy to the applicable Checkpoint gateways / clusters

After making that change, pushing policy, and restarting SmartView Monitor, the tunnels now show green:

Cisco ISR G2 to CheckPoint R80.30 IKEv1 VPN woes

I had previously done Cisco router to CheckPoint R80.30 gateway VPNs before without issue, but for whatever reason could not even establish phase 1 for this one. CheckPoint R80 VPN communities default to AES-256, SHA-1, Group 2, and 1-day timetime which is easy to match on the Cisco with this config:

crypto keyring mycheckpoint
 local-address GigabitEthernet0/0
 pre-shared-key address 192.0.2.190 key abcdefghij1234567890
!
crypto isakmp policy 100
 encr aes 256
 authentication pre-share
 group 2
 hash sha          ! <--- default value
 lifetime 864000   ! <--- default value
!

After verifying connectivity, doing packet captures, and multiple reboots on on both ends, IKE simply would not come up. On the Cisco ISR, debug crypto isakmp wasn’t especially helpful:

Jun 18 11:06:17.085: ISAKMP: (0):purging SA., sa=3246F97C, delme=3246F97C
Jun 18 11:06:17.285: ISAKMP: (0):SA request profile is (NULL)
Jun 18 11:06:17.285: ISAKMP: (0):Created a peer struct for 35.245.62.190, peer port 500
Jun 18 11:06:17.285: ISAKMP: (0):New peer created peer = 0x2CE62C3C peer_handle = 0x80000005
Jun 18 11:06:17.285: ISAKMP: (0):Locking peer struct 0x2CE62C3C, refcount 1 for isakmp_initiator
Jun 18 11:06:17.285: ISAKMP: (0):local port 500, remote port 500
Jun 18 11:06:17.285: ISAKMP: (0):set new node 0 to QM_IDLE
Jun 18 11:06:17.285: ISAKMP: (0):insert sa successfully sa = 2CE620E8
Jun 18 11:06:17.285: ISAKMP: (0):Can not start Aggressive mode, trying Main mode.
Jun 18 11:06:17.285: ISAKMP: (0):found peer pre-shared key matching 192.0.2.190
Jun 18 11:06:17.285: ISAKMP: (0):constructed NAT-T vendor-rfc3947 ID
Jun 18 11:06:17.285: ISAKMP: (0):constructed NAT-T vendor-07 ID
Jun 18 11:06:17.285: ISAKMP: (0):constructed NAT-T vendor-03 ID
Jun 18 11:06:17.285: ISAKMP: (0):constructed NAT-T vendor-02 ID
Jun 18 11:06:17.285: ISAKMP: (0):Input = IKE_MESG_FROM_IPSEC, IKE_SA_REQ_MM
Jun 18 11:06:17.285: ISAKMP: (0):Old State = IKE_READY New State = IKE_I_MM1
Jun 18 11:06:17.285: ISAKMP: (0):beginning Main Mode exchange
Jun 18 11:06:17.285: ISAKMP-PAK: (0):sending packet to 192.0.2.190 my_port 500 peer_port 500 (I) MM_NO_STATE
Jun 18 11:06:17.285: ISAKMP: (0):Sending an IKE IPv4 Packet.
Jun 18 11:06:17.369: ISAKMP-PAK: (0):received packet from 192.0.2.190 dport 500 sport 500 Global (I) MM_NO_STATE
Jun 18 11:06:17.369: ISAKMP-ERROR: (0):Couldn't find node: message_id 2303169274
Jun 18 11:06:17.369: ISAKMP-ERROR: (0):(0): Unknown Input IKE_MESG_FROM_PEER, IKE_INFO_NOTIFY: state = IKE_I_MM1
Jun 18 11:06:17.369: ISAKMP: (0):Input = IKE_MESG_FROM_PEER, IKE_INFO_NOTIFY
Jun 18 11:06:17.369: ISAKMP: (0):Old State = IKE_I_MM1 New State = IKE_I_MM1

The CheckPoint gave a more “useful” error:

Main Mode Failed to match proposal: Transform: AES-256, SHA1, Group 2 (1024 bit); Reason: Wrong value for: Authentication Method

This seemed to imply the CheckPoint was expecting certificate-based authentication rather than PSK. In traditional mode, the gateway is set by default for certificate only. But it’s not clear how this is configured in newer versions.

After poking around settings for quite a while, I simply deleted the VPN community in CheckPoint SmartConsole and re-created it. The connection then popped up immediately.

¯\_(ツ)_/¯

VPN throughput Tests – Palo Alto VM-300 to GCP

I was doing a deep dive read of supported IKEv2 ciphers on GCP native VPNs today and thought I’d setup a quick lab to see which settings would provide best throughput. Lab setup was as follows:

  • Palo Alto VM-300 on m4.xlarge in us-east-2 (Ohio)
  • IKEv2 VPN to GCP us-east4 (N. Virginia)
  • Latency is a steady 13ms round trip time
  • AWS side test instance is t3.xlarge (4 vCPU / 16 GB RAM)
  • GCP side test instance is e2-standard-4 (4 vCPU / 16 GB RAM)
  • Both VMs running Ubuntu Linux 18.04.4
  • File is 500 MB binary file transfer via SCP

Throughput speeds (in Mbps) using DH Group 14 (2048-bit) PFS:

Encryption / HashSHA-512SHA-256SHA-1
AES-GCM 256-bit664668672
AES-GCM 128-bit648680704
AES-CBC 256-bit510516616
AES-CBC 192-bit492523624
AES-CBC 128-bit494573658
Average: 604 Mbps

Throughput speeds (in Mbps) using DH Group 5 (1536-bit) PFS:

Encryption / HashSHA-512SHA-256SHA-1
AES-GCM 256-bit700557571
AES-GCM 128-bit660676616
AES-CBC 256-bit464448656
AES-CBC 192-bit595528464
AES-CBC 128-bit605484587
Average: 574 Mbps

Throughput speeds (in Mbps) using DH Group 2 (1024-bit) PFS:

Encryption / HashSHA-512SHA-256SHA-1
AES-GCM 256-bit680626635
AES-GCM 128-bit672664680
AES-CBC 256-bit584452664
AES-CBC 192-bit536520664
AES-CBC 128-bit528502656
Average: 608 Mbps

Key Takeaways

GCP will prefer AES-CBC in their negotiations, but AES-GCM provides roughly 25% better throughput. So if throughput is paramount, be sure to have only AES-GCM in the IPSec profile.

If using AES-CBC, SHA-1, while deprecated, is 13% faster than SHA-256 and 25% faster than SHA-512. Since SAs are rebuilt every 3 hours, cracking isn’t as large a concern as in typical SHA-1 use cases.

DH Group does not affect speeds. May as well use the strongest mutually supported value, which is Group 14 (2048-bit). GCP does not support Elliptic Curve (Groups 19-21) so these couldn’t be tested. I would expect faster SA build times, but no change in transfer speeds.

Assuming SHA-256 and Group 14 PFS, this graph summarizes the results:

VPN from Cisco ISR with frontdoor and interior VRFs + HSRP to a Cisco ASA

So this week I was tasked with bringing up a site-to-site VPN between a Cisco ISR and Cisco ASA.   Every site-to-site VPN I’ve done over the last 10 years or so has been route-based.  But the older Cisco ASA code won’t support those, so it was back to isakmp profiles and crypto-maps.  The real trick was the ISR was using both frontdoor and interior VRFs, and HSRP for failover for added complexity.

Here’s was the information:

  • Site A (Cisco ISR 4431, IOS-XE version 16.6.8):
  •   public IP: 198.51.100.52/29, HSRP IP: 198.51.100.54, VRF: EXTERNAL
  •   private IP IP: 10.111.111.1/24, VRF: INTERNAL
  • Site B (Cisco ASA, software version 9.4):
  •   public IP: 203.0.113.105
  •   private network: 10.222.222.0/24

The configuration for the ISR starts with the ISAKMP policy, which basically sets encryption parameters.  This is global, and not VRF-aware:

crypto isakmp invalid-spi-recovery
crypto isakmp keepalive 10
!
crypto isakmp policy 1
 encr aes 256              ! 256-bit AES encrytpion
 authentication pre-share
 group 2                   ! 1024-bit key
 lifetime 86400            ! default setting
 hash sha                  ! default setting
!

The pre-shared key is set in the crypto keyring, with needs to be mapped to the frontdoor VRF (the VRF set on the public interface)

crypto keyring MY_KEYRING vrf EXTERNAL
 local-address 198.51.100.54 EXTERNAL
 pre-shared-key address 203.0.113.105 key xxxxxxxxxxxxxxx

Unlike route-based VPNs, an ISAKMP profile is required, which is VRF-aware.  Note the presence of the iVRF (internal one) on the “vrf” line:

crypto isakmp profile MY_ISAKMP_PROFILE
 vrf INTERNAL
 keyring MY_KEYRING 
 match identity address 203.0.113.105 255.255.255.255 EXTERNAL
 local-address 198.51.100.54 EXTERNAL
!

For IPSec / Phase 2, a transform set of course should be defined.   Here I’m using Encapsulation Security Payload, AES 128-bit encryption with SHA-1 hashing, operating in IPSec tunnel mode:

crypto ipsec transform-set ESP_AES-128_SHA_TUNNEL esp-aes esp-sha-hmac 
 mode tunnel
!
crypto ipsec df-bit clear

Since this is not route-based, an ACL defines the “interesting” traffic to send via the tunnel:

ip access-list extended 101
 permit ip 10.111.111.0 0.0.0.255 10.222.222.0 0.0.0.255
!

Then a crypto map links this ACL with the ISAKMP profile and IPSec settings:

crypto map MY_CMAP 1 ipsec-isakmp 
 set peer 203.0.113.105
 set transform-set ESP_AES-128_SHA_TUNNEL 
 set pfs group5
 set isakmp-profile MY_ISAKMP_PROFILE
 match address 101
 reverse-route
 lifetime 3600                ! default setting
!

Finally, the crypto map is applied to the public interface.  If HSRP is being used between a pair of routers, a name for the HSRP group must be set, then added to the crypto map statement:

interface Port-channel1
 description Public Interface
 vrf forwarding EXTERNAL
 ip address 198.51.100.52 255.255.255.248
 ip nat outside
 standby delay minimum 30
 standby 1 ip 198.51.100.54
 standby 1 priority 254
 standby 1 preempt
 standby 1 name VPNHA
 load-interval 30
 no negotiation auto
 crypto map MY_CMAP redundancy VPNHA
!
ip route vrf EXTERNAL 0.0.0.0 0.0.0.0 198.51.100.49

I had missed the “redundancy” option on the crypto map in my initial config, which probably cause the traffic to source from the primary IP address rather than the HSRP one.  Running debug crypto isakmp, I would see this:

May 15 17:15:35.892: ISAKMP: (0):SA request profile is MY_ISAKMP_PROFILE
May 15 17:15:35.892: ISAKMP: (0):Created a peer struct for 203.0.113.105, peer port 500
May 15 17:15:35.892: ISAKMP: (0):New peer created peer = 0x80007FAD0B334DB8 peer_handle = 0x8000000080000012
May 15 17:15:35.892: ISAKMP: (0):Locking peer struct 0x80007FAD0B334DB8, refcount 1 for isakmp_initiator
May 15 17:15:35.892: ISAKMP: (0):local port 500, remote port 500
May 15 17:15:35.892: ISAKMP: (0):set new node 0 to QM_IDLE      
May 15 17:15:35.893: ISAKMP: (0):insert sa successfully sa = 80007FAD0B75C470
May 15 17:15:35.893: ISAKMP: (0):Can not start Aggressive mode, trying Main mode.
May 15 17:15:35.893: ISAKMP-ERROR: (0):No Cert or pre-shared address key. 
May 15 17:15:35.894: ISAKMP-ERROR: (0):construct_initial_message: Can not start Main mode

Since the debug wasn’t showing the source IP for this traffic, I spent several hours troubleshooting the ISAKMP profile and VRF statements, only to conclude they were in fact correct.

 

VPNs to GCP using IKEv2 when your Cisco router is behind NAT

I was able to follow this tutorial but had to make a few adjustments.  The main one is to configure the public IP address in the IKEv2 profile (see step 3 below). 

Remember of course that the router will need UDP ports 500 & 4500 forwarded by the firewall, which also must support ESP passthrough.

1) Configure a global IKEv2 proposal and policy. 

crypto ikev2 proposal MY_IKEV2_PROPOSAL 
 encryption aes-cbc-256 aes-cbc-192 aes-cbc-128
 integrity sha512 sha384 sha256
 group 24 16 14
!
crypto ikev2 policy MY_IKEV2_POLICY 
 proposal MY_IKEV2_PROPOSAL

2) And add the peer to the keyring:

crypto ikev2 keyring MY_KEYRING
 peer gcp1
  address 35.212.226.126
  pre-shared-key abcdef1234567890

3) Create a custom IKEv2 profile.  Note the highlighted public IP address and also the lifetime and DPD interval settings.

crypto ikev2 profile GCP_IKEV2_PROFILE
 match address local interface GigabitEthernet0
 match identity remote address 0.0.0.0
 ! If router is behind NAT, set this to the public IP
 identity local address 203.0.113.222
 authentication remote pre-share
 authentication local pre-share
 keyring local MY_KEYRING
 lifetime 36000                       ! 10 hour SA lifetime
 dpd 60 5 periodic                    ! 1 minute keepalives
!

4) Configure a custom IPSec transform set and profile.  This is 128-bit AES encryption with SHA-256 integrity:

! IPsec Settings
crypto ipsec transform-set ESP_AES128_SHA256 esp-aes esp-sha256-hmac
!
crypto ipsec profile GCP_IPSEC_PROFILE
 set security-association lifetime kilobytes disable
 set security-association lifetime seconds 10800
 set transform-set ESP_AES128_SHA256
 set pfs group14                          ! 2048-bit
 set ikev2-profile GCP_IKEV2_PROFILE
!

5) Finally, create the tunnel interface.  Unlike the IKEv2 profile, this simply references the External interface, not the public IP:

interface Tunnel1
 ip address 169.254.0.2 255.255.255.252
 ip mtu 1460
 ip virtual-reassembly in 
 ip tcp adjust-mss 1420
 tunnel source GigabitEthernet0
 tunnel mode ipsec ipv4
 tunnel destination 35.212.226.126
 tunnel protection ipsec profile GCP_IPSEC_PROFILE
!

Troubleshooting

The SAs should look like this:

Router#show crypto ikev2 sa
IPv4 Crypto IKEv2 SA

Tunnel-id Local Remote fvrf/ivrf Status 
2 192.168.1.123/4500 35.212.226.126/4500 none/none READY 
Encr: AES-CBC, keysize: 128, Hash: SHA256, DH Grp:14, Auth sign: PSK, Auth verify: PSK
Life/Active Time: 36000/1226 sec

Router#show crypto ipsec sa peer 35.212.226.126

interface: Tunnel1
    Crypto map tag: Tunnel1-head-0, local addr 192.168.1.123

   protected vrf: (none)
   local  ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   remote ident (addr/mask/prot/port): (0.0.0.0/0.0.0.0/0/0)
   current_peer 35.212.226.126 port 4500
     PERMIT, flags={origin_is_acl,}
    #pkts encaps: 45, #pkts encrypt: 45, #pkts digest: 45
    #pkts decaps: 58, #pkts decrypt: 58, #pkts verify: 58
    #pkts compressed: 0, #pkts decompressed: 0
    #pkts not compressed: 0, #pkts compr. failed: 0
    #pkts not decompressed: 0, #pkts decompress failed: 0
    #send errors 0, #recv errors 0

     local crypto endpt.: 192.168.1.123, remote crypto endpt.: 35.212.226.126
     path mtu 1500, ip mtu 1500, ip mtu idb GigabitEthernet0
     current outbound spi: 0x962EDB69(2519653225)
     PFS (Y/N): N, DH group: none

     inbound esp sas:
      spi: 0x10B829B(17531547)
        transform: esp-aes esp-sha-hmac ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 5, flow_id: Onboard VPN:5, sibling_flags 80000040, crypto map: Tunnel1-head-0
        sa timing: remaining key lifetime (sec): (14259)
        Kilobyte Volume Rekey has been disabled
        IV size: 16 bytes
        replay detection support: Y  replay window size: 1024
        Status: ACTIVE(ACTIVE)

     inbound ah sas:

     inbound pcp sas:

     outbound esp sas:
      spi: 0x962EDB69(2519653225)
        transform: esp-aes esp-sha-hmac ,
        in use settings ={Tunnel UDP-Encaps, }
        conn id: 6, flow_id: Onboard VPN:6, sibling_flags 80000040, crypto map: Tunnel1-head-0
        sa timing: remaining key lifetime (sec): (14259)
        Kilobyte Volume Rekey has been disabled
        IV size: 16 bytes
        replay detection support: Y  replay window size: 1024
        Status: ACTIVE(ACTIVE)

     outbound ah sas:

     outbound pcp sas:

VPNs to GCP using IKEv1 when your Cisco router is behind NAT

Tried my first VPN to GCP and didn’t have much luck with IKEv1.  While it did detect the remote router being behind NAT, Phase1 wouldn’t come up due to an ID mismatch:

received NAT-T (RFC 3947) vendor ID
remote host is behind NAT
IDir '192.168.1.123' does not match to '203.0.113.222'

Where 192.168.1.123 is the Real private IP of the router and 203.0.113.222 is the public NAT IP.

This is consistent with the GCP documentation on this topic, which states the following:

When using one-to-one NAT, your on-premises VPN gateway must identify itself using the same external IP address of the NAT device

See also the same configuration with IKEv2.

IPSec VPN Spoke Router using FQDN authentication

In a previous post I’d covered doing site-to-site IPSec tunnels on Cisco routers when one or both devices are behind NAT.  But what if multiple spoke routers have dynamic IP addresses? Or how about many behind the same NAT address? 

The solution is to have the spoke routers authenticate using FQDN hostname rather than IP address.  I’ve seen lots of examples which overly complicate how to do this.  It’s actually pretty simple and only requires minor changes.  Let’s assume the spoke routers have dynamic IPs and the hub has a static IP of 203.0.113.222…

IKEv1

Spoke Router

On spoke routers with IKEv1, simply replace  the “crypto keyring” statement with “crypto isakmp peer” to use FQDN authentication and IKE aggressive mode, like this:

hostname spoke1
! 
no crypto keyring MyHub
crypto isakmp peer address 203.0.113.222 [vrf InternetVRFName]
 set aggressive-mode password XXXXXXXX
 set aggressive-mode client-endpoint fqdn spoke1.mydomain.com 
!

Note the fqdn hostname doesn’t necessarily need to match the router’s hostname

IKEv2

Spoke Router

Set the Hub’s IP address and pre-shared key in an IKEv2 keyring:

crypto ikev2 keyring MY_IKEV2_KEYRING
 peer MyHub
  address 203.0.113.222
  pre-shared-key MySecretKey1234    ! Must be 16 chars or longer

The identity (hostname) in the IKEv2 profile via the identity local line:

hostname spoke1
!
crypto ikev2 profile SPOKE_IKEV2_PROFILE
 match address local interface GigabitEthernet0/0
 match identity remote address 203.0.113.222 255.255.255.255
 identity local fqdn spoke1.spokedomain.com
 authentication remote pre-share
 authentication local pre-share
 keyring local MY_IKEV2_KEYRING
 dpd 20 2 periodic 
!

IPSec profile:

crypto ipsec profile SPOKE_IPSEC_PROFILE
 set security-association lifetime kilobytes disable
 set pfs group14
 set ikev2-profile SPOKE_IKEV2_PROFILE
!

Tunnel Interface and static route to 10.0.0.0/8:

interface Tunnel1
 ip address 169.254.1.100 255.255.255.0
 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 SPOKE_IPSEC_PROFILE
!
ip route 10.0.0.0 255.0.0.0 Tunnel1

Hub Router

Each Spoke will need an entry. Use identity in the entry, not hostname

crypto ikev2 keyring SPOKES_IKEV2_KEYRING
 peer spoke1
  identity fqdn spoke1.spokedomain.com
  pre-shared-key MySecretKey1234
 !

The IKEv2 profile will be a bit different. The domain is used to match multiple spokes:

crypto ikev2 profile HUB_IKEV2_PROFILE
 match address local interface GigabitEthernet0/0
 match identity remote fqdn domain spokedomain.com
 identity local fqdn myhub.hubdomain.com
 authentication remote pre-share
 authentication local pre-share
 keyring local SPOKES_IKEV2_KEYRING
 dpd 10 2 on-demand
 virtual-template 1

The IPSec profile is almost the same but is responder-only (passive):

crypto ipsec profile HUB_IPSEC_PROFILE
 set security-association lifetime kilobytes disable
 set pfs group14
 set ikev2-profile HUB_IKEV2_PROFILE
 responder-only

Rather than a regular tunnel interface, a virtual template one is used:

interface Virtual-Template1 type tunnel
 ip unnumbered Loopback0
 tunnel source GigabitEthernet0/0
 tunnel mode ipsec ipv4
 tunnel destination dynamic
 tunnel protection ipsec profile HUB_IPSEC_PROFILE

IPSec VPNs on Cisco routers when both are behind NAT

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:

crypto isakmp invalid-spi-recovery
crypto isakmp disconnect-revoked-peers
crypto isakmp keepalive 10 crypto isakmp nat keepalive 900 ! 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 esp-aes esp-sha256-hmac 
 mode tunnel
crypto ipsec transform-set ESP_AES128_SHA esp-aes esp-sha-hmac 
 mode tunnel

! Create IPSec profile
crypto ipsec profile MY_IPSEC_PROFILE
 set transform-set ESP_AES128_SHA256 ESP_AES128_SHA 
 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 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 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 900
crypto ikev2 dpd 10 2 periodic

2) Create an IKEv2 Proposal and Policy

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