Back to Blog
José Manuel Requena Plens

MikroTik WireGuard VPN: Complete Dual-Stack IPv4/IPv6 Configuration

Configure WireGuard VPN on MikroTik RouterOS with full IPv4/IPv6 dual-stack. Access your home network with native IPv6 from any connection.

Cover image for MikroTik WireGuard VPN: Complete Dual-Stack IPv4/IPv6 Configuration

WireGuard has revolutionized VPN technology with its simplicity, speed, and modern cryptography. Unlike traditional VPN protocols like OpenVPN or IPSec, WireGuard uses a minimal codebase (~4,000 lines vs 100,000+) and state-of-the-art cryptographic primitives as described in the WireGuard whitepaper, resulting in faster connections and lower latency.

This guide demonstrates how to configure a production-ready WireGuard VPN on MikroTik RouterOS with dual-stack IPv4/IPv6 support. The result? You can connect from any network—even those without IPv6—and enjoy full IPv6 connectivity through your home router.

What You'll Build
  • A WireGuard VPN server on MikroTik RouterOS with full IPv4 + IPv6 dual-stack support
  • IPv6 via ULA + NAT66: VPN clients get private ULA addresses translated to your ISP’s global prefix
  • Firewall rules: Input, forward, NAT/masquerade, MSS clamping, and RAW table optimizations
  • Multi-client support: Each device gets unique keys and a dedicated IP pair (IPv4 + IPv6)
  • Full tunnel or split tunnel: Route all traffic through VPN, or only home network traffic
  • Tested on RouterOS 7.x with RB5009, but applicable to any MikroTik router with WireGuard support

Why WireGuard on MikroTik?

VPN Protocol Comparison
FeatureWireGuardOpenVPNIPSec/IKEv2
Code complexity~4,000 lines~100,000 lines~400,000 lines
Connection time100ms3-10 seconds1-3 seconds
CPU overheadVery lowHigh (userspace)Medium
CryptographyChaCha20, Curve25519Configurable (varies)AES, RSA/ECDH
Roaming supportSeamlessReconnection neededLimited (MOBIKE)

Architecture overview

Our configuration creates a dual-stack VPN where connected clients receive both IPv4 and IPv6 addresses. Traffic from clients is NAT’d (masqueraded) to access the internet through your home connection. For detailed MikroTik WireGuard documentation, refer to the official wiki.

Home Network

VPN Clients

MikroTik Router

Internet

Encrypted Tunnel

Encrypted Tunnel

Encrypted Tunnel

Masquerade

Access

ISP Connection

IPv4 + IPv6

WireGuard Interface

wg_devices

Firewall + NAT

Client 1

192.168.100.2

fd00:...:100::2

Client 2

192.168.100.3

fd00:...:100::3

Client N

192.168.100.x

fd00:...:100::x

LAN Devices

192.168.0.0/24

WireGuard Dual-Stack Architecture

Network addressing scheme

IP Address Assignment
ComponentIPv4 AddressIPv6 Address
WireGuard Interface (Router)192.168.100.1/24fd00:1111:2222:100::1/64
VPN Client Range192.168.100.2-254fd00:1111:2222:100::2-ffff
Home LAN192.168.0.0/24ISP-assigned prefix

Prerequisites


Step 1: create the WireGuard interface

First, we create the WireGuard interface on the MikroTik router. The router will generate a keypair automatically.

ROUTEROSCreate WireGuard Interface
/interface wireguard add \
    name=wg_devices \
    mtu=1500 \
    listen-port=53537 \
    comment="VPN for Mobile Devices"

Retrieve the server’s public key

After creating the interface, retrieve the public key to configure clients:

/interface wireguard print
Flags: X - disabled; R - running 0 R name="wg_devices" mtu=1500 listen-port=53537 private-key="[REDACTED]" public-key="YourServerPublicKeyHere123456789ABCDEFGHIJ="

Save the public-key value—you’ll need it when configuring client devices.


Step 2: assign IP addresses to the interface

The WireGuard interface needs both IPv4 and IPv6 addresses to serve as the gateway for VPN clients.

