## Motivation

You can find many WireGuard configuration guides for RouterOS 7, including [mducharme's fine road-warrior but I needed something a bit different. My use case is that the WireGuard server is a 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:


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

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 used a random number generator in the 1024-49151 range and then used that everywhere.

Since my VPN endpoint is behind another router, I [forwarded this UDP 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 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 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:

``` ini
Name: Home (value doesn't matter)

Private key: generated by app
Public key: ditto

Addresses:
DNS servers:

Peer:
  Public key: public-key line of output
  Endpoint:
  Allowed IPs: ::0/0
```

Notes:

1. Copy the public key value into the … public-key=""` bit in the RouterOS configuration.
1. The `Addresses` line is the same as `allowed-address` in the RouterOS configuration.
1. 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.
1. I recommend using a dynamic DNS service such as [MikroTik rather than a static IP on the `Endpoint` line.
1. The port number on the `Endpoint` line is the same random port I recommended you pick above.
1. 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 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.


## <a id="license"></a>License

This work is © 2022-2024 by Warren Young and is licensed under <a target="_blank" rel="license noopener noreferrer">CC BY-NC-SA 4.0<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" style="height:22px!important;margin-left:3px;vertical-align:text-bottom;" style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"

<div style="height: 50em" id="this-space-intentionally-left-blank"></div>