Hi guys,

Today’s blog post is going to be focused on a basic DMVPN configuration using BGP as the routing protocol of choice.

I’ll break it up into stages:

Configure the tunnel with basic NHRP configuration to create the DMVPN instance. Apply IPSec to the DMVPN traffic so that it transits encrypted Configure iBGP to interconnect all spoke sites with each other.

So let’s get started.

Topology:

Tunnel Configuration

Starting with the HUB…

HUB1(config)#int Tunnel0 HUB1(config-if)# HUB1(config-if)#ip add 10.0.0.1 255.255.255.0 HUB1(config-if)#ip mtu 1400 HUB1(config-if)#ip tcp-adjust-mss 1360 HUB1(config-if)#ip nhrp authentication BLOGPOST HUB1(config-if)#ip nhrp map multicast dynamic HUB1(config-if)#ip nhrp network-id 10 HUB1(config-if)#ip nhrp holdtime 30 HUB1(config-if)#tunnel source f0/0 HUB1(config-if)#tunnel mode gre multipoint HUB1(config-if)#tunnel key 100000

So, the commands of interest here are the NHRP ones.

We apply authentication to the tunnel using the ip nhrp authentication command. This does secure our DMVPN instance to an extent but this is more used to prevent accidental joining of the DMVPN instance etc. In terms of actually securing the data plane, that is where our IPSec encryption will come in.

The ip nhrp map multicast dynamic command is used to ensure that the relevant multicast traffic is received at the hub.

ip nhrp network-id 10 is used for the creation of multiple DMVPN networks on a single device. It is a way of differentiating between them. It is a locally significant value however for the sake of ease it will be consistent across the design.

ip nhrp holdtime 30 specifies how long NBMA addresses will be advertised before being re-authenticated as valid.

In order for us to peer to multiple spokes at once, we must also configure our tunnel as mode gre multipoint. This basically enables us to dynamically create tunnels with spokes that are in our tunnel subnet of 10.0.0.0/24.

tunnel key 100000 is another command used to ensure devices pick the correct tunnel to transit data plane traffic. This mainly comes into play when you have multiple tunnels exiting and entering your network.

The two spoke configs:

SPOKE1(config-if)#ip add 10.0.0.2 255.255.255.0 SPOKE1(config-if)#ip mtu 1400 SPOKE1(config-if)#ip tcp adjust-mss 1360 SPOKE1(config-if)#ip nhrp authentication BLOGPOST SPOKE1(config-if)#ip nhrp nhs 10.0.0.1 nbma 15.1.1.1 multicast SPOKE1(config-if)#ip nhrp network-id 10 SPOKE1(config-if)#ip nhrp holdtime 30 SPOKE1(config-if)#tunnel source f0/0 SPOKE1(config-if)#tunnel mode gre multipoint SPOKE1(config-if)#tun key 100000

SPOKE2(config-if)#ip add 10.0.0.3 255.255.255.0 SPOKE2(config-if)#ip mtu 1400 SPOKE2(config-if)#ip tcp adjust-mss 1360 SPOKE2(config-if)#ip nhrp authentication BLOGPOST SPOKE2(config-if)#ip nhrp nhs 10.0.0.1 nbma 15.1.1.1 multicast SPOKE2(config-if)#ip nhrp network-id 10 SPOKE2(config-if)#ip nhrp holdtime 30 SPOKE2(config-if)#tunnel source f0/0 SPOKE2(config-if)#tunnel mode gre multipoint SPOKE2(config-if)#tunnel key 100000

Now the only command different and of significance here is the ip nhrp nhs 10.0.0.1 nbma 15.1.1.1 multicast command. What this command is basically saying is that to get information about the other spokes on the network, I must talk to the router at 10.0.0.1. However in order to get there physically, I have to map that to the NBMA address of 15.1.1.1. To ensure I transmit my multicast packets there, I add the optional multicast attribute at the end.

IPSec Configuration

I’m just going to use a fairly generic IPSec configuration and not go into too much detail as I think that deserves a blog post on it’s own. So here is the IPSec configuration applied to all the devices in the DMVPN cloud:

