NordVPN IKEv2/IPsec with Cisco IOS

NordVPN is one of the more popular VPN providers. However, I couldn’t find any guides online for using their IKEv2/IPsec with Cisco IOS.

This guide shows how to use EAP MSCHAP and certificate based authentication with NordVPN and IOS. I hope this helps others get their VPN running more quickly than I did.

I had to upgrade the code on my router for this to work. I have this working on a Cisco 1941 running c1900-universalk9-mz.SPA.155-3.M5.bin. On older versions (early version 15 releases) local eap authentication for IKEv2 isn’t supported.

I’d also recommend using some sort of firewall config with this too, this isn’t included in any of the configuration below. Although all traffic will be PATed to your VPN IP, obscurity isn’t security blah blah blah.


The VPN Bit

First, import the NordVPN public key into your configuration. The certificate configuration below is taken from the public root.der cert that can be downloaded from the NordVPN website.

crypto pki trustpoint NORDVPN
 enrollment terminal pem
 revocation-check none
crypto pki certificate chain NORDVPN
 certificate ca 01
  3082050A 308202F2 A0030201 02020101 300D0609 2A864886 F70D0101 0D050030 
  39310B30 09060355 04061302 50413110 300E0603 55040A13 074E6F72 6456504E 
  31183016 06035504 03130F4E 6F726456 504E2052 6F6F7420 4341301E 170D3136 
  30313031 30303030 30305A17 0D333531 32333132 33353935 395A3039 310B3009 
  06035504 06130250 41311030 0E060355 040A1307 4E6F7264 56504E31 18301606 
  03550403 130F4E6F 72645650 4E20526F 6F742043 41308202 22300D06 092A8648 
  86F70D01 01010500 0382020F 00308202 0A028202 0100C92B FC1621CA 8D05DAEA 
  6C20C5F0 0BA42F91 9A6CDCD3 76FDE405 91F4084B 582A9746 9E8EC2AC 127998D0 
  A6A89FCB 990935CF B111F581 03608390 F6822C5D 77598952 F577744D F2F4526B 
  5CCA0391 7742181A 1DBCA272 53A95C7C 4545EBF5 311DC6C1 82E64AF5 4B511D2F 
  5E2589B7 AE92FFE6 1B90302A 695FB914 790F1DA4 2C1DDE22 884EAC1D D59B9D0E 
  AB16694D 2FAB30B6 1F9E48C9 A67FE7F4 E70A4DF5 43550FE8 192C6DBB 91730395 
  B24103B2 6E98A160 E79FF208 CC63989C 5251CD01 F98D3CF7 8F5401BD 122E42E0 
  6EBD491F 871D4513 08706628 2B7315EE 30FF9080 CE7891EC E0CE2254 69970E33 
  6CC5DE5B EBC0CBD7 0CC7CD78 8A09001B FD963C3D EBDC50F1 CCD0094E 65315980 
  DFB96DBF 911CF54E 6166EC24 FFD40ED5 9F9DFEBE 89C749A5 BAB4BC82 70802898 
  306B7932 670E9EE0 567C9982 F8BE9451 84F76F45 35823099 1E078C81 1F287152 
  64D18091 E6E98477 0FA85C14 073D7107 13125FC8 EB4B4C77 3DF71BA9 B43B8DAC 
  42DFFE01 1DD8098F D1BAC595 04907FA8 D4BDE04B 4DB63F22 69E6C241 6D631C08 
  6F1A6148 2D547D97 30F41335 8A1E4BF2 5848E651 54600837 7A35EDDE 151352EF 
  781DBFF0 B79796E8 63249EBB 87B19046 15C55467 F03842C6 CD0C9E43 075852BA 
  332CD708 29FE2675 850D83DF 0CA1EFA5 F7FF90B0 E86ED3C1 7FE2DB72 1E70432F 
  6AB98DBB C5A8F45F 02F28CE9 6DA62493 2D669EFD 0E2F0203 010001A3 1D301B30 
  0C060355 1D130405 30030101 FF300B06 03551D0F 04040302 0106300D 06092A86 
  4886F70D 01010D05 00038202 0100BD7D 42F6B193 F120DDA6 0F7D9578 DC924E06 
  65084755 9A5AB8EF 5A3F6C33 0FE01F20 9D07AC15 1B576366 428ECE74 266EF707 
  62D588BF 6A951126 23ABC4E4 80BC22C4 41252578 71ED5663 1C97AE8E 6B99583F 
  93A6B5D2 B96C6CAF DE83FFC6 1E82710D D5C33A89 0B5129F1 B7B824DD 02A95FA7 
  82761EBB A743EE5A 6FFB5942 50C47D92 0F1B13F6 F07F899A E24C811E FC82E839 
  017402AA 7B020342 70B70B02 66F15D09 17602092 077E55A7 4EAEF9E4 D68C6D3F 
  A724B957 5E2CB46B 70F9F034 0C9A7964 95787AA2 792EAC4C 958BC467 FA8A4C47 
  6809E697 BF640498 DE9D56A8 C3A13028 934B79BB 86115F31 1509F5C0 0B7A1CA6 
  535DB420 3BDB08C5 25C49B7E 27F80520 BC6C3002 4D7B673C 2EE70F45 677592E9 
  F9188D2D E8843619 34A130BE 51575273 E9F69C93 B39022B4 BD8BB401 DB382462 
  01EE0F08 077CF6B7 D2029AC5 AB82785D 35D70E7B 5E418A77 2B180F1A BD0D5C59 
  7B1F20A1 236EB9C4 B8493D6F 98DE97A3 5F1ED3CA A0773D98 3A5174D3 C849E55A 
  C0304CD6 62428677 87B79F4D 87C19A87 BE3E4CCD 6306CC38 7E124FBE 873B02D7 
  20EF8D09 12B6FDD3 89997E42 049A88C2 54F8411D 543D2C70 4074CF2A 148DA444 
  AD08CA73 A601985E C653FF69 3FE4A44B 043F2699 4259C19F 7027D424 73F21D12 
  3C0A4BF0 FCAD8206 0A790991 865E3DF7 EEA32F17 19D887A0 2DFAAAE3 5773223C 
  07C13329 960FB5A4 A20E5688 E958

