"NAT forward to gateway"

Hello everyone, I’m sorry for the probably unclear name - but I don’t know what to call it exactly. I have a network (see description below) that is controlled by one main router (Router A) and is a gateway for other routers in the network that are gateways for clients.

Router A - 10.20.1.1 (gateway, main router)
Router B - 10.20.1.23 (client of router A) and 10.20.7.1 (gateway)
Client A - 10.20.7.2 (client of router B)

Now Client A appears to Router A as 10.20.1.23 (because the standard masquerade is set on Router B). But I would like it to look like 10.20.7.2 for Router A, but its gateway remains Router B. For example, in the log, when Client A logs into Router A via winbox.

Is it possible to set this somehow?

Maybe I’m describing it wrong, but I want Router A to monitor traffic in the entire network and set up queues for individual clients of the entire network, but not be the gateway of the entire network…

Thanks in advance for any replies and advice.

You can selectively disable NAT for 10.20.7.2 on router B by placing an action=accept rule before the action=masquerade (or action=src-nat) one and let it match on src-address=10.20.7.2, or by adding src-address=!10.20.7.2 to the action=masquerade one if src-address match is not used in that rule yet. Or, if you explanation is just overcomplicated, you may simply disable the src-nat/masquerade rule at router B completely if you actually want to treat everything connected to LAN of router B the same way and 10.20.7.2 was just a particular example.

