Trouble Routing Certain Traffic Between Subdomains

I'm posting this in Beginner Basics because I feel like the answer is going to be simple and I'm just brand new to managing a firewall on this level. My problem is that I can't get my computer on one subnet to reach my web server on the other unless I forward all HTTP/S traffic to the server and break web browsing entirely. Here's the details....

_____

I have two subnets: 192.168.11.0/24 for my web host server, and 192.168.69.0/24 for my typical LAN devices (PC, phones, etc.)

There is a DNS entry for my web server so www.example.url resolves to my Mikrotik router's public IP address. Port forwarding has been successful so that requests for www.example.url on port 80 and 443 from outside of my LAN will retrieve my website.

Unforunately, fowarding all traffic on port 80 and 443 to my web server causes any HTTP/S requests from my LAN subnet to get routed to my website as well. I solved this by adding the In. Interface value and setting it to my WAN port so that this forwarding only applies to requests arriving from the internet.

Now the problem: I can't access the website from inside of my LAN. By specifying the In. Interface, I have excluded my LAN hosts from the forwarding.

_____

I'm going to leave the problem at that because I think my brainstorming has been mostly counter-productive and I bet there's a way to do this that's easy and standard. This is the first time I've ever encountered networking deeper than forwarding ports on a typical TP-Link home router so I'm drowning just a little here.

My understanding of the problem is that I need to forward ports to my LAN subnet the same way that I have for people on the internet, but trying to do so has left me breaking something no matter what idea I come up with.

What am I missing? What's the normal way to allow my PC on one subnet to reach a web server on another subnet without screwing up web browsing?

*Thanks for reading!*

If we start from default ROS configuration: there's this ultimate rule which enables port forwarding:

/ip firewall filter
add chain=forward action=drop connection-nat-state=!dstnat in-interface-list=WAN comment="defconf: drop all from WAN not DSTNATed"

The problem with it, which shows up whenever router setup and surrounding topology is not according to default setup expectations, is that it actually joins two distinct functions and they can be written as follows:

/ip firewall filter
add chain=forward action=accept connection-nat-state=dstnat in-interface-list=WAN comment="accept all DSTNATed traffic"
add chain=forward action=drop in-interface-list=WAN comment="drop all the rest of traffic from WAN"

Now, when one tries to forward some certain port for WAN users, a NAT rule similar to this should be constructed:

/ip firewall nat
add action=dst-nat chain=dstnat comment="HTTP to internal server" dst-port=80 in-interface-list=WAN protocol=tcp to-addresses=192.168.11.XX

One has to use something like in-interface-list=WAN not to capture traffic towards router's own WebFig. But it also skips performing DSTNAT for connections, originating in one of your LANs. So you have to widen the selection criteria to cover also your LAN ... but that inevitably creates danger of masking off router's own service (WebFig).
And when using in-interface-list=WAN (as per default configuration philosophy), then there's no firewall filter rule which would govern connections between different LAN segments. Which may be fine if you want to allow all connections in all directions, but may not be fine if you do have some firewall filter rules which limit connections between different LAN segments and you then need a rule which allows such DSTNATed traffic.

There's one elegant solution ... but it only works if your WAN IP address is static: change the NAT rule above to this one:

/ip firewall nat
add action=dst-nat chain=dstnat comment="HTTP to internal server" dst-port=80 dst-address=<your WAN IP address> protocol=tcp to-addresses=192.168.11.XX

This way if you use your web browser and try to access HTTP port on your router's WAN IP address, it'll get NATed (forwarded) to your internal web server. And if you try to access HTTP port on your router's LAN IP address, you'll land on WebFig pages.

If your WAN IP address is not static, then you can't use WAP IP address in DST-NAT rule (because it would fail to work every time your WAN IP address changes). There are ways around that, but that complicates your life a bit (and creates a window which starts at the moment your WAN IP address changes and until some magic stuff updates NAT rule).

As @mkx wrote, you cannot use the in-interface=xxx or in-interface-list=WAN condition in your DSTNAT rule. If your public IP address is a static one, then use dst-address=<your WAN IP address> as instructed by @mkx . But in case you have a fully dynamic WAN IP address that can change often, you can do this instead:

  • Create an address list ROUTER_LOCAL where you put the router's addresses in the LAN subnets (in this example 192.168.11.1 and 192.168.69.1:

    /ip firewall address-list
    add address=192.168.11.1 list=ROUTER_LOCAL
    add address=192.168.69.1 list=ROUTER_LOCAL
    
  • Your DSTNAT rule will then look like this:

    /ip firewall nat
    add action=dst-nat chain=dstnat comment="HTTP to internal server" \
        dst-address-list=!ROUTER_LOCAL dst-address-type=local dst-port=80 \
        protocol=tcp to-addresses=192.168.11.XX
    

    Notice the negation ! symbol. This will work for both static as well as dynamic WAN IP addresses, while still allow you to use WebFig on 192.168.11.1 and/or 192.168.69.1.

  • Also add the hairpin-NAT rule in case you haven't do it:

    /ip firewall nat
    add action=masquerade chain=srcnat dst-address=192.168.11.0/24 src-address=192.168.11.0/24
    

There is no hairpin here, as the server has its own subnet.
even if you have a dynamic WANIP, you can still use dst-address IDEA, except use dst-address-list

Where you use the ip cloud dyndns name that MT provides.
/ip firewall-address list
add address=848484mynetname.net list=myWAN

Then
/ip firewall-nat
add action=dst-nat chain=dstnat comment="HTTP to internal server" \
dst-address-list=myWAN dst-port=80 protocol=tcp to-addresses=192.168.11.XX

As noted previously, one should remove the dual function and often confusing MT firewall rule with the following:

