Classic hub-and-spoke IPsec has one ugly property: every packet between two branches has to climb up to the hub and back down. Two spokes 10ms apart end up 120ms apart because their traffic hairpins through a datacentre on another continent. ADVPN (Auto-Discovery VPN) removes that penalty by letting spokes build direct, on-demand shortcut tunnels to each other, while still using the hub as the control plane. This is the exact build I run in the lab, provisioned centrally from FortiManager so it scales.
What ADVPN actually does
The hub stays the anchor for routing, but it no longer has to carry spoke-to-spoke data:
- A branch sends traffic destined for another branch — it goes up the hub tunnel as normal.
- The hub recognises the flow, and via an IKE message tells both spokes about each other.
- The two spokes negotiate a dynamic shortcut tunnel directly.
- Subsequent packets take the direct path; the shortcut tears down after an idle timeout.
The hub is a route reflector, not a traffic concentrator. Once the shortcut is up, the datacentre uplink stops being the bottleneck for branch-to-branch traffic.
Two things make it work: IKEv2 for the auto-discovery signalling, and a routing overlay (iBGP) that preserves each spoke's next-hop so the shortcut can actually be resolved.
Lab topology
- HUB — datacentre FortiGate, static public IP, dial-up (dynamic) IPsec listener.
- SPOKE-A / SPOKE-B — branches on ordinary broadband, dynamic IPs.
- Overlay
10.200.0.0/24, each device with a loopback used for BGP. - Underlay = the internet; overlay = the ADVPN tunnel interface.
The phase-1 knobs that matter
This is where ADVPN lives. The hub runs a dynamic listener and advertises itself as a shortcut sender/forwarder:
config vpn ipsec phase1-interface
edit "ADVPN-HUB"
set type dynamic
set interface "wan1"
set ike-version 2
set peertype any
set net-device disable
set tunnel-search nexthop
set add-route disable
set auto-discovery-sender enable
set auto-discovery-forwarder enable
set psksecret <shared-secret>
set proposal aes256gcm-prfsha256
set dpd on-idle
next
end
Two hub settings trip people up: net-device disable keeps every spoke on one shared tunnel interface (instead of spawning one per peer), and tunnel-search nexthop tells the hub to resolve routes by next-hop so ADVPN shortcuts can be signalled.
The spokes are the mirror image — they receive shortcuts:
config vpn ipsec phase1-interface
edit "ADVPN-SPOKE"
set interface "wan1"
set ike-version 2
set remote-gw <hub-public-ip>
set auto-discovery-receiver enable
set net-device enable
set psksecret <shared-secret>
set proposal aes256gcm-prfsha256
set dpd on-idle
next
end
On the spoke, net-device enable is what lets a shortcut spin up its own child tunnel interface. Phase 2 on both ends uses wildcard selectors (0.0.0.0/0 ↔ 0.0.0.0/0) so any subnet can ride the overlay.
Routing: the hub as a BGP route reflector
ADVPN needs the overlay to hand a spoke the original next-hop of a remote spoke — not the hub's address — otherwise there's nothing to build a shortcut toward. iBGP with the hub as a route reflector does exactly that:
config router bgp
set as 65000
set router-id 10.200.0.254
config neighbor-group
edit "SPOKES"
set remote-as 65000
set route-reflector-client enable
set next-hop-self disable
set update-source "loopback0"
next
end
config neighbor-range
edit 1
set prefix 10.200.0.0 255.255.255.0
set neighbor-group "SPOKES"
next
end
end
next-hop-self disable on the reflector is the linchpin — it preserves the advertising spoke's overlay address as the next-hop, which is what the receiving spoke resolves the shortcut against. neighbor-range means you never hand-configure a BGP neighbour per branch; new spokes join dynamically.
Now do it fifty times — with FortiManager
Everything above is per-device CLI. Typing it into fifty spokes by hand is how you get fifty subtly-different configs and a bad on-call week. FortiManager gives you two clean ways to template it.
Option A — the SD-WAN Overlay template (fastest)
FortiManager's SD-WAN Overlay provisioning template is a wizard that generates the whole fabric for you: it asks for your regions, hub(s), WAN underlays and overlay addressing, then produces the IPsec (with ADVPN), BGP, SD-WAN zones, and the supporting CLI templates — plus the per-device metadata variables to make each spoke unique. For a greenfield hub-and-spoke this is the shortest path from zero to a working ADVPN fabric.
Option B — CLI template + metadata variables (full control)
When you want to own every line, build a CLI template and parameterise the per-spoke bits with metadata variables. Define variables like spoke_id, overlay_ip, and wan_if once per device, then reference them in one shared template:
config vpn ipsec phase1-interface
edit "ADVPN-SPOKE"
set interface "{{wan_if}}"
set remote-gw {{hub_public_ip}}
set auto-discovery-receiver enable
set net-device enable
next
end
config system interface
edit "loopback0"
set ip {{overlay_ip}} 255.255.255.255
next
end
Assign the template (or a template group bundling system, IPsec, BGP and SD-WAN) to a device group containing all spokes. Every spoke renders the same logic with its own values — one source of truth, fifty consistent configs.
Push it safely
Never install blind to production branches:
- Install Wizard → Install Preview shows the exact CLI diff each device will receive. Read it.
- Install to a pilot spoke first, confirm the tunnel and BGP session, then roll the rest.
- If FortiManager is in workspace mode, lock the ADOM, make changes, commit — otherwise nothing persists.
Verifying a shortcut actually forms
Bring up the base tunnels, then generate branch-to-branch traffic and watch the shortcut appear.
Check the parent tunnels and BGP first:
diagnose vpn ike gateway list
get router info bgp summary
Then, from a host behind SPOKE-A, ping a host behind SPOKE-B and watch the child tunnel negotiate:
diagnose vpn tunnel list
# a new shortcut interface appears, e.g. ADVPN-SPOKE_0, with the
# remote spoke's *public* IP as the gateway — proof it's direct, not via hub
traceroute between the two branches shows the spokes as adjacent hops — the hub is nowhere in the path. That's a live shortcut carrying the traffic directly.
The tell-tale sign of success: traceroute between the branches shows the two spokes as adjacent hops, with the hub nowhere in the path.
Gotchas from the bench
net-deviceis backwards between the roles —disableon the hub,enableon spokes. Getting this one setting wrong is the most common reason shortcuts silently never form.
- Use IKEv2. IKEv1 can do a single shortcut but IKEv2 is required for the signalling to behave at scale.
net-deviceis backwards between roles:disableon the hub,enableon spokes. Mixing this up is the most common reason shortcuts never form.- Next-hop preservation — if you set
next-hop-self enableon the hub reflector out of habit, shortcuts silently never build. Leave it disabled. - ADVPN behind NAT works, but both spokes behind symmetric NAT may fail to build a direct path and fall back to hub routing. Test your real branch NAT types.
- Template first, device later. Once you commit to FortiManager templates, stop editing spokes directly — a local change becomes config drift the next install will fight.
ADVPN turns a hub-and-spoke into something that behaves like a full mesh without the O(n²) tunnel management. FortiManager templates are what make that mesh a ten-minute rollout instead of a fifty-device slog.