Auto Draft

DMVPN Phase 2 on Cisco IOS-XE: Hub-and-Spoke to Spoke-to-Spoke VPN Configuration

What Is DMVPN and Why Phase 2 Matters

Dynamic Multipoint VPN (DMVPN) is one of those technologies that sounds intimidating at first but is genuinely elegant once it clicks. At its core, DMVPN solves a real enterprise pain point: how do you connect dozens or hundreds of remote sites without managing an explosion of static point-to-point VPN tunnels? Traditional hub-and-spoke VPNs work fine at small scale, but when Site A needs to talk to Site B, that traffic has to hairpin through the hub router — wasting bandwidth and adding latency.

DMVPN fixes this with three key technologies working together:

  • mGRE (Multipoint GRE) — A single tunnel interface on the hub can accept connections from any spoke, without pre-configuring each tunnel individually.
  • NHRP (Next Hop Resolution Protocol) — Spokes register their public IP addresses with the hub, and can query the hub to resolve the real address of other spokes dynamically.
  • IPsec — Encrypts the mGRE tunnels end-to-end, protecting spoke-to-spoke and hub-to-spoke traffic.

DMVPN comes in three phases, and each one changes how spoke-to-spoke traffic flows. Phase 1 forces all traffic through the hub — simple, but inefficient. Phase 2 enables direct spoke-to-spoke tunnels on demand, without pre-configuring anything between spokes. Phase 3 extends this with NHRP shortcuts and allows summarization at the hub. This guide covers Phase 2 in depth, with real IOS-XE CLI examples and the exact gotchas that bite engineers in production.

If you’re unsure which IOS platform you’re running, the DMVPN commands here apply specifically to IOS-XE (17.x). The key CLI differences between platforms are covered separately if needed.


Lab Topology

For this guide, we’re working with a simple but realistic DMVPN topology:

  • HUB1 — Public IP 203.0.113.1, Tunnel IP 10.100.0.1/24
  • SPOKE1 — Public IP 198.51.100.10, Tunnel IP 10.100.0.2/24, LAN 192.168.10.0/24
  • SPOKE2 — Public IP 198.51.100.20, Tunnel IP 10.100.0.3/24, LAN 192.168.20.0/24

All three routers run IOS-XE 17.x. EIGRP 100 handles routing inside the DMVPN cloud. The goal is for SPOKE1 to reach SPOKE2’s LAN directly, without traffic passing through HUB1.


Step 1: IPsec Profile Configuration (Hub and All Spokes)

Before configuring any tunnel interfaces, set up the IKE and IPsec parameters. These are identical on hub and all spokes. On IOS-XE, the recommended approach is IKEv2 with a profile, but IKEv1 (ISAKMP) is still common in legacy environments. Here we’ll use IKEv1 for maximum compatibility across hardware generations.

! --- ISAKMP Policy ---
crypto isakmp policy 10
 encr aes 256
 hash sha256
 authentication pre-share
 group 14
 lifetime 86400

! --- Pre-shared key (wildcard — accepts any peer) ---
crypto isakmp key DMVPN_KEY_2026 address 0.0.0.0 0.0.0.0

! --- IPsec transform set (transport mode for DMVPN) ---
crypto ipsec transform-set DMVPN-TS esp-aes 256 esp-sha256-hmac
 mode transport

! --- IPsec profile referenced by tunnel interface ---
crypto ipsec profile DMVPN-PROFILE
 set transform-set DMVPN-TS
 set pfs group14

Why transport mode? mGRE already adds its own encapsulation header. Transport mode encrypts only the payload (the GRE packet), keeping overhead lower compared to tunnel mode. This is the correct choice for DMVPN and is required for the shared keyword to work on the hub.


Step 2: Hub Tunnel Interface

The hub’s tunnel interface is the heart of the DMVPN cloud. It uses tunnel mode gre multipoint to accept connections from any spoke without static per-spoke configuration.

! --- HUB1 Tunnel Interface ---
interface Tunnel0
 description DMVPN Phase 2 Hub
 ip address 10.100.0.1 255.255.255.0
 no ip redirects
 no ip proxy-arp
 ip nhrp authentication DMVPN_KEY_2026
 ip nhrp map multicast dynamic
 ip nhrp network-id 100
 ip nhrp holdtime 300
 ip nhrp redirect
 ip tcp adjust-mss 1360
 tunnel source GigabitEthernet0/0/0
 tunnel mode gre multipoint
 tunnel key 100
 tunnel protection ipsec profile DMVPN-PROFILE shared