No matter which variant of the above you choose, you must add a route dst-address=10.20.7.0/xy gateway=10.20.1.23 to router A (replace xy by the actual mask of the LAN subnet of router B. You also have to make the DHCP lease for router B static, otherwise the route would become incorrect if router A would eventually assign a different address to router B (not likely but possible).

If you want it fancier, you can use OSPF so that router B would advertise itself as a gateway to 10.20.7.0/xy, but I guess it would be an overkill unless there are more than 5 routers in your network.

Hello, thank you very much. If I turn off src-nat/masquarade completely, the client’s internet stops working. Maybe I’m still missing some settings there? I have a route from Router A to Router B set up. I also have static IP addresses on DHCP.

Otherwise, yes, this is an example. There are currently 10 similar routers (as Router B) on the network and more to come, so if there is a better solution, I’d be happy to use it…?

Thanks in advance.

If you have a route to 10.20.7.0/24 (or what the actual mask is) on router A, NAT at router B should normally not be necessary. So there must be some additional issue which I cannot guess. Hence post the configuration exports of router A and router B (/export hide-sensitive file=router-X) between [code] and [/code] tags, after removing additional sensitive information (public IP addresses, usernames for VPNs etc.) first.

Thank you very much for the advice… So I checked it all over again on Router A, and found out what was causing it…

I had this firewall rule there that was blocking clients from getting to each other…

add action=drop chain=forward dst-address-list=ip_clients

Now I added this rule after which it started working:

add action=accept chain=forward dst-address-list=ip_clients in-interface-list=WAN

Is this ok like that or is there a better solution?

Apart from this, you proposed some more efficient solution over to route other routers in network by OSPF. Can you please advise how to set this up?

Thank you very much in advance.

The rule you have added looks strange to me in terms that you permit access to client subnets from WAN, but again - what you have shown is a modification to a configuration unknown to me, so how can I say it is the best way to do it or the worst?


Look at the OPSF manual. If it seems easy to you, do that; if it doesn’t, stay with the manual configuration. OSPF makes sense in mesh topologies where it can control path redundancy, and in star topologies with many “spokes” where it can be used to add routes automatically to the central hub. But in the latter case, the complete OSPF configuration on the spoke requires more steps than adding a route on the hub, so if there is a single LAN subnet on each spoke, it’s not worth the effort.

I was just wondering if it wasn’t too general… On the other hand, if there wasn’t the blocking rule at all, it’s partly the same as now… Anyway, in general, how would you recommend setting the rules when I want block so that clients cant reach each other (IP addresses in the “ip_clients” list) and so that even the ISP company (WAN) can’t access them. At the same time, of course, I also need them to have Internet access.

Basically, as long as Router B works as a masquerade for clients, this simple rule worked to do what I need:

add action=drop chain=forward dst-address-list=ip_clients

Now I need to make some exception to this rule so that the clients can get internet. :slight_smile: Maybe I described it inaccurately before…

Can you please advise on this specifically?
Thank you very much.

I normally prefer to construct the firewalls as a list of “accept” exceptions with a “drop the rest” rule at the end, because if you forget to permit something, your legal users will let you know very quickly; if you forget to forbid something, your illegal users will never notify you.

You seem to use the same approach, so the only issue I had with the rule you’ve shown in the previous post was that you perrmitted access to the client addreses via WAN, which looks like allowing access to them from the internet (well, mostly from ISP, packets towards private addresses usually don’t get too far in the internet) rather than from other clients. But maybe there is a typo and you have actually added this rule to router B, not to router A as you wrote?


For the third time: I haven’t seen your current configuration so all my advice is based on just experienced guesses. So I cannot suggest more that the above.

What I meant was that this rule worked for me on Router A, so that the internet works for clients, but I didn’t think it was a very good solution…

Sorry for the complications, I am sending my firewall configuration (from Router A - main router):

# 2023-12-04 16:09:38 by RouterOS 7.12
/ip firewall filter
add action=accept chain=input src-address=VPN Public IP
add action=accept chain=input comment="Access from VPN" src-address=\
    VPN range
add action=accept chain=forward comment="Access from VPN" src-address=\
    VPN range
add action=accept chain=input comment="Access from VPN" src-address=\
    second VPN range
add action=accept chain=forward comment="Access from VPN" src-address=\
    second VPN range
add action=accept chain=forward comment="Access to DNS" dst-address=\
    Internal DNS server
add action=drop chain=forward dst-address=VPN clients
add action=drop chain=forward dst-address=second VPN clients
add action=drop chain=forward comment="Block Clients IP" \
    dst-address-list=ip_clients
add action=add-src-to-address-list address-list=Syn_Flooder \
    address-list-timeout=1d30m chain=input comment=\
    "Add Syn Flood IP to the list" connection-limit=30,32 protocol=tcp \
    tcp-flags=syn
add action=drop chain=input comment="Drop to syn flood list" \
    src-address-list=Syn_Flooder
add action=add-src-to-address-list address-list=Port_Scanner \
    address-list-timeout=1w chain=input comment="Port Scanner Detect" \
    protocol=tcp psd=21,3s,3,1
add action=drop chain=input comment="Drop to port scan list" \
    src-address-list=Port_Scanner
add action=jump chain=input comment="Jump for icmp input flow" jump-target=\
    ICMP protocol=icmp
add action=jump chain=forward comment="Jump for icmp forward flow" \
    jump-target=ICMP protocol=icmp
add action=drop chain=forward comment="Drop to bogon list" dst-address-list=\
    bogons log=yes log-prefix=echo
add action=drop chain=forward comment="Avoid spammers action" dst-port=25,587 \
    protocol=tcp src-address-list=spammers
add action=accept chain=input comment="Accept to established connections" \
    connection-state=established
add action=accept chain=ICMP comment="Time Exceeded" icmp-options=11:0 \
    protocol=icmp
add action=accept chain=input comment="Accept to related connections" \
    connection-state=related
add action=accept chain=input comment="Full access to SUPPORT address list" \
    src-address-list=support
add action=accept chain=ICMP comment="Echo reply" icmp-options=0:0 protocol=\
    icmp
add action=accept chain=ICMP comment="Destination unreachable" icmp-options=\
    3:0-1 protocol=icmp
add action=accept chain=ICMP comment=PMTUD icmp-options=3:4 protocol=icmp
add action=drop chain=ICMP comment="Drop to the other ICMPs" disabled=yes \
    protocol=icmp
add action=drop chain=ICMP comment="Drop to the other ICMPs - on ether1" \
    in-interface=ether1-privod protocol=icmp
add action=drop chain=input comment="Block DNS TCP" dst-port=53 in-interface=\
    ether1-privod protocol=tcp
add action=drop chain=input comment="Block DNS UDP" dst-port=53 in-interface=\
    ether1-privod protocol=udp
add action=accept chain=input comment="Accept DNS - UDP" disabled=yes port=53 \
    protocol=udp
add action=accept chain=input comment="Accept DNS - TCP" disabled=yes port=53 \
    protocol=tcp

Thank you in advanced.

So my guess was wrong, your firewall setup is very unusual to put it softly. I could understand that if router A was an ISP router with no NAT and you would avoid using connection tracking to save CPU, but since NAT is necessary at least for the connections to/from the internet, connection tracking must be active anyway, so there is little point in not using it to build a proper stateful firewall. A stateful firewall allows you to only use a complicated sequence of rules to handle the initial packet of each connection and let the subsequent packets of connections whose initial packet has been allowed to pass be handled by a single “accept established or related” rule at the beginning (top) of each chain in filter (input and forward in your case). So I’d say have a look at how a stateful firewall looks like (the default configuration of the SoHo models is a good inspiration) and consider adapting it to your needs by adding permissive rules specifying which source addresses/in-interfaces are allowed to initiate connections towards which destination addresses/out-interfaces.

This is your basic default firewall ruleset with a focus on only identifying needed traffic and dropping everything else.

/ip firewall-address list { using static dhcp leases mostly }
add address=admin-IP1 list=Authorized  comment="admin local desktop"
add address=admin-IP2 list=Authorized comment="admin local laptop"
add address=admin-IP3 list=Authorized comment="admin remote vpn" { if using wireguard etc.... }
/ip firewall filter
{Input Chain}
(default rules to keep)
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid
add action=accept chain=input comment="defconf: accept ICMP" protocol=icmp
add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
( admin rules )
add action=accept chain=input src-address-list=Authorized comment="Config Access"
---> Add any more allow input chain rules needed here <----
add action=accept chain=input comment="Allow LAN DNS queries-UDP" \ {and NTP *** services if required etc}
dst-port=53 in-interface-list=LAN protocol=udp
add action=accept chain=input comment="Allow LAN DNS queries - TCP" \
dst-port=53 in-interface-list=LAN protocol=tcp
add action=drop chain=input comment="drop all else"
{forward chain}
(default rules to keep)
add action=accept chain=forward comment="defconf: accept in ipsec policy" ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related
add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
(user rules)
add action=accept chain=forward comment="allow internet traffic" in-interface-list=LAN out-interface-list=WAN
-->  Add any more allowed forward chain rules required here <---
add action=accept chain=forward comment="port forwarding"  connection-nat-state=dstnat  disabled=yes { enable if required }
add action=drop chain=forward comment="drop all else"

Thank you for the advice and also for the sent “pattern” of the configuration. I agree that the firewall needs a makeover. The previous one was set up by a former colleague, then I modified it. However, for now, is it possible to recommend a simple rule (but not too general - as I stated) that will allow clients to access the internet, but at the same time there could be a rule that blocks access to clients (see code below)? I need to do it somehow for now before there is more time for a complete rebuild.

add action=drop chain=forward dst-address-list=ip_clients

Thank you very much in advance.

If you looked at the config provided its a very simple addition… focus on the user rules…

{forward chain}
(default rules to keep)
add action=accept chain=forward comment=“defconf: accept in ipsec policy” ipsec-policy=in,ipsec
add action=accept chain=forward comment=“defconf: accept out ipsec policy” ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment=“defconf: fasttrack” connection-state=established,related
add action=accept chain=forward comment=“defconf: accept established,related, untracked” connection-state=established,related,untracked
add action=drop chain=forward comment=“defconf: drop invalid” connection-state=invalid

(user rules)
add action=accept chain=forward comment=“allow internet traffic” in-interface-list=LAN out-interface-list=WAN
→ Add any more allowed forward chain rules required here <—
add action=accept chain=forward comment=“port forwarding” connection-nat-state=dstnat disabled=yes { enable if required }
add action=drop chain=forward comment=“drop all else”

You have two options.
A. BLOCK SELECTED USERS before allowing all LAN out to the internet
B. BLOCK THEM ON THE SAME LINE as allowing all LAN out to the internet

A.
(user rules)
add action=drop chain=forward comment=“prevent some users” src-address-list=ip_clients out-interface-list=WAN
add action=accept chain=forward comment=“allow internet traffic” in-interface-list=LAN out-interface-list=WAN
add action=accept chain=forward comment=“port forwarding” connection-nat-state=dstnat disabled=yes { enable if required }
add action=drop chain=forward comment=“drop all else”

B.
add action=accept chain=forward comment=“allow internet traffic” in-interface-list=LAN out-interface-list=WAN src-address-list=!ip_clients
add action=accept chain=forward comment=“port forwarding” connection-nat-state=dstnat disabled=yes { enable if required }
add action=drop chain=forward comment=“drop all else”

the single line basically reads allow all users from the LAN go out the WAN as long as their IP address is not (the one ones on the list).