Back to blog

Cisco / IOS  ·  VPN  ·  July 2026

Cisco IOS
DMVPN

Site-to-site VPN works fine for two offices. Try it for thirty branches and you've hand-built a full mesh of tunnels that nobody can maintain. DMVPN is the answer: configure the hub once, add spokes without ever touching it, and let spokes build direct tunnels to each other on demand. This is the scalable WAN, explained without the mystique.

Cisco IOS DMVPN mGRE NHRP IPsec VPN

The problem DMVPN solves is combinatorial. Classic site-to-site tunnels are one-per-pair; a full mesh of N sites needs N(N-1)/2 tunnels, and every new branch means editing every existing router. DMVPN collapses that into one multipoint tunnel interface per router. It stands on three legs: mGRE (a single GRE interface that reaches many endpoints), NHRP (a "next-hop resolution" registry where spokes register with the hub and look each other up), and IPsec (a tunnel-protection profile encrypting it all).

Add a spoke and it registers with the hub — the hub needs zero changes. And with Phase 3, when two spokes talk, NHRP resolves a direct spoke-to-spoke tunnel so their traffic doesn't hairpin through the hub. It's the natural next step after the two-site VPN, and its RouterOS counterpart — RouterOS has no DMVPN — is covered in MikroTik hub-and-spoke.

Prerequisites

01

The Hub — Configure Once, Forever

A multipoint GRE tunnel, an NHRP network for spokes to register into, and tunnel protection. The hub accepts dynamic registrations, so you never edit it again as branches come and go.

IOS (HUB) — mGRE + NHRP + IPsec-protected Tunnel0
HUB(config)# interface Tunnel0
HUB(config-if)# ip address 172.16.0.1 255.255.255.0   # the DMVPN subnet
HUB(config-if)# tunnel source GigabitEthernet0/0       # its public interface
HUB(config-if)# tunnel mode gre multipoint            # mGRE — many endpoints
HUB(config-if)# ip nhrp network-id 1
HUB(config-if)# ip nhrp map multicast dynamic         # let spokes register
HUB(config-if)# ip nhrp redirect                     # Phase 3: enable spoke-to-spoke
HUB(config-if)# tunnel protection ipsec profile DMVPN-PROF
# Routing over the tunnel (OSPF here). On a hub, network type matters:
HUB(config-if)# ip ospf network broadcast

02

A Spoke — Point at the Hub, Done

Each spoke gets a nearly identical block, plus a static NHRP map to the hub (its "next-hop server"). Copy it to every branch, changing only the tunnel IP.

IOS (SPOKE) — register with the hub as NHS
SPOKE(config)# interface Tunnel0
SPOKE(config-if)# ip address 172.16.0.11 255.255.255.0
SPOKE(config-if)# tunnel source GigabitEthernet0/0
SPOKE(config-if)# tunnel mode gre multipoint
SPOKE(config-if)# ip nhrp network-id 1
# The hub's tunnel IP + real public IP, and register to it:
SPOKE(config-if)# ip nhrp nhs 172.16.0.1 nbma 203.0.113.1 multicast
SPOKE(config-if)# ip nhrp shortcut                    # Phase 3: accept redirects
SPOKE(config-if)# tunnel protection ipsec profile DMVPN-PROF
⚠ Gotcha — NBMA vs Tunnel Address, and the Routing Trap

DMVPN has two address planes and confusing them is the classic mistake. The NBMA address is the real public IP the packet is sent to; the tunnel address (172.16.x) is the overlay the routing protocol runs on. NHRP's whole job is mapping tunnel→NBMA. The routing trap: on the hub, don't let OSPF summarise away the spoke routes or change next-hops — spokes need the other spoke's tunnel IP as next-hop for Phase-3 shortcuts to work. On point-to-multipoint designs, watch OSPF network types (broadcast on hub, and matching on spokes) or adjacencies flap.

03

Phase 3 — Spokes Talk Directly

By default spoke-to-spoke traffic goes up to the hub and back down — a hairpin. Phase 3 (redirect on the hub, shortcut on spokes) makes NHRP resolve a temporary direct tunnel so branch A reaches branch B without the hub in the path.

IOS — watch a spoke-to-spoke tunnel form on demand
# Before any traffic: only the hub tunnel exists.
SPOKE-A# show dmvpn
 1 172.16.0.1  203.0.113.1  UP  static          # hub only

# Ping spoke B's LAN once -> hub redirects -> NHRP resolves B directly:
SPOKE-A# ping 10.20.0.1 source 10.10.0.1
SPOKE-A# show dmvpn
 1 172.16.0.1   203.0.113.1   UP  static
 1 172.16.0.12  198.51.100.2  UP  dynamic       # direct to spoke B!

04

Verify the Overlay Safe to Run

Three layers to confirm, in order: NHRP registrations, the IPsec SAs protecting them, and the routing adjacencies over the tunnel.

IOS — the DMVPN health walk
HUB# show ip nhrp                 # every spoke registered? tunnel->NBMA maps
HUB# show dmvpn detail            # peer states, crypto, uptime
HUB# show crypto ipsec sa | inc peer|pkts  # SAs up, encaps climbing
HUB# show ip ospf neighbor        # all spokes FULL on the tunnel
SymptomWhere to look
Spoke never registersNHS/NBMA wrong, or network-id mismatch. debug nhrp.
Registered but no encryptionIPsec profile/proposal mismatch — same as the two-site build.
Hub works, no spoke-to-spokeMissing redirect (hub) / shortcut (spoke), or next-hop rewritten by routing.
OSPF adjacency flapsMismatched network types over the mGRE tunnel.

Takeaways

  1. DMVPN kills the full-mesh problem — one multipoint tunnel per router instead of N² site-to-site tunnels.
  2. Three legs: mGRE (many endpoints, one interface), NHRP (registration + resolution), IPsec (tunnel protection).
  3. The hub is configured once — spokes register dynamically, so adding a branch never touches the hub.
  4. Keep NBMA (real public IP) and tunnel (overlay) addresses straight — NHRP maps between them; confusing them is the top mistake.
  5. Phase 3 (redirect + shortcut) gives direct spoke-to-spoke tunnels on demand, so branch traffic doesn't hairpin through the hub.
  6. Don't let routing rewrite spoke next-hops or summarise them away, or Phase-3 shortcuts break.

A growing branch network stitched together with one-off VPN tunnels?

NOCTIS designs scalable WANs on Cisco and MikroTik across Crete — hub-and-spoke overlays where adding a site is a copy-paste, spokes talk directly, and the whole thing routes and fails over cleanly.

Book a Discovery Call →