Key parameters to understand:

  • ip nhrp map multicast dynamic — Tells the hub to replicate multicast packets (used by routing protocols like EIGRP and OSPF) to all registered spokes. Essential for routing to converge.
  • ip nhrp redirect — The Phase 2-specific command. When the hub sees traffic between two spokes, it sends an NHRP redirect to the source spoke, saying “go direct — here’s the other spoke’s real IP.”
  • tunnel protection ipsec profile DMVPN-PROFILE shared — The shared keyword is required on the hub when multiple tunnels (from different spokes) terminate on the same interface.
  • ip tcp adjust-mss 1360 — Prevents TCP black-hole issues caused by mGRE overhead reducing the effective MTU.

Step 3: Spoke Tunnel Interfaces

Spoke configuration is nearly identical across all sites. The critical differences from the hub are the static NHRP mapping to the hub and the ip nhrp shortcut command.

! --- SPOKE1 Tunnel Interface ---
interface Tunnel0
 description DMVPN Phase 2 Spoke
 ip address 10.100.0.2 255.255.255.0
 no ip redirects
 no ip proxy-arp
 ip nhrp authentication DMVPN_KEY_2026
 ip nhrp map 10.100.0.1 203.0.113.1
 ip nhrp map multicast 203.0.113.1
 ip nhrp network-id 100
 ip nhrp holdtime 300
 ip nhrp nhs 10.100.0.1
 ip nhrp shortcut
 ip tcp adjust-mss 1360
 tunnel source GigabitEthernet0/0/0
 tunnel mode gre multipoint
 tunnel key 100
 tunnel protection ipsec profile DMVPN-PROFILE
! --- SPOKE2 Tunnel Interface (change IP and source accordingly) ---
interface Tunnel0
 description DMVPN Phase 2 Spoke
 ip address 10.100.0.3 255.255.255.0
 no ip redirects
 no ip proxy-arp
 ip nhrp authentication DMVPN_KEY_2026
 ip nhrp map 10.100.0.1 203.0.113.1
 ip nhrp map multicast 203.0.113.1
 ip nhrp network-id 100
 ip nhrp holdtime 300
 ip nhrp nhs 10.100.0.1
 ip nhrp shortcut
 ip tcp adjust-mss 1360
 tunnel source GigabitEthernet0/0/0
 tunnel mode gre multipoint
 tunnel key 100
 tunnel protection ipsec profile DMVPN-PROFILE

Phase 2 key parameters on spokes:

  • ip nhrp map 10.100.0.1 203.0.113.1 — Static mapping: tells the spoke that the hub’s tunnel IP (10.100.0.1) lives at public IP 203.0.113.1. Spokes don’t know each other’s public IPs — they discover them dynamically via NHRP.
  • ip nhrp nhs 10.100.0.1 — Defines the hub as the Next Hop Server. The spoke registers itself here on boot.
  • ip nhrp shortcut — Enables spoke-to-spoke shortcuts in Phase 2. Without this, the spoke won’t install CEF shortcut entries even after receiving an NHRP redirect from the hub.

Step 4: EIGRP for Phase 2 — The Critical Part

This is where Phase 2 configuration most commonly breaks, and where engineers waste hours debugging. EIGRP must be configured to preserve the original next-hop on the hub. By default, EIGRP sets itself as the next-hop for routes it advertises — which means SPOKE1 learns about SPOKE2’s LAN with HUB1 as the next-hop, and spoke-to-spoke traffic flows through the hub no matter what NHRP does.

Fix this with two commands on the hub’s Tunnel0 interface:

! --- On HUB1 Tunnel0 interface ---
interface Tunnel0
 no ip split-horizon eigrp 100
 no ip next-hop-self eigrp 100

Then configure EIGRP globally on all three routers:

! --- HUB1 ---
router eigrp 100
 network 10.100.0.0 0.0.0.255
 network 10.1.0.0 0.0.0.255
 no auto-summary

! --- SPOKE1 ---
router eigrp 100
 network 10.100.0.0 0.0.0.255
 network 192.168.10.0 0.0.0.255
 no auto-summary

! --- SPOKE2 ---
router eigrp 100
 network 10.100.0.0 0.0.0.255
 network 192.168.20.0 0.0.0.255
 no auto-summary

no ip split-horizon eigrp 100 allows the hub to re-advertise routes learned from SPOKE1 back out the same tunnel interface to SPOKE2. Without this, SPOKE2 never learns SPOKE1’s LAN from EIGRP. no ip next-hop-self eigrp 100 preserves the spoke’s tunnel IP as the next-hop in routing updates, so when SPOKE1 queries NHRP for 10.100.0.3, it knows it needs to resolve spoke-to-spoke — not just forward to the hub.


Step 5: Verify NHRP Registration and Spoke-to-Spoke Tunnels

Once all three routers are configured, verify the DMVPN state starting from the hub.

HUB1# show dmvpn
Legend: Attrb --> S - Static, D - Dynamic, I - Incomplete
        N - NATed, L - Local, X - No Socket
        # Ent --> Number of NHRP entries with same NBMA peer