ROUTEROSAssign IP Addresses
# IPv4 address for WireGuard interface
/ip address add \
    address=192.168.100.1/24 \
    interface=wg_devices \
    network=192.168.100.0 \
    comment="VPN Devices Network"

# IPv6 ULA address for WireGuard interface
/ipv6 address add \
    address=fd00:1111:2222:100::1/64 \
    interface=wg_devices \
    advertise=no \
    comment="VPN Devices IPv6 ULA"

Step 3: create IPv6 pool (optional)

If you want to manage IPv6 address allocation centrally, create a pool:

ROUTEROSCreate IPv6 Pool
/ipv6 pool add \
    name=wg_devices_pool_global \
    prefix=fd00:1111:2222:100::/64 \
    prefix-length=64 \
    comment="WireGuard Devices Global IPv6 Pool"

Step 4: add the interface to interface lists

MikroTik uses interface lists for firewall rules. Adding WireGuard to the appropriate lists ensures proper traffic handling.

ROUTEROSAdd to Interface Lists
# Add to VPN list for VPN-specific rules
/interface list member add \
    interface=wg_devices \
    list=VPN \
    comment="VPN Devices"

# Add to LAN list to allow access to local resources
/interface list member add \
    interface=wg_devices \
    list=LAN \
    comment="VPN Devices - LAN Access"

Step 5: configure firewall rules

The firewall configuration is critical for security and connectivity. We need rules for:

  1. Accepting WireGuard traffic on the listening port
  2. Allowing VPN clients to access the internet
  3. Allowing VPN clients to access local networks
  4. NAT/Masquerade for outbound traffic

Input chain: accept WireGuard connections

ROUTEROSFirewall Input Rules
# Allow WireGuard UDP port (IPv4)
/ip firewall filter add \
    chain=input \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Accept incoming connections"

# Allow WireGuard UDP port (IPv6)
/ipv6 firewall filter add \
    chain=input \
    action=accept \
    protocol=udp \
    port=53537 \
    comment="Allow WireGuard"

Forward chain: allow VPN traffic

ROUTEROSFirewall Forward Rules - IPv4
# FastTrack for established WireGuard connections (performance)
/ip firewall filter add \
    chain=forward \
    action=fasttrack-connection \
    connection-state=established,related \
    src-address-list=WireGuard \
    comment="FastTrack for WireGuard Networks"

# Allow VPN clients to internet
/ip firewall filter add \
    chain=forward \
    action=accept \
    src-address=192.168.100.0/24 \
    out-interface-list=WAN \
    comment="Allow WireGuard Devices to Internet"

# Allow return traffic from internet to VPN
/ip firewall filter add \
    chain=forward \
    action=accept \
    connection-state=established,related \
    dst-address=192.168.100.0/24 \
    in-interface-list=WAN \
    comment="Allow Internet to WireGuard Devices (replies)"

# Allow VPN clients to Home LAN
/ip firewall filter add \
    chain=forward \
    action=accept \
    src-address=192.168.100.0/24 \
    dst-address=192.168.0.0/24 \
    comment="Allow WireGuard Devices to Home LAN"
ROUTEROSFirewall Forward Rules - IPv6
# Allow VPN clients all outbound IPv6 traffic
/ipv6 firewall filter add \
    chain=forward \
    action=accept \
    in-interface=wg_devices \
    comment="WireGuard Devices: Allow all outbound"

# Allow return IPv6 traffic to VPN clients
/ipv6 firewall filter add \
    chain=forward \
    action=accept \
    connection-state=established,related \
    out-interface=wg_devices \
    comment="WireGuard Devices: Allow replies"

Create address list for WireGuard networks

ROUTEROSAddress Lists
/ip firewall address-list add \
    list=WireGuard \
    address=192.168.100.0/24 \
    comment="WireGuard Devices Network"

Step 6: configure NAT/Masquerade

For VPN clients to access the internet, their private addresses must be translated (NAT) to your public IP.

