Skip to main content
RunBook Academy

VyOSXLI · WireGuardWireGuard

WireGuard concept — kernel WireGuard, Noise protocol, UDP-based VPN

Advanced⏱ ~18 minshow interfaces wireguardgenerate pki wireguard key-pairconfigurecomparecommitsaverollbackwgtcpdumpip

What you'll learn

  • Define what WireGuard is at the protocol level
  • Explain the role of the Linux kernel module and the Noise protocol
  • Distinguish WireGuard from IPsec (route-based vs policy-based)
  • Recognise why production networks adopt WireGuard (speed, simplicity, modern crypto)

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-19

Not yet marked complete on this device.

WireGuard is a kernel-space VPN that has, in the last five years, become the default choice for many production site-to-site and remote-access deployments. It is fast (kernel-space cryptography, no userspace daemon overhead), secure (modern cryptography with no legacy ciphers), simple (a configuration of about 20 lines per peer), and reliable (the kernel module is small and well-audited). Compared with IPsec and OpenVPN, WireGuard trades protocol complexity for configuration simplicity and cryptographic modernity.

This lesson covers what WireGuard is at the protocol level, why it lives in the kernel, what the Noise Protocol Framework buys, the cryptography choices, and how WireGuard differs from IPsec and OpenVPN at a level the operator needs to read.

What WireGuard is

WireGuard is a tunnelling protocol that creates a virtual point-to-point link between two peers. The tunnel carries encrypted IP packets across an untrusted network, similar in principle to IPsec tunnel mode or OpenVPN. The difference is in the implementation:

  1. Kernel-space. WireGuard is implemented as a Linux kernel module (since Linux 5.6, January 2020). The cryptographic operations run in kernel space, alongside the network stack. There is no userspace daemon for the data path (in fact, WireGuard deliberately has no separate userspace daemon at all — the kernel module handles both control and data plane).
  2. Modern cryptography. WireGuard uses a small, fixed set of cryptographic primitives: Curve25519 for key exchange, ChaCha20 for symmetric encryption, Poly1305 for authentication, BLAKE2 for hashing, HKDF for key derivation, and SipHash24 for hashtable keys. There are no configuration options for cipher selection; the protocol is the cryptography.
  3. UDP transport. WireGuard carries its packets as UDP (default port 51820). UDP is connectionless; WireGuard simulates the connection state in its own handshake protocol.
  4. Single protocol family. WireGuard supports IPv4 and IPv6 simultaneously. Each peer can have multiple allowed-ips; the kernel routes the inner packet based on the source/destination IPs.
flowchart LR
  subgraph A["Endpoint A (VyOS)"]
    APP1["Application"]
    WG1["WireGuard kernel module<br/>wg0"]
  end
  subgraph B["Endpoint B (VyOS)"]
    WG2["WireGuard kernel module<br/>wg0"]
    APP2["Application"]
  end
  APP1 --> WG1
  WG1 -- "encrypted UDP/51820<br/>(outer IP header)" --> NET["Untrusted network"]
  NET --> WG2
  WG2 --> APP2

The kernel module is the only thing on the data path. There is no userspace processing for individual packets; the kernel does the encryption and routing. The result is throughput close to line rate on commodity hardware.

The Noise Protocol Framework

WireGuard uses the Noise Protocol Framework (noiseprotocol.org) for its handshake. Noise is a framework for cryptographic protocols — a set of primitives that can be combined to create different protocols. WireGuard uses Noise’s IK pattern:

  • I: the initiator’s static public key (long-term identity).
  • K: the responder’s static public key, known to the initiator.

The IK pattern produces a 1-RTT handshake: the initiator sends its static public key and an ephemeral public key in the first message; the responder replies with its static public key and an ephemeral public key; both sides derive the same symmetric session keys.

sequenceDiagram
  participant I as Initiator
  participant R as Responder
  Note over I,R: Both know each other's static public keys
  I->>R: msg 1: ephemeral pk, static pk (encrypted), timestamp, MAC1
  R->>I: msg 2: ephemeral pk, empty (encrypted), MAC1, MAC2
  Note over I,R: Both sides derive the same session keys
  Note over I,R: Data transport begins
  I->>R: encrypted data
  R->>I: encrypted data
  Note over I,R: After 2 minutes (or 2^64 messages)<br/>rekey
  I->>R: msg 1: new ephemeral pk, ...

