WireGuard Mesh vs Hub-and-Spoke Topology Design - 夜莺博客

WireGuard Mesh vs Hub-and-Spoke Topology Design

WireGuard makes tunnels easy and topologies hard. The configuration syntax tells you nothing about whether every node should be a peer of every other node, and the two obvious answers have very different failure and latency characteristics. The decision is usually made once, at the start, by whoever writes the first config file — and it is expensive to reverse later. This article lays out the trade-offs honestly, explains the AllowedIPs behaviour that causes most misconfigurations, and gives concrete configurations for both designs.

Hub-and-spoke

One node is configured as a peer of every other; the spokes are peers only of the hub. Cross-spoke traffic is routed through the hub.

  • Pros — simple and additive. Adding a fourth node means one edit on the hub and one config on the new node. Spokes do not need to know each other's public keys or current addresses, so only the hub has to be reachable.
  • Cons — the hub is a single point of failure; if it is offline no spoke reaches any other. Cross-spoke latency is hub-relative even when a direct path exists. The hub's bandwidth is the ceiling for all cross-spoke traffic.

Hub-and-spoke is correct for the common case of clients reaching a central resource, and for anything beyond six or seven nodes where the configuration burden of a mesh becomes real.

Full mesh

Every node is a peer of every other. Three nodes means three pairwise tunnels.

  • Pros — no single point of failure, optimal latency on every path, and bandwidth per link rather than bottlenecked at one node.
  • Cons — N-squared configuration. Three nodes is three tunnels; five is ten; ten is forty-five. Manual maintenance stops being practical past about five nodes. Every node also needs a stable reachable address to its peers, which means public addresses or dynamic DNS, because WireGuard has no NAT traversal of its own.

For three nodes, full mesh wins: the N-squared problem does not exist yet, and giving each node a public address or a dynamic DNS hostname solves reachability.

The AllowedIPs traps

AllowedIPs does two jobs simultaneously, which is why it causes more outages than any other WireGuard statement: it is an inbound filter on the source address of packets arriving from that peer, and an outbound routing decision for anything the kernel wants to send to those addresses.

# Trap 1: the VPN tutorial value on a mesh spoke
[Peer]
AllowedIPs = 0.0.0.0/0        # routes the world through this peer

# Trap 2: overlapping ranges between peers
[Peer]                        # node B
AllowedIPs = 10.10.0.0/24
[Peer]                        # node C
AllowedIPs = 10.10.0.0/24     # identical - ambiguous routing

# Correct: each peer owns exactly its own address
[Peer]                        # node B
AllowedIPs = 10.10.0.2/32
[Peer]                        # node C
AllowedIPs = 10.10.0.3/32

The first trap is that 0.0.0.0/0 is right for a client VPN and catastrophic in a mesh: it tells the node that every destination belongs to one peer, so management access from anywhere else gets routed into a tunnel that cannot return the traffic. The second is subtler — with two peers claiming the same subnet, the kernel picks whichever the routing table prefers and the other peer silently rejects the inbound traffic because the source address does not match its filter. The symptom is one-directional failure: pings out, nothing back.

Keepalives

[Interface]
PrivateKey = ...
Address = 10.10.0.1/24
ListenPort = 51820

[Peer]   # node B, behind NAT
PublicKey = ...
Endpoint = node-b.example.com:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25

PersistentKeepalive = 25 sends a small packet every 25 seconds to hold the NAT mapping open. It is needed when a peer is behind NAT and you need to be able to initiate traffic toward it. Between two hosts with public addresses it is unnecessary overhead; between two NATed peers it is essential, because without it the mapping expires on both sides and the next packet has nowhere to go.

Comparing the two in operational terms

Property Hub-and-spoke Full mesh
Config effort at add-node 2 edits N edits
Hub failure All cross-site traffic stops No impact on other paths
Cross-node latency Via hub Direct
Aggregate bandwidth ceiling Hub's link Per link
NAT traversal Only the hub needs reachability Every node needs reachability
Practical node limit Dozens About five, hand-maintained

Growing beyond hand-maintained configs

At the point where the mesh becomes tedious, the right answer is usually to generate the configuration rather than to abandon the topology. A configuration management tool or a topology-aware generator can render every node's file from a single description of nodes and links, which removes the transcription errors that make hand-managed meshes dangerous. Adding dynamic routing on top of the tunnels — BIRD or OSPF over the interfaces — gives automatic path selection and failover, at the cost of one more daemon to operate.

Whichever topology you choose, verify the tunnel before trusting it: wg show for handshakes, wg-quick up|down for controlled restarts, and the MTU guidance from WireGuard MTU and handshake troubleshooting because tunnel overhead is a frequent cause of "the tunnel is up but large transfers stall". A conventional point-to-point design is documented in WireGuard site-to-site VPN configuration if you only need two sites.

原文链接:https://animatedcreativity.com/tutorials/wireguard-mesh-between-three-personal-servers-hub-and-spoke-vs-full-mesh-and-the-allowedip/