ROUTEROSNAT Configuration
# IPv4 Masquerade for WireGuard
/ip firewall nat add \
    chain=srcnat \
    action=masquerade \
    src-address=192.168.100.0/24 \
    out-interface-list=WAN \
    comment="WireGuard Devices - Internet Access"

# IPv6 NAT66 for WireGuard (ULA to Global)
/ipv6 firewall nat add \
    chain=srcnat \
    action=masquerade \
    src-address=fd00:1111:2222:100::/64 \
    out-interface-list=WAN \
    comment="WireGuard Devices - IPv6 Internet Access"

Step 7: configure MSS clamping

TCP Maximum Segment Size (MSS) clamping prevents fragmentation issues with VPN tunnels. The WireGuard overhead reduces the effective MTU, so we must adjust TCP MSS accordingly.

ROUTEROSMSS Clamping
/ip firewall mangle add \
    chain=forward \
    action=change-mss \
    protocol=tcp \
    tcp-flags=syn \
    tcp-mss=1349-65535 \
    new-mss=1420 \
    in-interface=wg_devices \
    comment="WireGuard MSS clamping - Devices"

Step 8: configure RAW table for performance

Skip flood protection for WireGuard traffic to ensure smooth connectivity:

ROUTEROSRAW Table Rules
# IPv4: Skip flood protection for WireGuard
/ip firewall raw add \
    chain=prerouting \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Skip flood protection"

# IPv6: Skip flood protection for WireGuard
/ipv6 firewall raw add \
    chain=prerouting \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Skip flood protection"

Step 9: add WireGuard peers (clients)

Now we add client devices. Each client needs:

  • Unique IP addresses: A dedicated IPv4 and IPv6 address within the WireGuard subnet
  • Keypair: Private and public keys for authentication
  • Preshared key: Optional but recommended additional encryption layer

Create a peer

Choose how to generate the cryptographic keys. The recommended approach lets RouterOS generate everything automatically, but you can also pre-generate keys on the client device.

Since RouterOS 7.x, the router can generate all cryptographic keys automatically. This is the simplest approach — the router creates the private key, computes the public key, and generates the preshared key in a single command.

Create the peer with auto-generated keys

ROUTEROSAdd Peer with Auto-Generated Keys
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_client1 \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \
    persistent-keepalive=25s \
    comment="Client 1 - Mobile"

Set client configuration properties (optional)

These properties define the client-side configuration and enable the QR code feature in WinBox/WebFig:

ROUTEROSSet Client Configuration Properties
/interface wireguard peers set wg_client1 \
    client-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \
    client-dns=192.168.0.1,fd00:1111:2222:100::1 \
    client-endpoint=your-domain.com:53537 \
    client-allowed-address=0.0.0.0/0,::/0 \
    client-keepalive=25

Retrieve keys for manual client configuration

If you need to configure the client manually instead of scanning the QR code, retrieve the generated keys from the router:

ROUTEROSRetrieve Generated Keys
# Client's private key → goes into client's [Interface] section
:put [/interface wireguard peers get [find name=wg_client1] private-key]

# Preshared key → goes into client's [Peer] section
:put [/interface wireguard peers get [find name=wg_client1] preshared-key]

# Server's public key → goes into client's [Peer] section
:put [/interface wireguard get [find name=wg_devices] public-key]

Use these values to fill in the client configuration file in Step 10.

Generate keys on the client device first, then add the peer on the router using the client’s public key.

Generate keys on the client

# Generate private key wg genkey > privatekey # Generate public key from private key cat privatekey | wg pubkey > publickey # Generate preshared key (optional but recommended) wg genpsk > presharedkey # Display keys cat privatekey publickey presharedkey

Add peer on MikroTik

Use the client’s public key (not the private key) and the preshared key:

ROUTEROSAdd WireGuard Peer (Linux/macOS)
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_client1 \
    public-key="<CLIENT_PUBLIC_KEY>" \
    preshared-key="<PRESHARED_KEY>" \
    allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \
    persistent-keepalive=25s \
    comment="Client 1 - Mobile"