The WireGuard handshake is intentionally minimal — 1 round trip, 2 messages, 2 MAC computations. Compare to IKEv2 (used by IPsec) which has a more complex handshake with multiple round trips and authentication options. The simplicity is a deliberate design choice: less code, less attack surface, fewer ways for the protocol to be misconfigured.

Cryptographic choices

WireGuard uses a small set of cryptographic primitives, all considered modern and well-reviewed:

FunctionAlgorithm
Key exchangeCurve25519 (X25519)
Symmetric encryptionChaCha20
AuthenticationPoly1305
HashingBLAKE2s
Key derivationHKDF
Hashtable keysSipHash24
Nonces96-bit random nonces

These choices are baked into the protocol. The operator cannot select alternate ciphers (no AES, no RSA, no SHA-1, no DH group 1, etc.). The trade-off: no flexibility to choose a weak cipher. The implementation is fixed; the cryptography is fixed; the only key material the operator manages is the peer’s static public key.

WireGuard vs IPsec

WireGuard and IPsec are both VPNs, but they are designed differently. The operator needs to understand the differences to make a sensible choice.

PropertyWireGuardIPsec (IKEv2)
TransportUDPUDP (NAT-T) or IP protocol 50 (ESP)
Kernel spaceYes (Linux 5.6+)Yes (xfrm)
Userspace daemonNonestrongSwan, racoon, etc.
Cipher selectionFixed (ChaCha20-Poly1305)Configurable (AES-GCM, ChaCha20, etc.)
AuthenticationPublic keyPSK, certificates, EAP
Configuration complexityLowHigh
NAT traversalBuilt-inNAT-T (UDP 4500)
Multicast/broadcastNo (unicast only)Yes (with limitations)
Routing interactionRoute-based (wg0 interface)Policy or route-based (VTI)

WireGuard is simpler, faster, and more modern. IPsec is more flexible, more complex, and has more options. The right choice depends on the use case:

  • Simple site-to-site with two endpoints. WireGuard — minimal configuration.
  • Site-to-site with complex traffic selectors. IPsec with policy-based configuration.
  • Remote access for many devices. WireGuard — easy to provision clients.
  • Compliance-mandated cipher selection. IPsec — explicit cipher choice.

A common production pattern: site-to-site VPNs use WireGuard; legacy remote-access VPNs use IPsec (for compatibility with older clients); compliance-required deployments use IPsec with explicit cipher controls.

WireGuard vs OpenVPN

WireGuard and OpenVPN are both userspace-configured but differ in implementation.

PropertyWireGuardOpenVPN
Kernel/userspaceKernelUserspace
PerformanceNear line rate50-70% of line rate
TLSNoise (built-in)TLS (separate library)
UDP/TCPUDP onlyUDP or TCP
ComplexityLow (single config block)High (TLS, certificates, etc.)
AdoptionDefault for new deploymentsLegacy

WireGuard is faster, simpler, and more modern. OpenVPN is the legacy choice; many networks still run OpenVPN because of historical deployments and the TCP-mode support (which WireGuard does not have).

The discipline: pick WireGuard for new deployments; keep OpenVPN for legacy compatibility.

Configuration on VyOS 1.5 LTS

A WireGuard interface on VyOS 1.5 has two halves: the interface itself, which owns the private key, an address and a listening port; and one or more named peers under it. peer is a tag node — the name is a label you choose (the interface definition calls it a “peer alias” and allows up to 100 characters), and it appears nowhere on the wire. The far end’s socket is address plus port, two separate leaves.

configure

# Generate the key pair. Run from configuration mode with `run` and the
# private half is imported into the candidate configuration for you;
# the command prints the public half for the far end.
run generate pki wireguard key-pair install interface wg0

# The interface: tunnel address and the UDP port this router listens on.
set interfaces wireguard wg0 address '10.10.10.1/30'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 description 'VPN-to-SITE-B'