Now the crypto config. For match identity remote any you could also match on the FQDN of the specific NordVPN server. The benefit of the any keyword is that the only configuration that needs to be amended to move to a different server is the destination under the tunnel interface configuration.

crypto ikev2 profile NORD-USA
 match identity remote any
 authentication local eap mschapv2 username <nordvpn email address> password <nordvpn password>
 authentication remote rsa-sig
 pki trustpoint NORDVPN verify

crypto ipsec transform-set NORDVPN esp-aes 256 esp-sha-hmac 
 mode tunnel

crypto ipsec profile NORDVPN
 set transform-set NORDVPN 
 set ikev2-profile NORD-USA

Configure a tunnel interface and reference the IPsec profile. Your MTU and TCP MSS may change depending on the MTU of the Internet link. The below currently works for a 1500 byte WAN MTU.

interface Tunnel1
 ip address negotiated
 ip mtu 1438
 ip nat outside
 ip virtual-reassembly in
 ip tcp adjust-mss 1398
 tunnel source <wan interface>
 tunnel mode ipsec ipv4
 tunnel destination <nordvpn server ip>
 tunnel protection ipsec profile NORDVPN


How I’m Using it with NAT and PBR

I may look to revise this to use VRF Lite, but at the moment policy based routing is being used.

I have a “VPN” SSID on my AP, which drops into VLAN 30 on my LAN and is picked up on my router. PBR is used to push traffic over the VPN. The interface is marked as a nat inside interface.

interface GigabitEthernet0/1.30
 encapsulation dot1Q 30
 ip address
 ip nat inside
 ip virtual-reassembly in
 ip policy route-map NORDVPN-TRAFFIC

PBR is configured as follows. The ACL is present so that the same route map can be used on other interfaces and specific IPs can be pushed over the VPN.

ip access-list extended NORDVPN-TRAFFIC
 permit ip any

route-map NORDVPN-TRAFFIC permit 10
 match ip address NORDVPN-TRAFFIC
 set interface Tunnel1

NAT also uses route maps so that the PAT address used is based on the egress interface. In the Tunnel1 interface configuration in the VPN section, you can see Tunnel 1 is an outside interface.

ip access-list standard NAT
 permit <inside and inside VPN LAN IPs> <wildcard mask>

route-map NORD-NAT permit 10
 match ip address NAT
 match interface Tunnel1

route-map INTERNET-NAT permit 10
 match ip address NAT
 match interface <wan interface>

ip nat inside source route-map NORD-NAT interface Tunnel1 overload
ip nat inside source route-map INTERNET-NAT interface <wan interface> overload