The WireGuard Windows app generates keys automatically when creating a new tunnel.

  1. Download and install WireGuard for Windows
  2. Open the app and click Add TunnelAdd empty tunnel
  3. The app generates a keypair — copy the Public Key shown at the top
  4. Generate a preshared key from the command line:
# If WireGuard is installed, wg.exe is available in PATH wg genpsk

Add peer on MikroTik

ROUTEROSAdd WireGuard Peer (Windows)
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_client1 \
    public-key="<CLIENT_PUBLIC_KEY>" \
    preshared-key="<PRESHARED_KEY>" \
    allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \
    persistent-keepalive=25s \
    comment="Client 1 - Mobile"
Peer Configuration Parameters
ParameterValuePurpose
private-keyauto / noneAuto-generates keypair on the router (recommended method)
public-keyClient’s public keyIdentifies and authenticates the client
preshared-keyauto / shared secretAdditional symmetric encryption layer (post-quantum security)
allowed-addressClient IP(s)IPs the client can use; also acts as routing table
persistent-keepalive25 secondsMaintains NAT mappings, enables incoming connections

Example: multiple peers

Each peer must have a unique keypair and unique IP addresses. Never reuse keys between devices.

ROUTEROSMultiple Peer Configuration (RouterOS auto-keys)
# Client 1 - Mobile Device (e.g., iPhone)
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_phone \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \
    persistent-keepalive=25s \
    comment="Phone - Mobile VPN"

# Client 2 - Laptop (e.g., MacBook)
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_laptop \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.3/32,fd00:1111:2222:100::3/128 \
    persistent-keepalive=25s \
    comment="Laptop - Mobile VPN"

# Client 3 - Remote Site (Site-to-Site VPN)
/interface wireguard peers add \
    interface=wg_devices \
    name=wg_remote_site \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.10/32,fd00:1111:2222:100::a/128 \
    persistent-keepalive=25s \
    comment="Remote Site - Site-to-Site"

Step 10: client configuration

Now configure the client device. If you used the RouterOS auto-keys method and set the client properties in Step 9, you can simply scan the QR code from WinBox/WebFig — no manual configuration needed.

For manual setup, the configuration file format is the same across all platforms, but the setup method varies.

Download the WireGuard app from the App Store or Google Play. You can either:

  • Import a .conf file or scan a QR code
  • Create manually in the app
wg_home.conf (iOS/​Android)
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 192.168.100.2/32, fd00:1111:2222:100::2/128
DNS = 192.168.0.1, fd00:1111:2222:100::1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY>
Endpoint = your-domain.com:53537
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Install WireGuard:

# macOS (Homebrew) brew install wireguard-tools # Ubuntu/Debian sudo apt install wireguard # Fedora sudo dnf install wireguard-tools

Create the configuration file:

/​etc/​wireguard/​wg_home.conf
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 192.168.100.2/32, fd00:1111:2222:100::2/128
DNS = 192.168.0.1, fd00:1111:2222:100::1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY>
Endpoint = your-domain.com:53537
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Activate the tunnel:

# Start the tunnel sudo wg-quick up wg_home # Check status sudo wg show # Stop the tunnel sudo wg-quick down wg_home # Enable on boot (Linux only) sudo systemctl enable wg-quick@wg_home
  1. Download and install WireGuard for Windows
  2. Open the app and click Add TunnelImport tunnel(s) from file (if you have a .conf file) or Add empty tunnel to paste the configuration
  3. If creating from scratch, replace the configuration with:
wg_home.conf (Windows)
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 192.168.100.2/32, fd00:1111:2222:100::2/128
DNS = 192.168.0.1, fd00:1111:2222:100::1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <PRESHARED_KEY>
Endpoint = your-domain.com:53537
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
  1. Click Save then Activate

Configuration options explained

Client Configuration Parameters
ParameterDescription
AddressThe IP addresses assigned to this client (both IPv4 and IPv6)
DNSDNS servers to use. Can be your router or any DNS server accessible via VPN
EndpointYour router’s public IP or domain name with the WireGuard port
AllowedIPs0.0.0.0/0, ::/0 routes ALL traffic through VPN. Use specific subnets for split-tunnel