add chain=forward action=accept comment="internet traffic" in-interface-list=LAN out-interface-list=WAN
add chain=forward action=accept comment="port forwarding" connection-nat-state=dstnat
add chain=forward action=drop comment="drop all else"

I actually found the dst-address-type=local field in a solution somewhere after a couple more hours of searching and made a rule with that. It appears to work, though there are some oddities which may be related or may not (I'm setting everything up from scratch as a learning experience, so it's hard for me to say). I use WinBox but I'll do my best to write out the rule here...

add action=dst-nat chain=dstnat dst-address-type=local dst-port=80 protocol=tcp to-addresses=192.168.11.111

As you can see, it's the same except for your ROUTER_LOCAL list. I'm curious... if the web server is the only place any HTTP/S traffic would go to inside of my network (across the subnets) then do I still need to specify that the destination is not any of those list items? I'm not sure if my PC on subnet 192.168.69.0 will ever send port 80 traffic to any of the gateways, but I'm not sure of a lot of things, so...

As for the oddities I mentioned, Firefox does keep telling me now that I need to "sign into this network to use the internet", as I happily use the internet regardless. Also, playing Minecraft on the server shows a 'disconnected' icon as if whatever data exchange the client uses to detect a connection is broken, despite the game playing normally. Again, these may be unrelated as I might just be missing other rules still (I most certainly am not done with the firewall yet), but worth a mention.

Thanks a bunch for the information so far.

This look very promising and I think I understand exactly how your instructions will work, but I'm not sure what you mean here by "the ip cloud dyndns name". I know of a DNS provider called DynDNS, does your suggestion depend on me using their service, or is "dyndns" common shorthand for dynamic DNS as a whole? In either case, I'm not sure where to go to find this value. It would be very cool if I could use my URL in NAT rules, that would solve this problem for me.

Thanks for the info!

Thanks so much for the detailed response and sorry for the late reply, my day job does not involve computers, so it's a 24hr turnaround for me to reply.

I somehow forgot to mention this up front: I (as a learning exercise) did not start with the default configuration. I did, however, quickly implement the aforementioned firewall rule to drop all !dstnat traffic to achieve some base level of security as I learn the rest.

I did add the rule to forward port 80 to my web server (as well as 443, of course) and I'm happy to say that I understand how everything is working thus far. I think you've helped me understand the common solution to the problem, which is either a static IP or a script to update the dst-address to the current WAN IP in my case of a dynamic IP from my ISP.

I've got a couple questions, one about the script solution. I already use a script to send my WAN IP to my DNS host who then updates my DNS record accordingly. This happens ever hour or so, leaving me with an inevitable downtime period when my ISP changes my public address, but I accept it because my server is entirely recreational. Could I have that script, which is run on the web server host, include a signal to the router to update the WAN IP in a list? Or, could I now run both of these scripts on the Mikrotik? (I have no idea what capabilities my Mikrotik has, this is my first experience with the brand).

My other question is about the Dst. Address Type value in the 'Extra' tab of a NAT rule. Another hour or so of desperate googling after making this post, I found someone with apparently the same problem who used this to solve it. By setting the Dst. Address Type to local, it appears to effectively apply the rule if the connection is to the router, as if it belonged to the input chain but allowing me to apply a dst-nat action. With this set, things to appear to work normally (my website loads and so do others), except for a few peculiarities that might be related or not:

  1. Firefox keeps telling me that I have to "sign in to this network to use the internet" in a banner above websites despite being able to browse normally, and
  2. When I connect to a Minecraft server (one of the services my web server provides), I can play just fine but the 'disconnected' icon appears on the bottom left which tells me that my PC isn't receiving back some data that informs it that it's connected.

Is this Dst. Address Type field not appropriate for the situation, or simply needing additional rules to quiet these false reports of not being connected?

Thanks again for you knowledge.

When you use dst-address-type=local without the exception for the ROUTER_LOCAL list as in my example, then you redirection works when you enter the WAN IP address, but will also kick off when you enter http://192.168.69.1/ for example (and same for HTTPS if you also add a rule for port 443). Which means you are no longer able to access WebFig (the web management interface) to manage the router on that address, unless you change the WebFig configuration (the www and www-ssl services under /ip service) and move them to other ports.

If you use the address list and add the address exclusion, then you'll still be able to use WebFig without relocating the ports.

Of course, if you never have the need to use WebFig then you can ignore all that.

If your device is purchased from MikroTik (not a PC that you've built yourself and installed the x86 variant of RouterOS) then MikroTik provides you with a DDNS service with the domain name serialnumber.sn.mynetname.net that you can enable by going to the IP -> Cloud menu. This also applies if you've bought a CHR license. If enabled, this subdomain will point to your public IP address and will be kept up-to-date automatically.

Of course, you don't have to use that and can use other DDNS service providers of your choice.

You don't use the URL directly in NAT rule, but you can create IP -> Firewall -> Address List entries where you put a domain name instead of an IP address in the address field. The router will then automatically resolve the domain and generate dynamic IP firewall address list entries with the same name with the resolved IP addresses. The TTL of the domain will be considered to refresh the entries on time. You can then use the address list in thedst-address-list= or src-address-list= conditions of your firewall rules, including the NAT rules.

However, there will of course be delay due to the DNS TTL. If the domain's IP addresses change, there will be periods where the address list entries still have the old wrong IP addresses (it really depends on how long the TTL of the domain is, there is almost no issue if the TTL is only 1 minute, but it's really bad if the TTL is set to 1 day for example). There might be a time where your PC already resolves the new addresses, while the router still uses the old ones in the address list because the last time it updated the list was still more recent than TTL. During that period, your FW rules will not work.

If the TTL is too long, then this approach is not usable and the dst-address-type=local approach would be safer.