Interface: Tunnel0, IPv4 NHRP Details
Type:Hub, NHRP Peers:2,

 # Ent  Peer NBMA Addr    Peer Tunnel Add State  UpDn Tm Attrb
 ----- --------------- --------------- ----- -------- -----
     1 198.51.100.10   10.100.0.2      UP    00:42:17 D
     1 198.51.100.20   10.100.0.3      UP    00:38:04 D    

Both spokes are registered as D (Dynamic). State is UP. Now check the NHRP table in detail:

HUB1# show ip nhrp detail
10.100.0.2/32 via 10.100.0.2
   Tunnel0 created 00:42:17, expire 00:04:43
   Type: dynamic, Flags: registered used nhop
   NBMA address: 198.51.100.10
     (Claimed NBMA address: 198.51.100.10)
10.100.0.3/32 via 10.100.0.3
   Tunnel0 created 00:38:04, expire 00:06:56
   Type: dynamic, Flags: registered used nhop
   NBMA address: 198.51.100.20
     (Claimed NBMA address: 198.51.100.20)

Now trigger spoke-to-spoke traffic. From SPOKE1, ping a host on SPOKE2’s LAN:

SPOKE1# ping 192.168.20.1 source 192.168.10.1 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 192.168.20.1, timeout is 2 seconds:
..!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 97 percent (97/100), round-trip min/avg/max = 4/6/12 ms

The first two packets fail — that’s normal. Those packets go through the hub while NHRP resolution happens. Once resolved, subsequent traffic goes spoke-to-spoke. Verify on SPOKE1:

SPOKE1# show dmvpn
Interface: Tunnel0, IPv4 NHRP Details
Type:Spoke, NHRP Peers:2,

 # Ent  Peer NBMA Addr    Peer Tunnel Add State  UpDn Tm Attrb
 ----- --------------- --------------- ----- -------- -----
     1 203.0.113.1     10.100.0.1      UP    00:43:22 S
     1 198.51.100.20   10.100.0.3      UP    00:00:08 D    

SPOKE2 now appears as a D (Dynamic) entry with state UP — a direct spoke-to-spoke tunnel has been established. Verify the NHRP shortcut entry in CEF:

SPOKE1# show ip cef 192.168.20.0 detail
192.168.20.0/24, epoch 3, flags [subtree, check, deagg]
  Oops, recursive via 10.100.0.3
  nexthop 10.100.0.3 Tunnel0 label [dynamic]
  NHRP shortcut, expire 00:01:22

Troubleshooting Phase 2 — Common Failures

Spoke-to-Spoke Traffic Still Going Through Hub

This is the most common issue. Run show ip route 192.168.20.0 on SPOKE1 and check the next-hop. If it shows via 10.100.0.1 (the hub), then no ip next-hop-self eigrp 100 is either missing or not taking effect.

Also confirm NHRP redirect is configured on the hub: show run interface Tunnel0 | include redirect. Without ip nhrp redirect, the hub never tells SPOKE1 to go direct.

NHRP Resolution Fails — Spokes Can’t Register

SPOKE1# debug ip nhrp detail
*Aug 19 14:22:11.445: NHRP: Sending NHRP Registration Request via Tunnel0 to 10.100.0.1
*Aug 19 14:22:13.445: NHRP: No response from NHS 10.100.0.1, retrying
*Aug 19 14:22:15.445: NHRP: No response from NHS 10.100.0.1, retrying

If registration fails like this, verify the ISAKMP session is up first: show crypto isakmp sa. If the IKE session isn’t established, mGRE packets can’t reach the hub. Check NAT — if a spoke sits behind NAT, NHRP registration will include the private IP as the claimed NBMA address, which causes issues. Add ip nhrp registration no-unique on spoke tunnels behind NAT.

IPsec SA Missing or Flapping

SPOKE1# show crypto ipsec sa | include pkts
    #pkts encaps: 1482, #pkts encrypt: 1482, #pkts digest: 1482
    #pkts decaps: 1477, #pkts decrypt: 1477, #pkts verify: 1477
    #pkts compressed: 0, #pkts decompressed: 0
    #pkts not compressed: 0, #pkts compr. failed: 0
    #pkts not decompressed: 0, #pkts decompress failed: 0

Counters incrementing on both encaps and decaps means IPsec is healthy. If you see encaps incrementing but decaps at zero, traffic is one-way — check for asymmetric routing or ACL issues on the hub’s WAN interface. Ensure UDP 500 and 4500 (for NAT-T) are permitted inbound on any firewall between spokes and hub.

MTU and Fragmentation

