VyOSXLI · WireGuardWireGuard
WireGuard routing — routing over WireGuard, MTU 1420, MSS clamping
What you'll learn
- Explain how packets flow through a WireGuard tunnel at the routing level
- Calculate the MTU of a WireGuard tunnel (1420 bytes)
- Configure the MSS clamping for TCP-over-tunnel
- Recognise the production routing failure modes (MTU, MSS, asymmetric routing)
Prerequisites
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-15
WireGuard tunnels carry IP packets across an untrusted network. The tunnel is a virtual interface (wg0) with its own IP address and MTU; packets sent into the tunnel are encrypted and encapsulated in UDP, then sent over the underlying network. The routing decision on the inner packet is independent of the routing decision on the outer packet; the operator must configure routes on both layers.
This lesson covers the routing flow through a WireGuard tunnel, the MTU calculation (1420 bytes for the inner packet, not 1500), the MSS clamping that makes TCP work over the tunnel, and the production patterns for dynamic routing (BGP, OSPF point-to-point) over the tunnel.
How packets flow through the tunnel
When a host sends a packet to a destination behind the peer:
- The host sends the packet to its default gateway (the local router’s LAN IP).
- The local router receives the packet on the LAN interface.
- The local router looks up the destination in its routing table; the destination matches the route through
wg0(installed by the peer’sallowed-ips). - The router sends the packet into
wg0. The WireGuard kernel module encrypts it and encapsulates it in a UDP packet. - The UDP packet is sent out the WAN interface (or whichever interface routes to the peer’s endpoint).
- The UDP packet travels across the untrusted network to the peer’s endpoint.
- The peer receives the UDP packet, decrypts the inner packet, and delivers it to the peer’s local network.
- The destination host receives the inner packet and responds.
- The reverse path (destination → peer → WAN → local router → LAN → host) follows the same steps in reverse.
sequenceDiagram
participant H1 as Host (10.0.0.50)
participant R1 as R1 (WireGuard)
participant NET as Untrusted network
participant R2 as R2 (WireGuard)
participant H2 as Host (10.20.0.50)
H1->>R1: TCP SYN to 10.20.0.50:80
R1->>R1: routing decision: 10.20.0.0/16 via wg0
R1->>R1: encrypt inner packet (10.0.0.50 -> 10.20.0.50)
R1->>NET: UDP packet (src=R1.pub, dst=R2.pub:51820)
NET->>R2: UDP packet
R2->>R2: decrypt inner packet
R2->>H2: TCP SYN (10.0.0.50 -> 10.20.0.50:80)
H2->>R2: TCP SYN-ACK
R2->>R2: encrypt reply (10.20.0.50 -> 10.0.0.50)
R2->>NET: UDP packet to R1.pub:51820
R1->>R1: decrypt reply
R1->>H1: TCP SYN-ACK
The inner packet travels through the tunnel transparently. The outer packet carries the encrypted payload. The router does not re-encrypt or re-route the inner packet during transit — it routes the outer packet based on the peer’s endpoint.
The MTU calculation — 1420, not 1500
The default Ethernet MTU is 1500 bytes. A WireGuard tunnel adds overhead:
| Layer | Overhead |
|---|---|
| Inner IP header | 20 bytes |
| Inner TCP header | 20 bytes |
| UDP header | 8 bytes |
| Outer IP header | 20 bytes |
| WireGuard encryption/padding | 32 bytes |
Total overhead: 80 bytes. The maximum inner packet size that fits in the outer 1500-byte Ethernet frame is:
1500 - 20 (outer IP) - 8 (UDP) - 32 (WireGuard) = 1440
Some sources use slightly different numbers (the exact overhead depends on whether IPv4 or IPv6, on whether the IP header has options, etc.). The most commonly cited value is 1420 bytes as the MTU for the WireGuard interface, leaving a safety margin.
# Set the MTU on the WireGuard interface
set interfaces wireguard wg0 mtu 1420
Some operators set the MTU lower (e.g., 1380) to be extra safe. The trade-off: lower MTU means more fragmentation for large packets. The right MTU depends on the underlying network’s path MTU.
MSS clamping for TCP
TCP connections negotiate their Maximum Segment Size (MSS) during the SYN/SYN-ACK exchange. The MSS is the largest TCP payload that fits in a single IP packet, accounting for the IP and TCP headers. For Ethernet, the standard MSS is 1460 bytes (1500 - 40 bytes for IP + TCP headers).
When a TCP connection goes through a WireGuard tunnel with MTU 1420, the MSS needs to be smaller (e.g., 1380 bytes for safety). Without MSS clamping, the TCP endpoints may agree on MSS 1460 and then send 1460-byte segments that exceed the tunnel MTU; the tunnel must fragment them (or drop them, depending on the DF bit).
The fix: MSS clamping at the firewall. The firewall (or the router) rewrites the MSS in the TCP SYN/SYN-ACK to a value appropriate for the tunnel.
# Configure MSS clamping on the WireGuard interface
set interfaces wireguard wg0 mss 1380
# or
set firewall options mss-clamp interface wg0 1380
The MSS clamp value should be slightly smaller than the MTU to allow for any additional overhead (e.g., 1380 for MTU 1420, leaving 40 bytes for IP + TCP headers).
Static routing over WireGuard
A typical site-to-site configuration has static routes pointing to the peer’s network via the tunnel interface:
# On R1
set protocols static route 10.20.0.0/16 next-hop 10.10.10.2
# Or directly through the interface
set protocols static route 10.20.0.0/16 interface wg0
# Verify
show ip route 10.20.0.0/16
# S* 10.20.0.0/16 [1/0] via 10.10.10.2, wg0
The route via the tunnel interface sends traffic into wg0; the kernel routes the encrypted packet via the WAN interface based on the peer’s endpoint.
Dynamic routing over WireGuard
BGP works well over WireGuard (BGP is unicast-only, which matches WireGuard’s unicast-only nature). OSPF requires configuration changes (network-type point-to-point, since WireGuard does not forward multicast).
# BGP over WireGuard
# On R1
set interfaces wireguard wg0 address 10.10.10.1/24
set protocols bgp system-as 65001
set protocols bgp neighbor 10.10.10.2 remote-as 65002
set protocols bgp neighbor 10.10.10.2 update-source 10.10.10.1
# Verify
show ip bgp summary
# The peer should be Established
# On R2
set protocols bgp system-as 65002
set protocols bgp neighbor 10.10.10.1 remote-as 65001
set protocols bgp neighbor 10.10.10.1 update-source 10.10.10.2
The BGP session runs over the tunnel (peer’s tunnel IP). BGP advertises routes; the routes are installed in the routing table; traffic flows via the tunnel.
OSPF requires additional configuration:
# OSPF over WireGuard (point-to-point)
set protocols ospf area 0 network 10.10.10.0/24
set interfaces wireguard wg0 ip ospf network point-to-point
# Verify
show ip ospf neighbor
# Should show the peer via wg0
WireGuard does not forward multicast (which OSPF uses for neighbour discovery). Setting the OSPF network type to point-to-point forces unicast OSPF hello packets; adjacency forms via direct unicast.
Configuration and validation
configure
# Set the MTU on the WireGuard interface
set interfaces wireguard wg0 mtu 1420
# Configure static routes for the peer's network
set protocols static route 192.168.50.0/24 next-hop 10.10.10.2
# Optional: BGP over the tunnel
set protocols bgp system-as 65001
set protocols bgp neighbor 10.10.10.2 remote-as 65002
# Configure MSS clamping at the firewall
set firewall options mss-clamp interface wg0 1380
commit
save
Validation:
# Verify the route
show ip route 192.168.50.0/24
# Should show "via wg0"
# Test with a large packet
ping -s 1400 192.168.50.1
# Should succeed; this is near the MTU
ping -s 1500 192.168.50.1
# Should fail (or fragment); this exceeds the tunnel MTU
# Verify the BGP session
show ip bgp summary
# The peer should be Established
# Trace the route
traceroute 192.168.50.1
# Should show the path via wg0
A clean validation: routes via the tunnel are correct; the MTU test with -s 1400 succeeds and -s 1500 fails (or fragments); the BGP session is established; the MSS is clamped (TCP works).
Production failure modes
MTU too low, performance suffers
The operator sets MTU to 800 on the WireGuard interface. Large packets are fragmented unnecessarily; throughput drops.
Diagnostic: ping -s 1400 <peer-tunnel> fails; ping -s 700 <peer-tunnel> succeeds.
Fix: set MTU to 1420 (IPv4) or 1380 (larger safety margin).
MTU too high, packets drop
The operator leaves the default MTU (1500). Large packets exceed the tunnel capacity; they are fragmented or dropped.
Diagnostic: ping -s 1400 <peer-tunnel> succeeds; ping -s 1500 <peer-tunnel> fails (or fragments with high drop rate).
Fix: set MTU to 1420.
MSS not clamped, TCP performance degrades
TCP connections negotiate MSS 1460; segments exceed the tunnel MTU; fragmentation/drops reduce throughput.
Diagnostic: tcpdump -ni wg0 shows fragmented packets. Web downloads are slow.
Fix: configure MSS clamping on the WireGuard interface (e.g., 1380).
Asymmetric routing
The forward path uses R1 → R2 → R3. The reverse path uses R3 → R2 → R1 (same path), but a stateful firewall in the middle drops the return packets because it has no state.
Diagnostic: traceroute shows different forward/reverse paths; TCP connections stall.
Fix: align the routing on both sides; ensure the same path is used for both directions.
OSPF adjacency does not form over WireGuard
OSPF does not establish adjacency; the peers remain in Down state.
Diagnostic: show ip ospf neighbor shows no peer; tcpdump -ni wg0 'proto 89' shows no OSPF packets.
Fix: configure OSPF network type as point-to-point on the WireGuard interface.
Rollback
# Enter configuration mode and write the running configuration to a
# file you can load back. `save` is a configuration-mode command that
# takes a path; operational mode has no `| save` pipe.
configure
save /config/pre-change-wg-routing-TICKET.conf
# Remove the WireGuard routing
delete protocols static route 192.168.50.0/24 next-hop 10.10.10.2
delete firewall options mss-clamp interface wg0
# Read the diff before committing anything
compare
commit
# Or restore the previous configuration
load /config/pre-change-wg-routing-TICKET.conf
commit
save
The rollback removes the routing and MSS clamp; traffic reverts to the original path (or fails if no backup path).
Production discipline
Cross-course references
- Part XLI-01 (
XLI-VyOS-WireGuard/ concept) covers the protocol basics. - Part XLI-03 (
XLI-VyOS-WireGuard/ peers) covers the peer configuration that sets up the routing. - Part LI-02 (
LI-VyOS-MTU/ tunnel overhead) covers the MTU calculations for tunnels in general. - Part LI-04 (
LI-VyOS-MTU/ MSS clamping) covers the MSS clamping mechanism. - Part XLIII-02 (
XLIII-VyOS-VPNRouting/ BGP over VPN) covers BGP over a tunnel in detail.
Quiz
Knowledge check · 4 questions
Q1. What is the recommended MTU for a WireGuard interface on an IPv4 network?
Q2. MSS clamping is optional for TCP-over-WireGuard connections; without it, TCP works fine because the TCP endpoints negotiate an MSS appropriate for the tunnel.
Q3. An operator deploys a WireGuard tunnel between two sites. Ping and traceroute work through the tunnel. However, web downloads from hosts behind the tunnel are slow — much slower than expected for the link capacity. What is the most likely cause?
R1 and R2 have a WireGuard tunnel. The MTU on wg0 is left at default (1500). No MSS clamping is configured. Hosts behind R1 can ping hosts behind R2 (small packets); traceroute works. But HTTP downloads from a host behind R2 are slow. The link capacity should support 100 Mbps; actual throughput is 10 Mbps.
Q4. An operator configures OSPF on the WireGuard interface. The OSPF adjacency does not form. The peers remain in Down state. What is the most likely cause?
R1 and R2 have a WireGuard tunnel (wg0). The operator configures OSPF area 0 on both routers with the wg0 interface as an OSPF interface. Default network type (broadcast). OSPF adjacency does not form. `show ip ospf neighbor` shows no peer.
Passing score: 75%. Answers are checked in this browser.