SOLVED: Port forwarding from MikroTik router to internal network (behind DS-Lite) via WireGuard

Hey, I have a pretty common set-up request for providers that no longer grant static public IPs:

I want to set-up a cloud hosted router (CHR) using MikroTik, that should be used for TCP & UDP port forwarding to my internal network. I set up a Debian VM in my local network that connects to the MikroTik router using WireGuard. The CHR has a static IPv4 and v6 address. Here is what I set-up so far:

  • The Debian VM connects to the MikroTik router via IPv6 with the following configuration:
[Interface]
Address = 10.6.0.2/24
SaveConfig = true
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o ens3 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o ens3 -j MASQUERADE
ListenPort = 48080
PrivateKey = client_private_key

[Peer]
PublicKey = server_public_key
AllowedIPs = 10.6.0.0/24
Endpoint = [server_public_ipv6]:13231
PersistentKeepalive = 25
  • IPv4 forwarding is enabled on the Debian VM and the MikroTik CHR
  • The MikroTik’s (“server”) WireGuard interface has the IP address 10.6.0.1 and again the allowed addresses are: 10.6.0.0/24
  • On the MikroTik firewall I set up 4 rules so far:

accept forward from ether1 to wireguard1
accept forward from wireguard1 to ether1
dstnat from interface ether1 port 1234 to address 192.168.1.10 port 1234
srcnat for the out interface wireguard1 with action masquerade

I can successfully ping 10.6.0.2 on the MikroTik router and 10.6.0.1 on the Debian VM, so the tunnel is established it seems. However I think I am still missing some pieces to tell MikroTik essentially:

Everything you receive (IPv4) should get forwarded to the 192.168.1.0/24 IP range in the internal network of my Debian VM and the response from my internal network should go via the MikroTik CHR back to the internet.

Any help in providing me with the “rest of the puzzle”? Thanks!

Very confusing without a diagram.
Do you mean you setup CHR in the cloud on some service??

Hey, sorry for my late reply. Good news: I meanwhile solved my issue and I am able to “port forward” stuff on my internal network. Here a little image to explain what I have been trying to achieve:
SNAG-20240928-00.png
I guess it is a pretty straight forward Wireguard set-up, what solved the issue I described initially was, that I had the wrong understanding of how “AllowedIPs” work in Wireguard. My assumption was that on the server side you tell the peer what “IP ranges forwards are allowed”, however I found out that “AllowedIPs” determines which IP ranges should get forwarded to the Wireguard tunnel. So exposing my internal IPs on my Cloud Hosted Router via Allowed IPs solved it for me.

Thanks for your quick response @anav.

Good to hear, and if you run into future issues, please post both configs
/export file=anynameyouwish ( minus router serial number, any public WANIP information, keys etc.)

Allowed IPs describe three things

  1. THE WIREGUARD NETWORK PORTION
    a. the wireguard subnet 0/24 ( at the client device peer at initial handshake ) *********
    b. the wireguard exact peer /32 ( at the server device peer at initial handshake, should have a separate allowed IP entry for each client peer)

  2. The REMOTE SUBNETS, local users need to access.

  3. THE REMOTE SUBNETS, accessing the local LAN.

The Exceptions
******** If the client peer needs internet access through the connection, allowed peers are replaced by 0.0.0.0/0

Note: Local subnets are never described.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In your case, the allowed IPs on the wireguard of the CHR router (server for handshake) are simple.
10.20.30.2/32, NASsubnet, Anyother relevant remote subnet.

In other words, the outside users are going to come in on the CHR router heading to the server based on
StaticWANIP of the CHR and port off NAS server on the second router

With port forwarding rule.
add action=dst-nat chain=dstnat dst-address=staticIPofCHR dst-port=NAS port protocol=XYZ to-addresses=NAS_lanIP

So all that traffic now is heading to the IP address of the NAS server so we have to let the CHR know WHERE to send this non-local traffic.

The question that needs answering before proceeding → Does the NAS need to track sourceIP for any reason…
Solution A: The NAS server doesn’t need to know the sourceIP of each user, so we then, to simplify, sourcenat the traffic heading into the wireguard tunnel.
add chain=srcnat action=masquerade out-interface=wireguard1
Now all wireguard traffic will be given the source IP address of the wireguard interface on the CH

We still need a route to match the allowed IPs identifying where to send non-local subnet bound traffic.
add dst-address=NASsubnet gateway=wireguard1 routing-table=main.

Outside users are port forwarded to the lANIP of the server and the router is told to send that traffic out wireguard and on the way out the users IPs get changed to the IP of the CHR wireguard interface, so far so good.
The traffic arrives at the wireguard portal on the home router.
The incoming IP of the chr wireguard interface is accepted.
One needs a firewall rule forward chain rule to ensure that traffic can reach the subnet server
add action=accept chain=forward comment=“remote users to NAS” in-interface=wireguard1 dst-adddress=NAS_lanIP

The return traffic is sent to the wireguard IP of the CHR of which the home router is aware and sends the traffic back out the wireguard interface.

++++++++++++++++++++++++++++

Solution B: What if there is a requirement to capture the source IPs at the NAS server, this has a ripple effect on the settings.
There is no change on allowed IPs for the CHR,
There is no change on port forwarding,
However we CANNOT sourcenat out the wireguard tunnel.

The main changes are on the home router.
Allowed IPs becomes; 0.0.0.0/0 ( since you need to be able to capture all possible public IPs hitting the CHR)
So, the effect is that all that traffic forwarded from various IPs hits the home router,
We need the same forward chain rule to allow access to the NAS…
However when the NAS replies, the router has no idea where to send the return traffic!!!
Therefore we need to capture/identify the traffic and direct the traffic back through the wireguard tunnel.
Easiest is to
add table fib name=useWG
add route dst-address=0.0.0.0/0 gateway=WG-Home routing-table=useWG
/routing rules
add min-prefix=0 action=lookup-only-in-table table=main comment=“ensure NAS local traffic is permitted”
add src-address=NAS-lanIP action=lookup-only-in-table table=useWG comment=all other NAS traffic forced out tunnel"

So you can see that there is a simple way and a more complicated way of accomplishing the flow depending upon requirements.