MikroTik Solutions

WireGuard Configuration


You can find many WireGuard configuration guides for RouterOS 7, including mducharme's fine road-warrior configuration, but I needed something a bit different. My use case is that the WireGuard server is a CRS328 behind a third-party Internet router rather than a directly Internet-facing MikroTik router.

RouterOS Configuration

I added double-NAT to mducharme's configuration, then simplified it a bit:

/interface wireguard
add listen-port=12345 mtu=1420 name=wg1
/interface wireguard peers
add allowed-address= interface=wg1 public-key="iPhone-pubkey"
add allowed-address= interface=wg1 public-key="iPad-pubkey"
/ip address
add address= interface=wg1
/ip firewall nat
add action=src-nat chain=srcnat src-address= to-addresses=

This example uses the MikroTik default of for the LAN — with the router as .1 — and the nearby subnet for WireGuard.

Although port 13231 seems popular for WireGuard, there's nothing about the protocol that requires it. I prefer to put it somewhere random, making it harder for bots to target. I'm using 12345 in this example, but in my actual config I let the iOS client pick something random and then used that everywhere.

Since my RouterOS box is behind another router, I forwarded this UDP port to it. If you're running WireGuard on a RouterOS box acting as your Internet gateway instead, you'd need to add an "action=accept" firewall rule for that port instead. (Conversely, I don't have a firewall on my LAN's RouterOS boxes, since they're mainly acting as smart switches.)

The srcnat rule at the end is the novel bit. Without it, the clients can connect to internal LAN hosts, but they can't get back out to the Internet. That may in fact be fine for some use cases, but one of my uses for a VPN is to encrypt my Internet traffic over potentially hostile LANs. (Coffee shop and hotel type cases.) The consequence is that double-NAT may be a problem, so it's better to terminate WireGuard on the Internet border gateway router if you can, letting you drop that rule.

The protocols that tend to fail with double-NAT tend to be old, even obsolete. Many modern Internet protocols use clever NAT traversal methods that will work through double-NAT, so it is not always a problem in practice.

iOS WireGuard.app Configuration

The current iOS WireGuard client seems to have quite a lot of UI differences relative to what mducharme documented, so for completeness, here's my sanitized iPhone configuration:

Name: Home (value doesn't matter)

Private key: generated by app
Public key: ditto

DNS servers:

  Public key: public-key line of /interface/wireguard/print output
  Endpoint: my.dynamic.dns.example.com:12345
  Allowed IPs:, ::0/0


  1. Copy the public key value into the /interface/wireguard/peers … public-key="" bit in the RouterOS configuration.
  2. The Addresses line is the same as allowed-address in the RouterOS configuration.
  3. The DNS servers line points to a private LAN DNS server in this example, but it could instead be the border gateway router's IP if it's running a DNS cache, a public DNS server such as, etc.
  4. I recommend using a dynamic DNS service such as MikroTik Cloud rather than a static IP on the Endpoint line.
  5. The port number on the Endpoint line is the same random port I recommended you pick above.
  6. We set a wide-open Allowed IPs line to allow the client to act as any LAN client, using all resources freely, both LAN and WAN.

Everything else we leave at their defaults. With this configuration you can see LAN resources, and everything else gets srcnatted and sent as if it was coming from the WireGuard server, subject to whatever rules you have for Internet access from that LAN.

Alternate Double-NAT Avoidance Methods

There are two potential ways to avoid double-NAT while still terminating WireGuard behind a NAT:

  1. If your Internet gateway router supports custom static routes, you could route the WireGuard subnet ( in my example) to the RouterOS box as the next-hop IP.

  2. If you're only using desktop OS WireGuard clients, you may be able to use their PostUp and PostDown rules to manipulate the local route table instead. I couldn't do that in my case because the iOS client doesn't have that option, and even if it did, I feel quite sure iOS wouldn't let you directly manipulate the route table like that.


This work is © 2022-2024 by Warren Young and is licensed under CC BY-NC-SA 4.0