# The peer. SITE-B is a name of your choosing, not part of the protocol.
set interfaces wireguard wg0 peer SITE-B public-key 'XMrlPykaxhdAAiSjhtPlvi30NVkvLQliQuKP7AI7CyI='
set interfaces wireguard wg0 peer SITE-B address '198.51.100.2'
set interfaces wireguard wg0 peer SITE-B port '51820'
set interfaces wireguard wg0 peer SITE-B allowed-ips '10.10.10.0/30'
set interfaces wireguard wg0 peer SITE-B allowed-ips '10.0.0.0/24'
set interfaces wireguard wg0 peer SITE-B persistent-keepalive '25'

# allowed-ips does not create a route on VyOS. Steer the traffic yourself.
set protocols static route 10.0.0.0/24 interface wg0

compare
commit
save

The commit-time checks in interfaces_wireguard.py tell you what the minimum really is, and each one names the peer it is unhappy about:

ConditionError at commit
No private-key on the interfaceWireguard private-key not defined
No peer at allAt least one Wireguard peer is required!
Peer without allowed-ipsWireguard allowed-ips required for peer "SITE-B"!
Peer without public-keyWireguard public-key required for peer "SITE-B"!
address without port, or port without addressBoth Wireguard port and address must be defined for peer "SITE-B" if either one of them is set!
Same public key on two peers of one interfaceDuplicate public-key defined on peer "SITE-B"
Peer carrying this interface’s own public keyPeer "SITE-B" has the same public key as the interface "wg0"

That last one almost always means both routers’ key pairs were generated in the same place and got crossed. Note that all of these fire at commit, not at set — the only thing rejected as you type is a value that fails its own constraint, such as a key that is not base64 (Key is not base64-encoded) or an interface not named wgN (WireGuard interface must be named wgN).

Validation

# The peer table, handshake age and byte counters. This is the command
# that answers "is the tunnel up".
show interfaces wireguard wg0 summary

# The interface as the kernel sees it: link state, addresses, counters.
show interfaces wireguard wg0

# The public key to hand to the far end (the private half stays hidden).
show interfaces wireguard wg0 public-key

# Narrower views of the same state.
show interfaces wireguard wg0 peers
show interfaces wireguard wg0 endpoints
show interfaces wireguard wg0 allowed-ips

# Capture the outer packets on the WAN interface.
monitor traffic interface eth0 filter 'udp port 51820'

# Test the tunnel itself, then something behind it.
ping 10.10.10.2
ping 10.0.0.10

# Verify the route to the peer's network exists and points at wg0.
show ip route 10.0.0.0/24

summary is the one that matters, and this is what it prints:

vyos@R1:~$ show interfaces wireguard wg0 summary
interface: wg0
  public key: rSuuvkAuSoyqvogoA5OJjYBbJKKaYS13pWs4K69PTOE=
  private key: (hidden)
  listening port: 51820

peer: XMrlPykaxhdAAiSjhtPlvi30NVkvLQliQuKP7AI7CyI=
  endpoint: 198.51.100.2:51820
  allowed ips: 10.10.10.0/30, 10.0.0.0/24
  latest handshake: 1 minute, 3 seconds ago
  transfer: 1.15 MiB received, 942.53 KiB sent
  persistent keepalive: every 25 seconds

A clean validation: the peer appears with a latest handshake measured in seconds or a couple of minutes rather than hours, and transfer counters that are non-zero in both directions; the tunnel interface holds the configured address; ping to a host behind the tunnel succeeds.

Production failure modes

No handshake

The peer is configured, but show interfaces wireguard wg0 summary shows the peer with no latest handshake line at all. The peer’s public key is wrong (each side must hold the other side’s public half, never its own), the far end’s address/port pair points somewhere unreachable, or a firewall between the two drops UDP 51820.

Diagnostic: show interfaces wireguard wg0 summary; show interfaces wireguard wg0 public-key on each router, compared against the peer ... public-key configured on the other; monitor traffic interface eth0 filter 'udp port 51820' to see whether handshake initiations are leaving and whether anything comes back.

Fix: correct the public key, correct address/port, or open the firewall. A capture that shows initiations going out and nothing returning points at the far end or the path; a capture that shows nothing leaving points at this router.

Asymmetric path

