MikroTik WireGuard: native or container VPN
Two ways to run a VPN client on RouterOS 7, the built-in WireGuard interface or a container, with commands run on a virtual router and CPU cost on real boards.
Key takeaways
- Two routes exist on RouterOS 7: the built-in WireGuard interface, which needs no extra package, and a container client, which needs the container package, a device-mode change and a RouterOS 7.21 or later floor.
- AllowedIPs 0.0.0.0/0 plus a default route through the interface sent all 5 of the router's own test pings into the tunnel in our lab run, and none out of the WAN link.
- 122 Mbit/s against 66.8 Mbit/s: that is what our container core and RouterOS's own kernel tunnel moved on two physical MikroTik routers on 2026-09-01, at 0.53 against 1.10 percent CPU per Mbit/s; our core lost on round-trip time, 1.22 ms against 0.92 ms.
- The container route, out of the box, tunnels only the container's own traffic, and nothing from the LAN uses it until you paste ForestVPN's routing script; the native route does nothing you did not write.
On this page (10)
- Can a MikroTik router run WireGuard as a VPN client?
- Which RouterOS version do you need for WireGuard and for containers?
- What do RouterOS's WireGuard interface and a container client each need?
- How do you set up the native WireGuard interface on RouterOS 7?
- What does AllowedIPs 0.0.0.0/0 do to the router's own traffic?
- How do you run the container client on RouterOS?
- Does a WireGuard container use less CPU than RouterOS's own WireGuard?
- What does the MTU do to a MikroTik tunnel?
- Does a MikroTik kill switch work?
- Should you use RouterOS's WireGuard interface or a container VPN client?
A MikroTik can be a VPN client two ways: RouterOS 7's built-in WireGuard interface, or a container, which is how ForestVPN's router client ships. We ran both on one RouterOS 7.24.1 Cloud Hosted Router (CHR), a virtual router, and add CPU numbers from real boards, including the round we lost.
Can a MikroTik router run WireGuard as a VPN client?
Yes: RouterOS 7 has a WireGuard interface, and a peer on it makes the router a client of any server you hold a configuration for. MikroTik's WireGuard page lists the interface's properties, lists 13231 as the listen-port default and 1420 as the MTU, and shows import and export of configurations. A third-party guide, MikroTik Masters, published on 2025-01-30, states RouterOS 7.1 or later as its requirement.
That native interface speaks the protocol and nothing else. It does not register you anywhere, pick a server or build a firewall.
You bring a configuration and write the rest yourself:
- the router's own private key, the peer's public key and an endpoint
- the addresses, routes and NAT
In a .conf file the peer's permitted addresses are called AllowedIPs. RouterOS calls the same setting allowed-address, and this article uses both names.
The second route is a container. RouterOS can run Linux container images once the RouterOS container package is installed, and our client, the image suquant/fvpn (at the pinned tag on our download page), runs that way.
It talks to RouterOS over a veth, a virtual Ethernet link between the router and the container, registers the router as its own device, holds its own keys and prints a pairing code.
Its sibling image suquant/fvpnq is raw tunnelling from a config file and is what an exit node runs. It is not the client and not what this article means.
We do not hand out a WireGuard .conf file for the native route, so you need a server you already hold a configuration for.
Which RouterOS version do you need for WireGuard and for containers?
Both routes need RouterOS 7, and the container route adds a package and a higher floor.
Native route
The only floor we can cite is MikroTik Masters' RouterOS 7.1 or later, from a post dated 2025-01-30. Read MikroTik's own page for the release you run, because that guide is older than this one.
Container route
MikroTik's container page says the package is compatible with arm, arm64 and x86 architectures. It adds that remote-image pulls need a lot of free space in main memory.
Our client then asks for two things, according to our MikroTik download page:
- RouterOS 7.21 or later, with the container package. Older versions reject the install block.
- Device-mode, a RouterOS switch that keeps risky features off until someone with physical access turns them on, set to allow containers.
What is verified
MikroTik router setup records one hardware verification: a cAP ax (arm64, RouterOS 7.24.1) that registered, printed a pairing code, verified the signed server list and connected. That is the entire verified claim, and we will not stretch it. The choose-traffic and kill-switch recipes are separate pages with their own notes.
Some boards need a variant. The flash folder recipe describes 16 MB boards, such as the hAP ac², that keep only their flash folder across a reboot; our download page says "The install block handles it", and the recipe does so by pulling the image again at every boot. The recipe's own note reads: "Not yet verified on hardware."
What do RouterOS's WireGuard interface and a container client each need?
The native route needs nothing beyond RouterOS 7 and a config; the container route needs a package, a device-mode change and some RouterOS rules of your own before the LAN uses it. Here are the two side by side, with the sources named in the cells.
| Item | Native WireGuard interface | Container client (suquant/fvpn) |
|---|---|---|
| Needs | RouterOS 7 | RouterOS 7.21 or later, container package, device-mode container=yes |
| Where the tunnel runs | RouterOS's own kernel implementation | Userspace, inside the container |
| Keys and account | You hold the config from your server | The container makes its own machine key and prints a pairing code |
| Storage | Nothing extra | Our plain install needs no disk and keeps root and state on built-in storage; MikroTik's page recommends an attached disk for container volumes |
| Which traffic | Whatever your routes say | Only the container's own traffic, until you paste the routing script, which adds mangle rules (RouterOS's packet-marking firewall chain) and a routing table |
| Kill switch | None shipped, you write it | Part of the routing script, in every mode |
| Physical access | Not needed | Needed once, to confirm device-mode |
| Speed pair we hold | RouterOS's kernel tunnel: 66.8 Mbit/s on two MikroTik routers, 2026-09-01 | Our core in a RouterOS container, started by hand: 122 Mbit/s on the same two routers, same day |
Those two speeds are not one test run twice. The throughput post explains why the two arms needed different traffic generators, and the section on CPU below carries the caveats.
How do you set up the native WireGuard interface on RouterOS 7?
You create the interface, give it an address and add one peer; the route to the tunnel's subnet comes from the address you gave the interface. That is three commands, in that order, plus a firewall rule on a listening side that filters its input. Below is what we ran on the lab's client router, followed by its own printout.
How this was tested
- Product
- MikroTik RouterOS Cloud Hosted Router (virtual)
- Version
- 7.24.1 stable, build 2026-08-21, licence level free
- System
- arm64 under QEMU 11.1.2 software emulation, 2 vCPU
- Checked
- Runs
- 1
Not tested
A virtual router, not hardware. The peer was a second RouterOS virtual router on a private link in documentation address ranges. Keys, addresses and endpoints are throwaway lab values, and public keys are redacted in the saved output. No ForestVPN account or production identity was used. Not tested: any throughput, CPU or round-trip figure on the virtual router, the container's LAN path, mangle rules, the kill switch, RouterOS releases older than 7.24.1, small-flash boards, and any MTU other than the default 1420.
/interface/wireguard/add name=wg-lab
/ip/address/add address=10.99.0.2/24 interface=wg-lab
/interface/wireguard/peers/add interface=wg-lab \
public-key="<peer public key>" \
endpoint-address=192.0.2.2 endpoint-port=51820 \
allowed-address=10.99.0.0/24 persistent-keepalive=5s comment=lab-peer
After the peer was in, the router showed this. Note the handshake counter and the connected route (flag DAc) that appeared for the tunnel's subnet:
> /interface/wireguard/print
0 R name="wg-lab" mtu=1420 listen-port=56422
> /interface/wireguard/peers/print detail
0 ;;; lab-peer
interface=wg-lab name="peer1"
endpoint-address=192.0.2.2 endpoint-port=51820
allowed-address=10.99.0.0/24 persistent-keepalive=5s
rx=92 tx=212 last-handshake=9s
> /ip/route/print
DAc 10.99.0.0/24 wg-lab main
> /ping 10.99.0.1 count=5
sent=5 received=5 packet-loss=0% min-rtt=2ms1us avg-rtt=3ms397us
The five pings crossed the tunnel with no loss. The R flag means the interface is running. The handshake is the proof that matters: a non-empty last-handshake means the peer answered, whatever a ping says later.
Routes and ports
That DAc route is the connected route RouterOS creates from the interface address, 10.99.0.2/24. It does not come from the peer or its allowed-address: RouterOS creates no routes from that field, which is why the next section has to add a default route by hand. A peer subnet outside the interface's own subnet needs its own /ip/route entry.
MikroTik's table says 13231 is the default listen port. Our 7.24.1 interface, created without a listen-port, came up on 56422. Set listen-port explicitly whenever a firewall rule or a peer's configuration depends on it.
On the peer side
- On a router whose input chain drops unsolicited traffic, the listening side needs an accept rule for UDP on its listen port, placed above the drop. MikroTik's page adds the same kind of rule. Our peer had no such drop rule, so this run did not show it being needed.
- Set
persistent-keepaliveon a router that sits behind NAT, so the mapping does not expire when the link is quiet.
What the guides stop at
Proton's MikroTik page continues past the peer with four steps:
- A masquerade rule on the interface.
- Two routes that split the address space in half (0.0.0.0/1 and 128.0.0.0/1).
- A DNS server change.
- A host route for the endpoint through the normal gateway.
Those steps turn "the ping works" into "the LAN uses it". We did not run Proton's service, and this describes what its page says, nothing about how it performs.
What does AllowedIPs 0.0.0.0/0 do to the router's own traffic?
It lets every destination through the peer, and once you point a default route at the interface the router's own traffic goes with the rest. Here "the router's own traffic" means RouterOS's own pings, DNS lookups and update checks, which leave by whatever route says so. On the native route the router is no bystander.
We tested it on the same virtual router. It had no other default route before the change, so the run shows where the router's traffic goes once the tunnel holds the default, not a contest with an existing WAN default route.
Before the change the router had no route to the lab host and three pings failed with "no route". Then we widened the peer's allowed address to 0.0.0.0/0 and added a default route through the interface:
/interface/wireguard/peers/set [find comment=lab-peer] \
allowed-address=0.0.0.0/0
/ip/route/add dst-address=0.0.0.0/0 gateway=wg-lab comment=default-via-tunnel
> /ping 198.51.100.1 count=5
sent=5 received=5 packet-loss=0%
> /ip/firewall/filter/print stats where comment~"count"
;;; count: labhost icmp arrived on WAN link
0 input passthrough 0 0
;;; count: labhost icmp arrived through tunnel
1 input passthrough 280 5
On the peer, a counter on the WAN link read 0 packets and a counter on the tunnel read 5. All five pings went into the tunnel.
That is why a copy-pasted "send everything" recipe can cut a router off from its own management traffic: if the peer cannot answer, nothing the router sends beyond its directly connected networks gets out. Our post on a VPN that connects but carries nothing goes through the symptoms that follow.
How do you run the container client on RouterOS?
You enable container mode once, with physical access, then give the container a veth interface, a mount for its state and a pinned image. MikroTik documents the first step as /system/device-mode/update container=yes, confirmed by a reset-button press, or by a cold reboot on x86.
Physical access is the point. The same MikroTik page warns that once the container feature is enabled, containers can be added, started and removed remotely, and that a router is as secure as anything you run in a container. Enabling it is a decision. Do not treat it as a formality.
On our virtual router the confirmation was different, because it has no button. The update printed a countdown, "turn off power in 5m to activate changes", and the change applied after a power-off. The device-mode printout then read container: yes. On hardware, expect the reset button the documentation names.
Container objects
The setup follows the pasted block on our download page, and our lab used these objects (state and root on the attached disk, for a reason given below):
How this was tested
- Product
- ForestVPN router client in a RouterOS container
- Version
- image suquant/fvpn:0.3.17, RouterOS 7.24.1, container package 7.24.1
- System
- virtual router, arm64 under QEMU software emulation
- Checked
- Runs
- 1
Not tested
Same virtual router as the native run, with a free licence level. Root and state sat on the attached disk, disk1, because the router had only 68.9 MiB free on its built-in storage. The container was not paired to any ForestVPN account, and the pairing code it printed was not entered anywhere; it is redacted in the saved log. The container was stopped at the end of the run. Not tested: the container's LAN path, mangle rules, the kill switch and any speed.
/interface/veth/add name=veth-fvpn address=172.31.254.2/30 \
gateway=172.31.254.1
/ip/address/add address=172.31.254.1/30 interface=veth-fvpn
/container/mounts/add list=fvpn-state src=disk1/forestvpn \
dst=/etc/forestvpn mode=rw
/container/add remote-image=suquant/fvpn:0.3.17 interface=veth-fvpn \
root-dir=disk1/fvpn mountlists=fvpn-state logging=yes start-on-boot=yes \
privileged=yes name=fvpn
That block is shortened to the objects that matter. The real one on the download page also carries the entrypoint and the arguments, so paste that one, not ours.
Our first pull failed with "check registry failed: resolving error" because the router had no DNS server yet. After we gave it one the pull downloaded three layers and the container started.
What the log showed
In order, the log showed:
- A new machine key written.
- The interface
fvpn0started. - The status page started.
- The signed server list verified.
- A new device registered and a pairing code printed.
That is a virtual router, not the hardware verification, which remains the cAP ax on the install page. The log also explains why the native commands above do not apply here: you never type a private key, a peer or an endpoint. The client makes its own key and fetches its exit.
Disk choice
MikroTik's page recommends container volumes on an attached disk. Our download page answers "Do I need a disk?" with no for the plain container install, and its block puts root and state on built-in storage. The lab used disk1 only because the virtual router's built-in space was nearly full.
LAN traffic
Out of the box only the container's own traffic uses the tunnel. The install script says so itself: with its LAN option left off, the LAN keeps its normal connection. To send LAN devices through it you paste the routing script from the router's status page, which adds the mangle rules and the routing table, and the choose-traffic page explains its modes.
Does a WireGuard container use less CPU than RouterOS's own WireGuard?
On the one pair of hardware runs we hold, our core in a container used about half the CPU per megabit that RouterOS's own tunnel did, and it lost on latency. On two physical MikroTik routers on 2026-09-01, an RB3011UiAS as sender and a cAP ax as receiver, both on RouterOS 7.24.1, the throughput post records 122 Mbit/s for our core, run as fv in a RouterOS container started by hand, and 66.8 Mbit/s for RouterOS's kernel tunnel.
Show the data
| Container core | 122 Mbit/s |
|---|---|
| RouterOS kernel tunnel | 66.8 Mbit/s |
CPU per megabit and round-trip time tell the other half. Each figure is a single run, from the same post.
| Measure | Container core | RouterOS kernel tunnel |
|---|---|---|
| Throughput (Mbit/s) | 122 | 66.8 |
| Sender CPU per Mbit/s (percent) | 0.53 | 1.10 |
| Round-trip time (ms) | 1.22 | 0.92 |
The kernel tunnel won on round-trip time. These limits matter more than the numbers:
- The two arms used different traffic generators,
dd | ncfor ours andbandwidth-testfor the kernel tunnel, because no one generator ran on both. - The figures belong to those two boards. We have not repeated them on other models, on OpenWrt, or on the virtual router, where software emulation would say nothing about a real board.
- If your router is a different board, measure for yourself.
Whether WireGuard is quicker than OpenVPN on a MikroTik is a question we cannot answer. We never timed OpenVPN there.
FastTrack can also skip the rules a tunnel needs; see how FastTrack interacts with a tunnel.
What does the MTU do to a MikroTik tunnel?
A wrong MTU looks like this: the handshake succeeds, small packets such as pings work, and large downloads stall. If the interface is running and pages hang, suspect that before a dead tunnel.
Tunnel headers eat into the packet, so the largest packet that fits inside it is smaller than the link underneath allows. The RouterOS WireGuard interface defaults to an MTU of 1420, per MikroTik's page, and our native run printed mtu=1420.
There are two fixes:
- Lower the interface MTU in steps and test again.
- Clamp the TCP maximum segment size on the router. The container's tunnel runs at an MTU of 1416, and the routing script on the choose-traffic page adds two mangle rules that set
change-mssto 1336 for it.
That clamp ships with the container route's script, so on the native route you write your own. The connected-but-no-internet post has the longer version.
We never tried an MTU other than the default 1420, so we cannot suggest a better value for your link.
For the general rule and how to find a working value, see the WireGuard MTU guide.
Does a MikroTik kill switch work?
On the container route the kill switch is part of ForestVPN's routing script, in every mode. As the MikroTik kill switch help page lists it, the script adds a routing table whose default route is the container with a blackhole behind it, a routing rule that never lets a marked packet fall back to the main table, and forward drops. The page records a test on a cAP ax test LAN running RouterOS 7.24.5, and gives a stop-the-container leak test you can repeat.
It covers only the traffic you selected, and it is IPv4 only. The native route ships no kill switch at all; you would write the equivalent rules yourself. We did not exercise either in the lab run described here.
Should you use RouterOS's WireGuard interface or a container VPN client?
Choose the native interface if you already hold a WireGuard configuration for a server you run or rent and want to write every route yourself. Choose the container if you want a client that looks after its own keys and exit, and you accept the package, device-mode and RouterOS rules it asks for.
| If | Choose |
|---|---|
| You hold a WireGuard config for your own server and read RouterOS comfortably | Native interface |
| You want the router itself to hold an account-managed identity | Container client |
| Your board is a 16 MB flash-folder model | Container with the flash folder recipe ("Not yet verified on hardware"), or native |
| You cannot touch the router to confirm device-mode | Native interface |
| You need a kill switch you can verify today | Native: none shipped, you write it. Container: the routing script's kill switch, with a leak test on its help page |
| You want to send chosen apps or services, not the whole LAN | Container, with the routing script's devices or services mode; native: write the mangle rules yourself |
Whichever you pick, test with a stop. Bring the tunnel down on purpose and watch what the LAN does. A guide that ends at "ping works" never shows you that.
Where to go next:
- The container route's LAN steering is on the choose-traffic page.
- The MikroTik vs OpenWrt comparison sets this recipe against the OpenWrt one.
- For an OpenWrt router, the OpenWrt WireGuard post covers the manual route.
ForestVPN's tunnel in the container uses the unmodified Noise_IKpsk2 handshake the WireGuard project specifies. The WireGuard comparison page sets the protocols side by side.
Questions and answers
Can I use a MikroTik router with WireGuard?
Yes. RouterOS 7 has a WireGuard interface built in, so you create the interface, add a peer, give the interface an address and write the routes yourself. A second route runs a client in a RouterOS container instead.
Can I use MikroTik as a VPN client?
Yes, in two ways. The native route makes the router a WireGuard client of any server you hold a configuration for. The container route runs the ForestVPN client on the router, which registers itself and prints a pairing code.
Which MikroTik routers support WireGuard?
Any router running RouterOS 7, with 7.1 or later the floor a third-party guide cites for the native interface. For the container route you also need the container package, which MikroTik documents for arm, arm64 and x86, and our client asks for RouterOS 7.21 or later.
Is WireGuard faster than OpenVPN on MikroTik?
We did not time OpenVPN on MikroTik, so we cannot say. The one pair we hold compares two WireGuard-protocol implementations on two MikroTik routers, and it does not transfer to other boards.
What is device-mode and why does the container package ask for a reset-button press?
Device-mode is a RouterOS switch that keeps risky features off until someone with physical access to the router turns them on. On hardware the confirmation is a reset-button press, or a cold reboot on x86. On our virtual router it asked for a power-off instead.
What does AllowedIPs 0.0.0.0/0 do to my router's own traffic?
If you also add a default route through the WireGuard interface, the router's own pings, DNS and updates go into the tunnel too. In our lab run all five test pings arrived through the tunnel and none through the WAN link.
How much CPU does each route use?
On two MikroTik routers on 2026-09-01 the container core used 0.53 percent of the sender's CPU per Mbit/s, and RouterOS's kernel tunnel used 1.10. That is one pair of runs on that hardware, not a rule.
Does a MikroTik kill switch work?
On the container route the kill switch ships inside ForestVPN's routing script: a blackhole route, a rule that never falls back to the main table and forward drops. It covers only the traffic you selected, and the native route has none, so read the help page before relying on it.
Sources
- MikroTik documentation: WireGuard (read October 16, 2026)
- MikroTik documentation: Container (read October 16, 2026)
- MikroTik Masters: Setting up WireGuard on MikroTik (published 2025-01-30) (read October 16, 2026)
- Proton VPN support: WireGuard on MikroTik routers (read October 16, 2026)
- WireGuard protocol and cryptography (read October 16, 2026)
How this was made
Drafted with AI assistance from a lab run on a virtual RouterOS 7.24.1 router, ForestVPN's router help pages and MikroTik's documentation, checked by automated gates and an editor; the CPU figures come from an earlier run on two physical routers.