WireGuard VPN
WireGuard VPN
Section titled “WireGuard VPN”TL;DR (Quick start)
Section titled “TL;DR (Quick start)”Create a basic WireGuard tunnel between two routers:
On Router A (initiator):
/interface wireguard add name=wg-tunnel listen-port=13231/interface wireguard print# Note the public-key value and share with Router B
/interface wireguard peers add interface=wg-tunnel \ public-key="<ROUTER_B_PUBLIC_KEY>" \ allowed-address=10.255.255.2/32,192.168.2.0/24 \ endpoint-address=198.51.100.20 endpoint-port=13231/ip address add address=10.255.255.1/30 interface=wg-tunnel/ip route add dst-address=192.168.2.0/24 gateway=wg-tunnelOn Router B (responder):
/interface wireguard add name=wg-tunnel listen-port=13231/interface wireguard print# Note the public-key value and share with Router A
/interface wireguard peers add interface=wg-tunnel \ public-key="<ROUTER_A_PUBLIC_KEY>" \ allowed-address=10.255.255.1/32,192.168.1.0/24/ip address add address=10.255.255.2/30 interface=wg-tunnel/ip route add dst-address=192.168.1.0/24 gateway=wg-tunnelAdd firewall rule on both:
/ip firewall filter add action=accept chain=input protocol=udp dst-port=13231 place-before=0Overview
Section titled “Overview”WireGuard is a modern VPN protocol that provides secure, high-performance tunnels using state-of-the-art cryptography (Curve25519, ChaCha20, Poly1305, BLAKE2s). It operates on a peer-to-peer model with no inherent server/client distinction.
What this does:
- Creates encrypted tunnels between RouterOS devices or third-party clients
- Uses cryptographic key pairs for authentication (no passwords)
- Routes traffic based on “allowed-address” lists (cryptokey routing)
- Automatically handles NAT traversal with keepalive packets
When to use WireGuard:
- Site-to-site tunnels between offices
- Road warrior remote access for mobile devices
- Hub-and-spoke VPN topologies
- When you need simpler configuration than IPsec
- When you want better performance than OpenVPN
When NOT to use it:
- Compatibility with legacy devices that don’t support WireGuard
- When you need certificate-based authentication
- When TCP-based VPN is required (some corporate firewalls block UDP)
Prerequisites
Section titled “Prerequisites”- MikroTik router running RouterOS 7.1 or later
- At least one side with a public IP or port forwarding configured
- UDP port 13231 (default) accessible through firewalls
- Access to exchange public keys between peers
Configuration Steps
Section titled “Configuration Steps”Step 1: Create the WireGuard Interface
Section titled “Step 1: Create the WireGuard Interface”Create a WireGuard interface on each router. The private key is auto-generated.
/interface wireguard add name=wg-tunnel listen-port=13231Step 2: Get the Public Key
Section titled “Step 2: Get the Public Key”Display the interface to see the auto-generated public key:
/interface wireguard printExample Output:
Flags: X - disabled; R - running 0 R name="wg-tunnel" mtu=1420 listen-port=13231 private-key="<hidden>" public-key="A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V="Copy the public-key value and share it with the remote peer (via secure channel like email or chat).
Step 3: Configure the Remote Peer
Section titled “Step 3: Configure the Remote Peer”Add the remote peer using their public key and define which networks are reachable through them:
/interface wireguard peers add interface=wg-tunnel \ public-key="<REMOTE_PUBLIC_KEY>" \ allowed-address=10.255.255.2/32,192.168.2.0/24 \ endpoint-address=198.51.100.20 \ endpoint-port=13231Key properties:
public-key: The remote peer’s public key (required)allowed-address: Networks reachable via this peer (acts as both ACL and routing)endpoint-address: Remote peer’s public IP or hostname (required on initiator)endpoint-port: Remote peer’s WireGuard port
Step 4: Assign Tunnel IP Address
Section titled “Step 4: Assign Tunnel IP Address”Assign an IP address to the WireGuard interface for the tunnel network:
/ip address add address=10.255.255.1/30 interface=wg-tunnelUse a dedicated /30 or /31 subnet for point-to-point tunnels.
Step 5: Add Routes for Remote Networks
Section titled “Step 5: Add Routes for Remote Networks”Add static routes for the remote LAN:
/ip route add dst-address=192.168.2.0/24 gateway=wg-tunnelStep 6: Configure Firewall Rules
Section titled “Step 6: Configure Firewall Rules”Allow WireGuard handshake traffic and forwarding:
/ip firewall filteradd action=accept chain=input protocol=udp dst-port=13231 comment="WireGuard" place-before=0add action=accept chain=forward in-interface=wg-tunnel comment="WireGuard forward in" place-before=0add action=accept chain=forward out-interface=wg-tunnel comment="WireGuard forward out" place-before=0Common Scenarios
Section titled “Common Scenarios”Scenario 1: Road Warrior (Remote Access)
Section titled “Scenario 1: Road Warrior (Remote Access)”Configure a server with multiple mobile clients (phones, laptops) connecting remotely:
Server Configuration:
# Create interface/interface wireguard add name=wg-server listen-port=13231
# Assign server IP (use a dedicated subnet for VPN clients)/ip address add address=192.168.100.1/24 interface=wg-server
# Add peers for each client (use /32 for individual clients)/interface wireguard peers add interface=wg-server \ public-key="<CLIENT_1_PUBLIC_KEY>" \ allowed-address=192.168.100.2/32 \ name=laptop
/interface wireguard peers add interface=wg-server \ public-key="<CLIENT_2_PUBLIC_KEY>" \ allowed-address=192.168.100.3/32 \ name=phone
# Firewall rules - allow WireGuard and forwarding/ip firewall filteradd action=accept chain=input protocol=udp dst-port=13231 place-before=0add action=accept chain=forward in-interface=wg-server place-before=0add action=accept chain=forward out-interface=wg-server place-before=0
# NAT masquerade - REQUIRED for clients to access internet through VPN/ip firewall nat add action=masquerade chain=srcnat out-interface=ether1 \ src-address=192.168.100.0/24 comment="WireGuard road warrior NAT"Common Issue
Without the NAT masquerade rule, road warrior clients can connect but won’t have internet access through the VPN. This is the most common “connected but no internet” problem.
Client Configuration (for WireGuard app on iOS/Android/Windows/macOS):
Split tunnel - only VPN traffic goes through tunnel (recommended):
[Interface]Address = 192.168.100.2/24PrivateKey = <client_private_key>DNS = 192.168.100.1
[Peer]PublicKey = <server_public_key>Endpoint = server.example.com:13231AllowedIPs = 192.168.100.0/24, 192.168.1.0/24PersistentKeepalive = 25Full tunnel - ALL traffic goes through VPN (for privacy/security):
[Interface]Address = 192.168.100.2/24PrivateKey = <client_private_key>DNS = 192.168.100.1
[Peer]PublicKey = <server_public_key>Endpoint = server.example.com:13231AllowedIPs = 0.0.0.0/0, ::/0PersistentKeepalive = 25Generating client keys: Use the WireGuard app to generate keys, or on a MikroTik:
# Generate a key pair for the client/interface wireguardadd name=temp-keygenprint# Copy the private-key and public-key, then removeremove temp-keygenScenario 2: Client Behind NAT
Section titled “Scenario 2: Client Behind NAT”When your MikroTik is behind a NAT router (double NAT scenario):
# Create interface/interface wireguard add name=wg-client listen-port=13231
# Assign tunnel IP/ip address add address=10.255.255.2/30 interface=wg-client
# Configure peer with persistent-keepalive to maintain NAT mapping/interface wireguard peers add interface=wg-client \ public-key="<SERVER_PUBLIC_KEY>" \ allowed-address=10.255.255.1/32,192.168.0.0/24 \ endpoint-address=server.example.com \ endpoint-port=13231 \ persistent-keepalive=25s
# Add route to remote network/ip route add dst-address=192.168.0.0/24 gateway=wg-clientThe persistent-keepalive=25s sends a packet every 25 seconds to keep the NAT mapping alive.
Scenario 3: Server as Responder Only
Section titled “Scenario 3: Server as Responder Only”When the server has a static IP and should only respond to connections (never initiate):
/interface wireguard peers add interface=wg-server \ public-key="<CLIENT_PUBLIC_KEY>" \ allowed-address=192.168.100.2/32 \ responder=yesThe responder=yes setting prevents the server from attempting to initiate handshakes to clients with dynamic IPs.
Scenario 4: Import Configuration File (v7.19+)
Section titled “Scenario 4: Import Configuration File (v7.19+)”Import an existing WireGuard configuration:
/interface wireguard wg-import file=client.confOr import from a string:
/interface wireguard wg-import config-string="[Interface]Address=192.168.88.3/24ListenPort=13533PrivateKey=<key>[Peer]PublicKey=<key>Endpoint=199.168.100.10:51820AllowedIPs=0.0.0.0/0PersistentKeepalive=25"Verification
Section titled “Verification”Check 1: Verify Interface is Running
Section titled “Check 1: Verify Interface is Running”/interface wireguard printExpected Output:
Flags: X - disabled; R - running 0 R name="wg-tunnel" mtu=1420 listen-port=13231 private-key="..." public-key="..."The “R” flag indicates the interface is running.
Check 2: Verify Peer Handshake
Section titled “Check 2: Verify Peer Handshake”/interface wireguard peers printExpected Output:
0 interface=wg-tunnel public-key="..." endpoint-address=198.51.100.20 endpoint-port=13231 current-endpoint-address=198.51.100.20 current-endpoint-port=13231 allowed-address=10.255.255.2/32,192.168.2.0/24 last-handshake=1m23sThe last-handshake should show a recent time (under 3 minutes). If it shows “never”, the handshake hasn’t completed.
Check 3: Test Tunnel Connectivity
Section titled “Check 3: Test Tunnel Connectivity”/ping 10.255.255.2 count=3Expected: Successful replies with 0% packet loss.
Check 4: Verify Traffic Statistics
Section titled “Check 4: Verify Traffic Statistics”/interface wireguard peers print statsExpected: rx and tx bytes should increment when traffic flows.
Troubleshooting
Section titled “Troubleshooting”Problem: Handshake never completes (last-handshake shows “never”)
Section titled “Problem: Handshake never completes (last-handshake shows “never”)”Cause: Firewall blocking UDP traffic on port 13231.
Solution: Add firewall rule to accept WireGuard traffic:
/ip firewall filter add action=accept chain=input protocol=udp dst-port=13231 place-before=0Problem: Handshake works but no traffic passes between LANs
Section titled “Problem: Handshake works but no traffic passes between LANs”Cause: Missing forward firewall rules or incorrect allowed-address.
Solution:
- Add forward rules:
/ip firewall filter add action=accept chain=forward in-interface=wg-tunnel place-before=0/ip firewall filter add action=accept chain=forward out-interface=wg-tunnel place-before=0- Verify
allowed-addressincludes the remote LAN subnet.
Problem: Traffic routes to wrong peer
Section titled “Problem: Traffic routes to wrong peer”Cause: Overlapping subnets in allowed-address across multiple peers.
Solution: Each subnet can only appear in ONE peer’s allowed-address. Use /32 for individual clients:
# Wrong - overlappingadd allowed-address=10.0.0.0/24 public-key="peer1"add allowed-address=10.0.0.0/24 public-key="peer2"
# Correct - unique addressesadd allowed-address=10.0.0.1/32 public-key="peer1"add allowed-address=10.0.0.2/32 public-key="peer2"Problem: Tunnel works initially then drops after inactivity
Section titled “Problem: Tunnel works initially then drops after inactivity”Cause: NAT state timeout on upstream device.
Solution: Enable persistent-keepalive on the peer behind NAT:
/interface wireguard peers set [find name=my-peer] persistent-keepalive=25sProblem: Second peer has handshake but no traffic
Section titled “Problem: Second peer has handshake but no traffic”Cause: First peer has allowed-address=0.0.0.0/0 which captures all routing.
Solution: Only use 0.0.0.0/0 for single-peer “route all traffic” scenarios. Otherwise use specific subnets.
Problem: Configuration correct but handshake never completes (ISP issue)
Section titled “Problem: Configuration correct but handshake never completes (ISP issue)”Cause: Some ISPs/carriers filter UDP traffic on non-standard ports.
Solution:
- Try a different port number (e.g., 51820)
- Test from a different network to isolate the issue
Problem: MTU issues causing packet fragmentation
Section titled “Problem: MTU issues causing packet fragmentation”Cause: Default MTU of 1420 too large for some networks (especially with double NAT).
Solution: Reduce MTU on the WireGuard interface:
/interface wireguard set wg-tunnel mtu=1380Related Topics
Section titled “Related Topics”VPN Alternatives
Section titled “VPN Alternatives”- WireGuard Site-to-Site - native RouterOS WireGuard guide
- IPsec IKEv2 - enterprise VPN standard
- L2TP VPN Server - legacy VPN option
- ZeroTier - peer-to-peer VPN alternative
Network Configuration
Section titled “Network Configuration”- Static Routes - routing through VPN tunnel
- Firewall Basics - allow VPN traffic
- IP Addresses - tunnel IP configuration
Security
Section titled “Security”- IP Services - management access control
- Certificates - for other VPN protocols