WireGuard VPN
WireGuard VPN
Section titled “WireGuard VPN”WireGuard is a modern VPN protocol built into the Linux kernel and supported natively by RouterOS v7+. It replaces complex negotiation protocols with a minimal, audited cryptographic design: Curve25519 key exchange, ChaCha20-Poly1305 encryption, BLAKE2s hashing. The result is a VPN that is simpler to configure, faster, and harder to misconfigure than IPsec or OpenVPN.
This guide covers interface setup, peer configuration, site-to-site tunnels, road warrior (remote access) configuration, and how WireGuard compares to IPsec.
Concepts
Section titled “Concepts”Interface and peer model
Section titled “Interface and peer model”A WireGuard interface is the local tunnel endpoint. RouterOS auto-generates a private/public key pair when the interface is created. You assign it a tunnel IP address, and it listens on a UDP port for encrypted traffic from peers.
A peer is a remote endpoint. Each peer has:
- A public key — the peer’s identity (generated on their side)
- An allowed-address list — which IP prefixes can be routed through this peer
- An optional endpoint-address/port — where to send outbound packets
The allowed-address field does double duty: it controls which source addresses are accepted from the peer inbound, and which destination addresses are routed to the peer outbound. RouterOS installs these as kernel routing entries automatically.
Allowed-address is routing
Section titled “Allowed-address is routing”When you add allowed-address=10.1.101.0/24,192.168.200.0/24 to a peer, RouterOS:
- Routes any packet destined for those prefixes out through the WireGuard interface to that peer.
- Accepts inbound packets from that peer only if their source falls within those prefixes.
Allowed-address ranges must not overlap between peers on the same interface. Overlapping ranges make routing ambiguous and will cause connectivity failures.
WireGuard vs IPsec
Section titled “WireGuard vs IPsec”| Feature | WireGuard | IPsec (IKEv2) |
|---|---|---|
| Configuration complexity | Low — interface + peers | High — profile, peer, identity, proposal, policy |
| Key exchange | Static keys (Curve25519) | Dynamic (IKE negotiation) |
| Crypto agility | Fixed modern primitives | Configurable (risk of weak choices) |
| NAT traversal | Built-in (UDP encapsulation) | Requires NAT-T (UDP 4500) |
| Rekeying | Automatic | IKE SA lifetime-based |
| Interoperability | WireGuard-only peers | Industry-wide (Cisco, Juniper, etc.) |
| RouterOS support | v7.1+ | All versions |
| Audit footprint | ~4000 lines of code | Very large |
Choose WireGuard for new RouterOS-to-RouterOS tunnels, remote access, and any situation where both endpoints can run WireGuard.
Choose IPsec when interoperating with third-party equipment (Cisco, Juniper, FortiGate), when your policy requires certificate-based authentication, or when running on RouterOS v6.
Prerequisites
Section titled “Prerequisites”- RouterOS 7.1 or later on all routers
- UDP reachability between WAN IPs on the chosen listen port (default 13231 or 51820)
- Public keys exchanged out-of-band between the two sides
Interface Setup
Section titled “Interface Setup”Create the WireGuard interface. RouterOS generates the key pair automatically.
/interface/wireguard/add listen-port=13231 mtu=1420 name=wireguard1Display the interface to get your public key — share this with the remote peer:
/interface/wireguard/printExample output:
Flags: X - disabled; R - running 0 R name="wireguard1" mtu=1420 listen-port=13231 public-key="base64publickey..." private-key="(hidden)"Assign a tunnel IP address:
/ip/address/add address=10.1.101.1/24 interface=wireguard1Peer Configuration
Section titled “Peer Configuration”Each remote endpoint is a peer entry. You need the remote side’s public key before proceeding.
/interface/wireguard/peers/add \ interface=wireguard1 \ public-key="REMOTE-PUBLIC-KEY-BASE64" \ allowed-address=10.1.101.2/32,192.168.200.0/24 \ endpoint-address=203.0.113.25 \ endpoint-port=13231 \ persistent-keepalive=25sKey parameters:
| Parameter | Purpose |
|---|---|
public-key | Remote peer’s identity (from their /interface/wireguard/print) |
allowed-address | IPs routed to/accepted from this peer — include peer tunnel IP + remote LANs |
endpoint-address | Peer’s WAN IP (or hostname); omit for dynamic clients |
endpoint-port | Peer’s listen port |
persistent-keepalive | Send keepalive every N seconds — use 25s for NAT traversal |
If only one side has a known public IP, set endpoint-address/endpoint-port only on the side that initiates. The passive side omits the endpoint and learns it from the first incoming packet.
Site-to-Site Tunnel
Section titled “Site-to-Site Tunnel”Scenario: Office1 (WAN 192.168.99.1, LAN 10.0.0.0/24) ↔ Office2 (WAN 192.168.88.2, LAN 10.255.255.0/24). Tunnel IPs: 10.1.101.1 (Office1) and 10.1.101.2 (Office2).
Office1
Section titled “Office1”/interface/wireguard/add listen-port=13231 mtu=1420 name=wireguard1/ip/address/add address=10.1.101.1/24 interface=wireguard1
# Paste Office2's public key in allowed-address/interface/wireguard/peers/add \ interface=wireguard1 \ public-key="OFFICE2-PUBLIC-KEY" \ allowed-address=10.1.101.2/32,10.255.255.0/24 \ endpoint-address=192.168.88.2 \ endpoint-port=13231 \ persistent-keepalive=25s
# Route Office2's LAN via the tunnel/ip/route/add dst-address=10.255.255.0/24 gateway=wireguard1
# Allow incoming WireGuard UDP/ip/firewall/filter/add \ chain=input protocol=udp dst-port=13231 \ action=accept comment="WireGuard" place-before=1Office2
Section titled “Office2”/interface/wireguard/add listen-port=13231 mtu=1420 name=wireguard1/ip/address/add address=10.1.101.2/24 interface=wireguard1
/interface/wireguard/peers/add \ interface=wireguard1 \ public-key="OFFICE1-PUBLIC-KEY" \ allowed-address=10.1.101.1/32,10.0.0.0/24 \ endpoint-address=192.168.99.1 \ endpoint-port=13231 \ persistent-keepalive=25s
/ip/route/add dst-address=10.0.0.0/24 gateway=wireguard1
/ip/firewall/filter/add \ chain=input protocol=udp dst-port=13231 \ action=accept comment="WireGuard" place-before=1Verify
Section titled “Verify”# Check tunnel state and last handshake time/interface/wireguard/peers/print detail
# Ping remote tunnel IP/ping 10.1.101.2
# Ping remote LAN host/ping 10.255.255.1A recent last-handshake value (within ~3 minutes) confirms the tunnel is active.
Road Warrior (Remote Access)
Section titled “Road Warrior (Remote Access)”Road warrior is the term for a VPN server that accepts connections from mobile clients with dynamic IPs. Each client gets a unique /32 allowed-address; the server never needs to know their endpoint in advance.
Server configuration
Section titled “Server configuration”# Create WireGuard interface/interface/wireguard/add listen-port=13231 mtu=1420 name=wireguard1
# Assign server tunnel IP/ip/address/add address=172.16.0.1/24 interface=wireguard1
# Allow incoming WireGuard UDP/ip/firewall/filter/add \ chain=input protocol=udp dst-port=13231 \ action=accept comment="WireGuard" place-before=1
# Masquerade WireGuard clients going to the internet/ip/firewall/nat/add \ chain=srcnat out-interface=ether1 \ action=masquerade comment="WireGuard client NAT"
# Add a peer for each client — one peer per user/interface/wireguard/peers/add \ interface=wireguard1 \ public-key="CLIENT1-PUBLIC-KEY" \ allowed-address=172.16.0.2/32
/interface/wireguard/peers/add \ interface=wireguard1 \ public-key="CLIENT2-PUBLIC-KEY" \ allowed-address=172.16.0.3/32Note: no endpoint-address on the server — clients connect from dynamic IPs.
Generating client configs
Section titled “Generating client configs”RouterOS can produce a ready-to-import config (including QR code) for each peer:
# Generate config for a specific peer/interface/wireguard/peers/show-client-config \ [find where interface=wireguard1 and allowed-address="172.16.0.2/32"]Add as-qr-code=yes to display a QR code for mobile apps.
The generated config includes:
- Client’s private key (from the peer entry)
- Server’s public key
- Client tunnel IP
- Server endpoint address and port
- DNS (if configured)
Client split-tunnel vs full-tunnel
Section titled “Client split-tunnel vs full-tunnel”| Mode | Client AllowedIPs |
|---|---|
| Split tunnel (LAN only) | 172.16.0.0/24, 10.0.0.0/24 — only VPN traffic through tunnel |
| Full tunnel (all traffic) | 0.0.0.0/0, ::/0 — all client traffic routed through server |
Full tunnel requires the masquerade NAT rule above to be in place on the server.
Allowed-Address Routing Details
Section titled “Allowed-Address Routing Details”How WireGuard routes traffic
Section titled “How WireGuard routes traffic”When RouterOS receives an outbound packet, it checks the WireGuard peer table for a peer whose allowed-address contains the destination. If found, the packet is encrypted and sent to that peer’s endpoint.
When RouterOS receives an inbound WireGuard packet, it decrypts it and checks whether the source IP is in the sending peer’s allowed-address. If not, the packet is dropped.
Non-overlapping requirement
Section titled “Non-overlapping requirement”# WRONG — both peers claim 10.0.0.0/8/interface/wireguard/peers/add ... allowed-address=10.0.0.0/8 # peer 1/interface/wireguard/peers/add ... allowed-address=10.0.0.0/8 # peer 2 — ERROR
# CORRECT — each peer owns distinct prefixes/interface/wireguard/peers/add ... allowed-address=10.1.0.0/24 # peer 1/interface/wireguard/peers/add ... allowed-address=10.2.0.0/24 # peer 2RouterOS will reject or misbehave on overlapping entries on the same interface.
Firewall Rules
Section titled “Firewall Rules”Minimum required firewall additions for WireGuard:
# Accept incoming WireGuard handshakes and data/ip/firewall/filter/add \ chain=input protocol=udp dst-port=13231 \ action=accept comment="WireGuard inbound" place-before=1
# Allow established/related through forward chain/ip/firewall/filter/add \ chain=forward connection-state=established,related \ action=accept comment="Forward established"
# Allow WireGuard clients to reach LAN/ip/firewall/filter/add \ chain=forward in-interface=wireguard1 \ action=accept comment="WireGuard to LAN"For IPv6 road warrior servers, add the same rules under /ipv6/firewall/filter.
Monitoring and Troubleshooting
Section titled “Monitoring and Troubleshooting”Status commands
Section titled “Status commands”# Interface state and public key/interface/wireguard/print detail
# Peer state: last handshake, rx/tx bytes, endpoint/interface/wireguard/peers/print detailA peer is healthy if last-handshake is within ~3 minutes. If it shows never, the tunnel has not exchanged a handshake — check firewall and public keys.
Enable debug logging
Section titled “Enable debug logging”/system/logging/add topics=wireguard,debug action=memory/log/print where topics~"wireguard"Common issues
Section titled “Common issues”| Symptom | Likely cause | Fix |
|---|---|---|
last-handshake: never | UDP port blocked or wrong endpoint | Check firewall on both sides; verify endpoint-address |
| Handshake OK, no traffic | Missing or wrong route | Check allowed-address and /ip route print |
| Connection drops under NAT | UDP state timed out | Add persistent-keepalive=25s to peer |
| Partial connectivity | Overlapping allowed-address | Make sure no two peers share prefix ranges |
| Fragmented large packets | MTU too high | Set interface MTU to 1420 |
WireGuard adds 60 bytes of overhead (32-byte header + 28 bytes for IPv4/UDP). With a standard 1500-byte Ethernet path:
1500 (Ethernet) - 60 (WireGuard overhead) = 1420 bytes tunnel MTU/interface/wireguard/set wireguard1 mtu=1420Key Management
Section titled “Key Management”RouterOS generates the private key automatically at interface creation. You cannot (and should not) set it manually. The public key is derived from the private key and is safe to share.
# Create interface — key pair generated automatically/interface/wireguard/add name=wireguard1 listen-port=13231 mtu=1420
# Read the public key to share with remote peers/interface/wireguard/printIf you need to rotate keys, remove and re-create the interface, then update all peers with the new public key.
Related Topics
Section titled “Related Topics”- IPsec Site-to-Site VPN — for third-party interoperability
- OpenVPN — certificate-based TLS VPN
- Firewall Filter — protecting VPN traffic with firewall rules
- IP Tunnels — GRE, IPIP, and other encapsulation options