mGRE adds 24 bytes of header overhead, and IPsec in transport mode adds another 50-60 bytes (depending on cipher). On a 1500-byte Ethernet path, the usable payload drops to around 1400 bytes. If you see large pings failing but small ones passing, MTU is the culprit. The ip tcp adjust-mss 1360 command handles TCP, but ICMP and UDP applications don’t benefit from MSS clamping. Set the tunnel interface MTU explicitly:

interface Tunnel0
 ip mtu 1400
 ip tcp adjust-mss 1360

Integrating OSPF with DMVPN Phase 2

EIGRP is the path of least resistance for Phase 2, but OSPF works with careful configuration. The network type must be point-to-multipoint on the hub (which avoids the need for a DR/BDR election that never completes on mGRE) and point-to-point on spokes.

! --- HUB1 ---
interface Tunnel0
 ip ospf network point-to-multipoint
 ip ospf 1 area 0

router ospf 1
 router-id 10.100.0.1
 passive-interface default
 no passive-interface Tunnel0

! --- SPOKE1 ---
interface Tunnel0
 ip ospf network point-to-multipoint
 ip ospf 1 area 0

router ospf 1
 router-id 10.100.0.2
 passive-interface default
 no passive-interface Tunnel0

Point-to-multipoint preserves the original next-hop in LSAs, similar to EIGRP’s no ip next-hop-self. The trade-off is that OSPF adjacencies form only hub-to-spoke, not spoke-to-spoke — meaning OSPF still routes spoke-to-spoke via the hub, but NHRP will install a CEF shortcut to bypass that forwarding path once traffic flows. It works, but it’s less clean than EIGRP. For more on diagnosing OSPF adjacency issues in general, see our OSPF troubleshooting guide on IOS-XE.


DMVPN with BGP for Multi-Hub Designs

In enterprise deployments with redundant hubs, BGP is often the routing protocol of choice inside the DMVPN cloud. The challenge is the same as with EIGRP: the hub must not advertise spoke routes with itself as the next-hop.

With BGP, use route reflectors at the hubs and configure next-hop unchanged on iBGP peers to preserve original next-hops:

! --- HUB1 acting as BGP Route Reflector ---
router bgp 65000
 bgp router-id 10.100.0.1
 neighbor SPOKES peer-group
 neighbor SPOKES remote-as 65000
 neighbor SPOKES route-reflector-client
 neighbor SPOKES next-hop-self

! To preserve original next-hop for Phase 2:
 neighbor SPOKES route-map NOOP out

route-map NOOP permit 10
 set ip next-hop unchanged

This ensures that when HUB1 reflects SPOKE1’s routes to SPOKE2, the next-hop remains 10.100.0.2 (SPOKE1’s tunnel IP), allowing NHRP to resolve the shortcut correctly. For a deep-dive into BGP design, our BGP protocol guide covers the fundamentals.


Monitoring DMVPN in Production

A few show commands to keep in your muscle memory for ongoing DMVPN health checks:

! Check overall DMVPN state on any router
show dmvpn detail

! Check all NHRP mappings (hub shows all spokes; spoke shows hub + any active spoke shortcuts)
show ip nhrp

! Check IKE sessions (Phase 1)
show crypto isakmp sa

! Check IPsec SAs (Phase 2)
show crypto ipsec sa summary

! Check CEF shortcut entries on spokes (confirms spoke-to-spoke is bypassing hub)
show ip cef detail | include NHRP

! Check EIGRP neighbors on the DMVPN interface
show ip eigrp neighbors Tunnel0

For production monitoring at scale, integrating these commands into a Python-driven polling loop with Netmiko is the right move. Our Python network automation guide covers exactly that setup — pulling show command output from dozens of routers simultaneously and alerting on NHRP registration drops or IPsec flaps.


Summary

DMVPN Phase 2 is production-proven and still widely deployed across enterprise WAN environments. The technology is mature, and IOS-XE’s implementation is solid — but the configuration pitfalls are real. The most critical points to take away:

  • ip nhrp redirect on the hub — Without this, spokes never get told to go direct.
  • ip nhrp shortcut on spokes — Without this, spokes won’t install the CEF shortcut after getting an NHRP redirect.
  • no ip next-hop-self eigrp <AS> on the hub tunnel interface — Without this, EIGRP routes point to the hub as next-hop and traffic never goes spoke-to-spoke at the routing level.
  • MTU planning matters — Set ip mtu 1400 and tcp adjust-mss 1360 on all tunnel interfaces from day one.

When you get Phase 2 right, the result is a scalable, encrypted WAN fabric that intelligently routes spoke-to-spoke traffic without any static tunnel configuration between sites. Add a second hub for redundancy, plug in route reflectors, and you’ve got an architecture that scales to hundreds of branches without the management overhead of traditional MPLS or static IPsec mesh VPNs.

Enjoying this post?

Get more guides like this delivered straight to your inbox. No spam, just tech and trails.