Split tunnel vs full tunnel

Split Tunnel

Home Network

Internet

Client

Destination?

VPN Tunnel

Home Router

Direct Connection

Full Tunnel

Client

VPN Tunnel

Home Router

Internet

Traffic Routing Modes

Full tunnel — all traffic goes through VPN:

  • Hides your location from all websites
  • Higher latency for general browsing
  • Full IPv6 access through home connection
INIFull Tunnel Example
# Route ALL traffic through VPN
AllowedIPs = 0.0.0.0/0, ::/0

Split tunnel — only traffic to specified networks uses VPN:

  • Better performance for general internet use
  • Home network access without routing everything
INISplit Tunnel Example
# Only route home network traffic through VPN
AllowedIPs = 192.168.0.0/24, 192.168.100.0/24, fd00:1111:2222::/48

Step 11: verify the connection

After configuring both sides, test the connection.

On the client

# macOS/Linux sudo wg show # Or use the WireGuard app on iOS/Android
interface: wg_home public key: ClientPublicKeyHere123456789ABCDEFGHIJKLMNO= private key: (hidden) listening port: 51820 peer: YourServerPublicKeyHere123456789ABCDEFGHIJ= preshared key: (hidden) endpoint: 203.0.113.50:53537 allowed ips: 0.0.0.0/0, ::/0 latest handshake: 5 seconds ago transfer: 1.24 MiB received, 456.78 KiB sent

On the MikroTik router

/interface wireguard peers print
Flags: X - disabled 0 name="wg_client1" interface=wg_devices public-key="<CLIENT_PUBLIC_KEY>" preshared-key="(present)" allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 current-endpoint-address=198.51.100.75 current-endpoint-port=51820 last-handshake=5s rx=1302528 tx=467352

Test IPv6 connectivity

# Check your IPv6 address curl -6 ifconfig.co # Test IPv6 connectivity ping6 google.com # Verify route traceroute6 google.com

Complete configuration summary

Here’s the complete RouterOS configuration for reference. Values marked with # ← CUSTOMIZE must be replaced with your own.

wireguard-complete.rsc
# ═══════════════════════════════════════════════════════════════════════════════
# WIREGUARD VPN - COMPLETE DUAL-STACK CONFIGURATION
# ═══════════════════════════════════════════════════════════════════════════════
# MikroTik RouterOS 7.x
# IPv4 + IPv6 dual-stack with full internet access
# ═══════════════════════════════════════════════════════════════════════════════

# ───────────────────────────────────────────────────────────────────────────────
# INTERFACE CONFIGURATION
# ───────────────────────────────────────────────────────────────────────────────

/interface wireguard add \
    name=wg_devices \
    mtu=1500 \
    listen-port=53537 \
    comment="VPN for Mobile Devices"                              # ← CUSTOMIZE port

# ───────────────────────────────────────────────────────────────────────────────
# IP ADDRESS ASSIGNMENT
# ───────────────────────────────────────────────────────────────────────────────

/ip address add \
    address=192.168.100.1/24 \
    interface=wg_devices \
    network=192.168.100.0 \
    comment="VPN Devices Network"                                 # ← CUSTOMIZE subnet

/ipv6 address add \
    address=fd00:1111:2222:100::1/64 \
    interface=wg_devices \
    advertise=no \
    comment="VPN Devices IPv6 ULA"                                # ← CUSTOMIZE ULA prefix

# ───────────────────────────────────────────────────────────────────────────────
# IPv6 POOL (Optional)
# ───────────────────────────────────────────────────────────────────────────────

/ipv6 pool add \
    name=wg_devices_pool_global \
    prefix=fd00:1111:2222:100::/64 \
    prefix-length=64 \
    comment="WireGuard Devices Global IPv6 Pool"

# ───────────────────────────────────────────────────────────────────────────────
# INTERFACE LISTS (create 'VPN' list if it doesn't exist)
# ───────────────────────────────────────────────────────────────────────────────