The forward path works (VyOS-A → VyOS-B through WireGuard); the reverse path is broken. The far end has session state but the source addresses of the returning packets are not covered by that peer’s allowed-ips, so the kernel discards them on receipt.

Diagnostic: capture on both endpoints. Traffic leaves one router and is not delivered by the other; the receiving side’s transfer: counter increments (the packets arrived and decrypted) while the application sees nothing.

Fix: align the allowed-ips lists so each is the mirror image of the other. allowed-ips is checked in both directions — outbound it selects which peer to encrypt for, inbound it decides whether a decrypted packet’s source address is one that peer is allowed to claim.

MTU too high

The default Ethernet MTU is 1500; WireGuard adds overhead (UDP, IP, encryption); the resulting tunnel MTU is approximately 1420. Packets larger than 1420 are fragmented or dropped.

Diagnostic: ping with the -s option to set the packet size; find the largest packet that passes.

Fix: clamp the MSS (Maximum Segment Size) at the firewall; reduce the MTU on the tunnel interface.

Routing not configured

The tunnel is up (the handshake succeeds and the peer shows a recent handshake), but traffic to the remote network does not flow. This is the commonest first-day WireGuard failure on VyOS and the cause is structural: allowed-ips is not a route. VyOS hands the list to wg set and nothing else — the interface script contains no route installation at all. Unlike wg-quick, which reads AllowedIPs from a .conf file and adds matching routes, the VyOS CLI leaves routing entirely to you.

Diagnostic: show ip route 10.0.0.0/24 returns nothing, while show interfaces wireguard wg0 summary shows a healthy recent handshake.

Fix: add the route — set protocols static route 10.0.0.0/24 interface wg0 — or run a routing protocol over the tunnel (Part XLIII). Remember that the prefix must appear in both places: in the routing table so the packet is sent to wg0, and in that peer’s allowed-ips so WireGuard will encrypt it. Either one alone is a silent drop.

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-TICKET.conf

# Remove the WireGuard configuration
delete interfaces wireguard wg0

# Read the diff before committing anything
compare
commit

# Or restore a previous configuration
load /config/pre-change-wg-TICKET.conf
commit
save

The rollback removes the WireGuard interface; the tunnel goes down; routing through the tunnel is removed; traffic falls back to the original path (or fails if no backup path exists).

Production discipline

Cross-course references

  • Part XLI-02 (XLI-VyOS-WireGuard / keys) covers the Curve25519 key generation and management.
  • Part XLI-03 (XLI-VyOS-WireGuard / peers) covers the named peer node in detail: public-key, allowed-ips, and the address/port pair that replaced the old single endpoint leaf.
  • Part XLII-01 (XLII-VyOS-IPsec / IPsec concept) covers the IPsec alternative that WireGuard is often compared to.
  • Part LI-02 (LI-VyOS-MTU / tunnel overhead) covers the MTU calculations for tunnels, including WireGuard.

Quiz

Knowledge check · 4 questions

  1. Q1. WireGuard carries its packets using which transport layer?

  2. Q2. WireGuard's handshake protocol is based on the Noise Protocol Framework's IK pattern, which is a 1-round-trip protocol (one message in each direction to establish session keys).

  3. Q3. An operator wants to run OSPF (which uses multicast for neighbour discovery) over a WireGuard tunnel. After configuration, OSPF adjacency does not establish. What is the most likely cause?

    VyOS-A and VyOS-B have a WireGuard tunnel (wg0). The tunnel has handshaked successfully (verified with `show interfaces wireguard wg0 summary`). The operator configures OSPF on the wg0 interface with network-type broadcast, expecting the standard OSPF behaviour. OSPF does not establish adjacency. The operator suspects a configuration error.

  4. Q4. An operator notices that WireGuard throughput on a Linux router is at line rate (~940 Mbps on a 1G link), while OpenVPN throughput on the same router is approximately 500 Mbps. What explains the difference?

    VyOS-A and VyOS-B have both WireGuard and OpenVPN configured between them (separate tunnels). WireGuard throughput is 940 Mbps; OpenVPN throughput is 500 Mbps. The operator is benchmarking to choose which VPN to use for a new deployment. Both tunnels carry the same encrypted payload.

Passing score: 75%. Answers are checked in this browser.