18 thoughts on “NordVPN IKEv2/IPsec with Cisco IOS

  1. Interesting article. I am looking for a VPN that I can use with my Cisco router and this may be the solution.

    PS Why capitals only allowed?

    1. I’m glad this helped. I’m a better network engineer than a website maintainer. I think it’s because I have this in my CSS… “text-transform: uppercase”. I’ll take a look.

  2. Hey,
    Great Howto!
    But i fail already on the first step. Could you please describe howto import the root.der?
    Thank you!

    1. The mass of HEX below “crypto pki certificate chain NORDVPN” is the root.der. It’s already part of this config, so no need to import the file.

  3. Hey Matt,

    Just tried to get it to work with iOS 15.8 and can’t seem to get it to work;

    I get renegotiations every 60 seconds on IPSEC phase, although the IKEv2 exchange successfully completes and the tunnel comes up.

    Ping seems to work, even with large packets of 1400 bytes.

    Any ideas/suggestions? eventually the IPSEC SA renegotiations exhaust router memory space causing errors.

    1. Perhaps debugs could help you pinpoint the cause of the renegotiating. I’ve only tried this on my IOS 15.5 1941, maybe this is a bug introduced in 15.8?

      1. Hey Matt,

        Was out of town for a bit but the next step is to downgrade and see what that does. I’ll try 15.7 and 15.5 to see if I can pinpoint it. Will get back on this.



      2. Hey Matt,

        Tried in the same config with 15.5(3)M9 as well as 15.7(3)M4a with the same result. It does not work, multiple SA’s get inserted at the rate of about 1 / minute. I’m wondering if my IPSEC settings are wrong somehow, which would cause the router to renegotiate the IPSEC SA every minute.

        Are there any global settings done to disable multiSA support, or are there any other specific settings i may have missed? (IPSEC or IKEwise)?

        What i see that may be related, is that around every minute I get
        (debug crypto ipsec, then all possible options enabled)
        [] -> [ACL automatic]: message ACL for always up maps
        [ACL automatic]: message = ACL for always up maps
        [ACL automatic] -> [ACL automatic]: delayed (60000 msec) message ACL for always up maps

        shortly followed by another SA being inserted.

        I am using vrf, although the tunnel interface can be in the global routing table or the VRF i assign it to with the same result. I tried the PBR approach you use with the same result.

        I do have the following IKE proposal, but as IKE completes I don’t think this is the problem.
        crypto ikev2 proposal NordVPN
        encryption aes-cbc-256
        integrity sha256
        group 14

        I have the MTU on the tunnel interface set to 1380, and the MSS to 1330 because of the PPPoEoVLAN implementation my ISP uses.

  4. Slight update;
    I do have traffic working now, even with VRF and NAT.
    It seemed that an erroneous NAT configuration triggered ping working but other traffic not

    However, still getting the number of IPSEC SA’s increase by 2 every minute.

    As a suggestion, an outbound acccesslist restricting outgoing traffic to > any and dropping all others will prevent the number of IPSEC SA’s increasing drastically; this happens if the IPSEC traffic selector does not match. It doesn’t solve the issue I’m seeing yet, but to be continued.


    1. Hi Michael,
      I have had similar problems with far too many IPSEC SA’s being created. I am finally down to one inbound and one outbound SA. I can’t pinpoint the exact fix but here are a few thing I recently added to my config.

      1. The access list you recommended on Tunnel1. Even after configuring route-maps and ZPFW I had a lot of traffic headed towards the tunnel that was not from my NATed address.
      ip access-list extended ACL_VPN_NORD_INT
      10 permit ip any (200792 matches)
      20 permit icmp any
      999 deny ip any any (740 matches)
      interface Tunnel1
      ip access-group ACL_VPN_NORD_INT out

      2. I enabled pfs. I though it might change the way SA negotiation is initiated. It won’t appear to be working in when you view the security association until SAs have been regenerated according to this post
      crypto ipsec profile NORDVPN
      set pfs group5

      3. I deleted the default ipsec profile to be sure I was always using the NORDVPN profile.
      no crypto ipsec profile default

      4. After the SAs were under control I added a security-association idle-time to clean up in case they got bad again.
      crypto ipsec profile NORDVPN
      set security-association idle-time 120

  5. Hey Adam,

    Thanks for the response!

    “set pfs” in the ipsec profile is what basically caused the issue to be resolved. This would be group1, there’s doubtlessly a better group to use, but at least it works now, thanks!



    1. Hi Michael,
      Can you please post your VRF configuration? I am having difficulty bringing up my tunnel interfaces after applying the VRF configuration. I am aiming to have all VPN encapsulated traffic in a dedicated VRF and the rest of my interfaces remaining in the global VRF providing un-encapsulated WAN access.

      1. Figured it out. I applied the VRF in the below places. Additional VRF config would also be required for any static routes or route-maps pointing towards the tunnel1 interface. The main problem I had was IOS automatically removed the ip address when the new VRF is applied. For Tunnel1 it issues “no ip address” and will need to be changed back to “ip address negotiated” or you will not get an address from NORD.

        ip vrf VRF_VPN
        interface GigabitEthernet0/1.30
        ip vrf forwarding VRF_VPN
        ip address
        interface Tunnel1
        ip vrf forwarding VRF_VPN
        ip address negotiated
        ip nat inside source route-map NORD-NAT interface Tunnel1 VRF_VPN overload

        This VRF will show up as the as the ivrf when you issue “#show crypto ikev2 sa”. The fvrf is the ipsec encapsulated traffic and is none (global vrf) by default. These can also both be set in the ikev2 profile and checked using “#show crypto ikev2 profile”.

  6. Does any else have their tunnel interface go UP and DOWN every hour when the IPSEC lifetime of 3600s expires? I expected to see new security associations be generated before the lifetime expires. This results in a 1min outage every hour. Possibly related is immediately after the tunnel is up, my router tries to negotiate a 2nd session that doesn’t receive an address from NordVPN and never result in any inbound/outbound esp sas.

    R0#debug crypto ikev2 packet
    *TIMESTAMP (just after first set of esp sas): IPSEC:(SESSION ID = 1) (key_engine) request timer fired: count = 1,
    (identity) local= A.A.A.A:0, remote= B.B.B.B:0,

    R0#show crypto ipsec sa
    interface: Tunnel2
    Crypto map tag: Tunnel2-head-0, local addr A.A.A.A

    protected vrf: VPN
    local ident (addr/mask/prot/port): (
    remote ident (addr/mask/prot/port): (
    current_peer B.B.B.B port 500
    PERMIT, flags={}
    #pkts encaps: 166, #pkts encrypt: 166, #pkts digest: 166
    #pkts decaps: 125, #pkts decrypt: 125, #pkts verify: 125
    #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.: A.A.A.A, remote crypto endpt.: B.B.B.B
    plaintext mtu 1422, path mtu 1492, ip mtu 1492, ip mtu idb Dialer1
    current outbound spi: 0xCCDDD042(3437088834)
    PFS (Y/N): N, DH group: none

    inbound esp sas:
    spi: 0x87A38EB4(2275643060)
    transform: esp-256-aes esp-sha-hmac ,
    in use settings ={Tunnel, }
    conn id: 2252, flow_id: Onboard VPN:252, sibling_flags 80000040, crypto map: Tunnel2-head-0
    sa timing: remaining key lifetime (k/sec): (4153267/3527)
    IV size: 16 bytes
    replay detection support: Y
    Status: ACTIVE(ACTIVE)
    inbound ah sas:
    inbound pcp sas:
    outbound esp sas:
    spi: 0xCCDDD042(3437088834)
    transform: esp-256-aes esp-sha-hmac ,
    in use settings ={Tunnel, }
    conn id: 2251, flow_id: Onboard VPN:251, sibling_flags 80000040, crypto map: Tunnel2-head-0
    sa timing: remaining key lifetime (k/sec): (4153266/3527)
    IV size: 16 bytes
    replay detection support: Y
    Status: ACTIVE(ACTIVE)
    outbound ah sas:
    outbound pcp sas:

    protected vrf: VPN
    local ident (addr/mask/prot/port): (
    remote ident (addr/mask/prot/port): (
    current_peer B.B.B.B port 500
    PERMIT, flags={origin_is_acl,}
    #pkts encaps: 0, #pkts encrypt: 0, #pkts digest: 0
    #pkts decaps: 0, #pkts decrypt: 0, #pkts verify: 0
    #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.: A.A.A.A, remote crypto endpt.: B.B.B.B
    plaintext mtu 1492, path mtu 1492, ip mtu 1492, ip mtu idb Dialer1
    current outbound spi: 0x0(0)
    PFS (Y/N): N, DH group: none

    inbound esp sas:
    inbound ah sas:
    inbound pcp sas:
    outbound esp sas:
    outbound ah sas:
    outbound pcp sas:

Leave a Reply to matt Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.