/interface list add name=VPN comment="VPN Interfaces" # only if list doesn't exist yet
/interface list member add interface=wg_devices list=VPN comment="VPN Devices"
/interface list member add interface=wg_devices list=LAN comment="VPN Devices - LAN Access"

# ───────────────────────────────────────────────────────────────────────────────
# ADDRESS LISTS
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall address-list add \
    list=WireGuard \
    address=192.168.100.0/24 \
    comment="WireGuard Devices Network"

# ───────────────────────────────────────────────────────────────────────────────
# FIREWALL - INPUT CHAIN
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall filter add \
    chain=input \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Accept incoming connections"              # ← CUSTOMIZE port

/ipv6 firewall filter add \
    chain=input \
    action=accept \
    protocol=udp \
    port=53537 \
    comment="Allow WireGuard"                                     # ← CUSTOMIZE port

# ───────────────────────────────────────────────────────────────────────────────
# FIREWALL - FORWARD CHAIN (IPv4)
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall filter add \
    chain=forward \
    action=fasttrack-connection \
    connection-state=established,related \
    src-address-list=WireGuard \
    comment="FastTrack for WireGuard Networks"

/ip firewall filter add \
    chain=forward \
    action=accept \
    src-address=192.168.100.0/24 \
    out-interface-list=WAN \
    comment="Allow WireGuard Devices to Internet"                  # ← CUSTOMIZE subnet

/ip firewall filter add \
    chain=forward \
    action=accept \
    connection-state=established,related \
    dst-address=192.168.100.0/24 \
    in-interface-list=WAN \
    comment="Allow Internet to WireGuard Devices (replies)"        # ← CUSTOMIZE subnet

/ip firewall filter add \
    chain=forward \
    action=accept \
    src-address=192.168.100.0/24 \
    dst-address=192.168.0.0/24 \
    comment="Allow WireGuard Devices to Home LAN"                  # ← CUSTOMIZE subnets

# ───────────────────────────────────────────────────────────────────────────────
# FIREWALL - FORWARD CHAIN (IPv6)
# ───────────────────────────────────────────────────────────────────────────────

/ipv6 firewall filter add \
    chain=forward \
    action=accept \
    in-interface=wg_devices \
    comment="WireGuard Devices: Allow all outbound"

/ipv6 firewall filter add \
    chain=forward \
    action=accept \
    connection-state=established,related \
    out-interface=wg_devices \
    comment="WireGuard Devices: Allow replies"

# ───────────────────────────────────────────────────────────────────────────────
# NAT / MASQUERADE
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall nat add \
    chain=srcnat \
    action=masquerade \
    src-address=192.168.100.0/24 \
    out-interface-list=WAN \
    comment="WireGuard Devices - Internet Access"                  # ← CUSTOMIZE subnet

/ipv6 firewall nat add \
    chain=srcnat \
    action=masquerade \
    src-address=fd00:1111:2222:100::/64 \
    out-interface-list=WAN \
    comment="WireGuard Devices - IPv6 Internet Access"             # ← CUSTOMIZE ULA prefix

# ───────────────────────────────────────────────────────────────────────────────
# MANGLE - MSS CLAMPING
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall mangle add \
    chain=forward \
    action=change-mss \
    protocol=tcp \
    tcp-flags=syn \
    tcp-mss=1349-65535 \
    new-mss=1420 \
    in-interface=wg_devices \
    comment="WireGuard MSS clamping - Devices"

# ───────────────────────────────────────────────────────────────────────────────
# RAW TABLE - SKIP FLOOD PROTECTION
# ───────────────────────────────────────────────────────────────────────────────

/ip firewall raw add \
    chain=prerouting \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Skip flood protection"

/ipv6 firewall raw add \
    chain=prerouting \
    action=accept \
    protocol=udp \
    dst-port=53537 \
    comment="WireGuard - Skip flood protection"

# ───────────────────────────────────────────────────────────────────────────────
# PEERS — Using auto-generated keys (recommended)
# Retrieve keys with: :put [/interface wireguard peers get [find name=X] private-key]
# ───────────────────────────────────────────────────────────────────────────────