HUB1(config)#crypto isakmp policy 1 HUB1(config-isakmp)#encryption aes HUB1(config-isakmp)#authentication pre-share HUB1(config-isakmp)#group 14 HUB1(config)#crypto isakmp key BLOGPOST address 0.0.0.0 HUB1(config)#crypto ipsec transform-set BLOGTRANS esp-aes esp-sha-hmac HUB1(cfg-crypto-trans)#mode transport HUB1(config)#crypto ipsec profile BLOGPROF HUB1(ipsec-profile)#set transform-set BLOGTRANS

And to apply it to the tunnel interface:

HUB1(config)#interface Tunnel0 HUB1(config-if)#tunnel protection ipsec profile BLOGPROF

Two points to note here. The crypto isakmp key BLOGPOST address 0.0.0.0 uses the address of 0.0.0.0 so as to not require static configuration of each peer on the DMVPN network. This is to facilitate zero-touch deployments which is the basis on which DMVPN was designed. Spokes can be added at will without need to reconfigure hub routers.

The other point is the tunnel protection ipsec profile BLOGPROF command. In short, the tunnel protection command replaces the outdated and complex crypto mapping facility. This basically automatically generates all the attributes that a crypto map would have such as the ACL to permit gre traffic etc. Each peer that registers itself with the hub will have its own crypto map automatically generated. This dramatically cuts down on configuration and reduces the impact of human error.

BGP Configuration

So the BGP configuration is going to have a couple extra elements than the default configuration you are probably used to. I’ll explain these after I show you the config’s for both the hub and spokes:

HUB1(config)#router bgp 65000 HUB1(config-router)#bgp log-neighbor-changes HUB1(config-router)#no bgp default ipv4-unicast HUB1(config-router)#neighbor BLOGPOST peer-group HUB1(config-router)#neighbor BLOGPOST remote-as 65000 HUB1(config-router)#bgp listen range 10.0.0.0/24 peer-group BLOGPOST HUB1(config-router)#address-family ipv4 HUB1(config-router-af)#neighbor BLOGPOST activate HUB1(config-router-af)#neighbor BLOGPOST route-reflector-client

SPOKE1(config)#router bgp 65000 SPOKE1(config-router)#bgp log-neighbor-changes SPOKE1(config-router)#neighbor 10.0.0.1 remote-as 65000 SPOKE1(config-router)#network 2.2.2.2 mask 255.255.255.255

SPOKE2(config)#router bgp 65000 SPOKE2(config-router)#bgp log-neighbor-changes SPOKE2(config-router)#neighbor 10.0.0.1 remote-as 65000 SPOKE2(config-router)#network 3.3.3.3.3 mask 255.255.255.255

So…as you can see the spoke config is very, very simple indeed! It’s basically a one-touch deployment model and this can scale quite well to fairly large deployments. As for the HUB config, it also has simplicity to it. It seems more complicated than your standard BGP IPv4 peering configuration however these commands are simple in nature and save you a massive headache in the future. Let’s examine them:

no bgp default ipv4-unicast is a personal favourite of mine. It’s not necessarily needed in this deployment as we are fully IPv4 however when you start mixing in IPv4, MP-BGP etc…it’s very useful to not automatically have your neighbors brought up as IPv4 neighbors. This way I can configure them more specifically using the address-family ipv4 command, as shown in this example.

neighbor BLOGPOST peer-group is also useful. Most of you are probably aware of peer-groups + templates. They enable you to set specific attributes to multiple neighbors at once. This is a mandatory requirement when using the bgp listen range command as you do not configure neighbors statically or with static attributes.

bgp listen range 10.0.0.0/24 peer-group BLOGPOST is one of the main reasons why BGP scales so well in a DMVPN environment. This basically makes BGP operate kind of like an IGP, listening on a subnet for any BGP speaking neighbors.

neighbor BLOGPOST route-reflector-client enables you to scale iBGP in a DMVPN environment. Normally iBGP requires you to configure it as a full mesh setup due to the loop prevention mechanism of discarding routes containing their own AS number but route-reflector-client eliminates this behaviour. Without this, you would have to individually peer each spoke to each other and this would eliminate the use-case for dynamic and scalable DMVPN!

So, to wrap up….DMVPN is one of my absolute favourite technologies that exists in Cisco IOS. It gives you so much flexibility and so much ability to scale. It has been pouted as a potential use case for when IoT becomes common place, enabling you to secure your connection to devices using IPSec with dynamically created tunnels etc.

Let me know what you think of this post in the comments.