/interface wireguard peers add \
    interface=wg_devices \
    name=wg_phone \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.2/32,fd00:1111:2222:100::2/128 \  # ← CUSTOMIZE IPs
    persistent-keepalive=25s \
    comment="Phone - Mobile VPN"                                   # ← CUSTOMIZE

/interface wireguard peers add \
    interface=wg_devices \
    name=wg_laptop \
    private-key=auto \
    preshared-key=auto \
    allowed-address=192.168.100.3/32,fd00:1111:2222:100::3/128 \  # ← CUSTOMIZE IPs
    persistent-keepalive=25s \
    comment="Laptop - Mobile VPN"                                  # ← CUSTOMIZE

Troubleshooting

Connection won’t establish

The most common issue. If last-handshake never appears on either side, the initial handshake isn’t completing.

Check the WireGuard interface is running — a disabled or stopped interface won’t accept connections:

ROUTEROSVerify Interface Status
/interface wireguard print
# Look for the "R" (running) flag. If you see "X" (disabled), enable it:
/interface wireguard enable wg_devices

Verify the UDP port is reachable — the firewall must accept incoming WireGuard packets. Check the input chain has an accept rule for your port:

ROUTEROSCheck Firewall Input Rules
# List input rules that match your WireGuard port
/ip firewall filter print where chain=input and dst-port~"53537"
# If empty, add the rule:
/ip firewall filter add chain=input action=accept protocol=udp dst-port=53537 \
    comment="WireGuard - Accept incoming connections" place-before=0

Verify the peer’s public key matches — the most subtle error. The server must have the client’s public key, and the client must have the server’s public key. Any mismatch silently drops all packets:

ROUTEROSVerify Keys
# Show the server's public key (this goes into the client's [Peer] section)
:put [/interface wireguard get wg_devices public-key]

# Show the client's public key stored on this peer
:put [/interface wireguard peers get [find name=wg_client1] public-key]

Check if the peer shows a handshake — if last-handshake shows a time, the tunnel is established even if traffic isn’t flowing:

ROUTEROSCheck Peer Handshake
/interface wireguard peers print detail where interface=wg_devices
# Look for: last-handshake=Xs (seconds since last handshake)
# If empty or very old, the tunnel is not established

Can connect but no internet access

The tunnel is up (handshake succeeds) but the client can’t browse the web or reach external hosts.

Check NAT/masquerade rules — without masquerade, the VPN client’s private IP reaches the internet but return packets have nowhere to go:

ROUTEROSVerify NAT Rules
# Check IPv4 masquerade
/ip firewall nat print where chain=srcnat and src-address~"192.168.100"
# Should show: action=masquerade out-interface-list=WAN

# Check IPv6 masquerade
/ipv6 firewall nat print where chain=srcnat and src-address~"fd00"

Check forward chain rules — even with NAT, the firewall’s forward chain must allow VPN traffic toward the WAN:

ROUTEROSVerify Forward Rules
/ip firewall filter print where chain=forward and src-address~"192.168.100"
# You need at least:
#   accept src=192.168.100.0/24 out-interface-list=WAN
#   accept connection-state=established,related dst=192.168.100.0/24 in-interface-list=WAN

Test DNS resolution — a common cause of “no internet” is that DNS queries fail. From the client, try reaching an IP directly to isolate the issue:

# Test direct IP connectivity (bypasses DNS) ping 1.1.1.1 # If ping works but browsing doesn't, DNS is the problem. # Try a different DNS in the client config: # DNS = 1.1.1.1, 2606:4700:4700::1111

IPv6 not working

IPv4 works through the tunnel but IPv6 traffic doesn’t flow.

Verify the IPv6 address is assigned to the WireGuard interface:

ROUTEROSCheck IPv6 Address
/ipv6 address print where interface=wg_devices
# Should show your ULA address, e.g., fd00:1111:2222:100::1/64

Check IPv6 NAT66 rule — unlike IPv4, the IPv6 masquerade is often forgotten:

ROUTEROSVerify IPv6 NAT66
/ipv6 firewall nat print where chain=srcnat
# Must include: action=masquerade src-address=fd00:1111:2222:100::/64 out-interface-list=WAN

Check IPv6 forward rules — the IPv6 firewall is independent from IPv4. You need explicit forward rules:

ROUTEROSVerify IPv6 Forward Rules
/ipv6 firewall filter print where chain=forward and interface~"wg_devices"
# Need at minimum:
#   accept in-interface=wg_devices (outbound)
#   accept connection-state=established,related out-interface=wg_devices (return)

Test from the client — run these commands while connected to the VPN:

# Verify your IPv6 address is from the ULA range ip -6 addr show wg_home # Test connectivity to a known IPv6 address (Google DNS) ping6 2001:4860:4860::8888 # If the ping works, test DNS resolution over IPv6 curl -6 ifconfig.co

Slow performance

WireGuard is extremely efficient, but several factors can limit throughput on MikroTik devices.

Enable FastTrack — this is the single largest performance improvement. FastTrack bypasses most firewall processing for established connections:

ROUTEROSCheck FastTrack
# Verify FastTrack rule exists and has packet counters increasing
/ip firewall filter print stats where action=fasttrack-connection and comment~"WireGuard"
# If missing:
/ip firewall filter add chain=forward action=fasttrack-connection \
    connection-state=established,related src-address-list=WireGuard \
    comment="FastTrack for WireGuard Networks"

Check MSS clamping — symptoms of missing MSS clamping include: pages partially loading, HTTPS sites timing out, large file downloads failing while small requests work fine:

ROUTEROSVerify MSS Clamping
/ip firewall mangle print where action=change-mss and in-interface=wg_devices
# Should show: new-mss=1420 tcp-flags=syn tcp-mss=1349-65535

Check MTU — if you experience packet loss or stalls, try reducing the WireGuard interface MTU:

ROUTEROSAdjust MTU
# Check current MTU
/interface wireguard print proplist=name,mtu

# If set to 1500 and experiencing issues, try the default 1420:
/interface wireguard set wg_devices mtu=1420
# Then update MSS clamping to match:
# new-mss = MTU - 40 (IPv6 header) - 20 (TCP header) = 1360

Monitor CPU load — WireGuard encryption is not hardware-offloaded on MikroTik. High CPU usage limits throughput:

ROUTEROSMonitor CPU
/system resource print
# Look for cpu-load percentage. On RB5009 with a single client,
# WireGuard typically uses <5% CPU at 100+ Mbps.

Useful diagnostic commands

A quick-reference for common RouterOS diagnostic commands related to WireGuard:

ROUTEROSWireGuard Diagnostic Commands
# Show all peers with connection status and traffic stats
/interface wireguard peers print detail

# Show only connected peers (those with a recent handshake)
/interface wireguard peers print where last-handshake<1m

# Monitor WireGuard traffic in real-time
/interface monitor-traffic wg_devices once

# Check interface packet counters
/interface print stats where name=wg_devices

# View firewall rule hit counters (useful to find rules that never match)
/ip firewall filter print stats where comment~"WireGuard"

# Check if the port is listening
/tool netwatch print where host=127.0.0.1 and port=53537

Security best practices

  • Always use preshared keys for post-quantum security
  • Use unique keypairs for each device (never share private keys)
  • Keep RouterOS updated for security patches
  • Use a non-standard port to reduce scan exposure
  • Consider automatic IP whitelisting for connected peers
  • Monitor connection logs for unauthorized access attempts

Conclusion

You now have a fully functional WireGuard VPN with dual-stack IPv4/IPv6 support on your MikroTik router. This configuration provides:

  • Secure remote access to your home network from anywhere
  • Full IPv6 connectivity even from IPv4-only networks
  • Fast, modern encryption with minimal overhead
  • Seamless roaming between Wi-Fi and cellular networks

WireGuard’s simplicity makes it easy to maintain, and MikroTik’s implementation is robust enough for production use. Whether you’re accessing your NAS, home automation, or simply want to browse securely on public Wi-Fi, this setup has you covered.