Option "!" Does not work in rules with a drop action.

Hi! This does not work on my router. Collected a simple circuit in GNS3. There are 2 CHR with such settings. Ros 6.48.2

Based on the documentation on: help.mikrotik
Brief firewall filter rule explanation:

  • drop incoming packets that are not NAT`ed, ether1 is public interface, log attempts with “!NAT” prefix;

The rule that should deny everything except DST NAT does not work.

# r1 | ether1 - 172.16.5.231/28 (isp) | bridge1 - 172.16.10.1/24 (lan)
/ip firewall filter
add action=accept chain=forward comment="Establishet, Related" connection-state=established,related
add action=accept chain=input connection-state=established,related
add action=drop chain=forward comment="DNAT con state ISP -> LAN" connection-nat-state=!dstnat in-interface=ether1 out-interface=bridge1
add action=drop chain=forward comment="Drop all not allowed"
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
add action=dst-nat chain=dstnat in-interface=ether1 to-addresses=172.16.10.254
# pc1 | 172.16.10.254/24 GW 172.16.10.1

# r2 | ether1 - 172.16.5.232/28 (isp) | bridge1 - 172.16.11.1/24 (lan)
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
# pc2 | 172.16.11.254/24 GW 172.16.11.1

pc2 → ping 172.16.5.231 : WORK

add action=accept chain=forward comment="DNAT con state ISP -> LAN" connection-nat-state=dstnat in-interface=ether1 out-interface=bridge1

pc2 → ping 172.16.5.231 : NOT WORK

add action=drop chain=forward comment="DNAT con state ISP -> LAN" connection-nat-state=!dstnat in-interface=ether1 out-interface=bridge1

Another example. r1 - instead of the 3rd rule.
These two rules should equally allow.

/ip firewall filter
add action=accept chain=forward dst-address=!172.16.10.253 in-interface=ether1 out-interface=bridge1 - work
/ip firewall filter add
action=drop chain=forward dst-address=!172.16.10.254 in-interface=ether1 out-interface=bridge1 - not work

Hence the conclusion that “!” works only with accept rules.
This is how it should be or is it a mistake??

Suggest you un-pretzel yourself and make clean rules.
Like this combination which does everything you want and more
(1) add action=accept chain=forward comment=“allow port forwarding”
connection-nat-state=dstnat connection-state=new in-interface-list=WAN
(2) add action=drop chain=forward comment=“drop all else”

In other words I have no intention to delve into the mess created by your config nor I imagine too many people wish to.

THe default rules work equally well, but most prefer a concept of only allow what you explicitly want and drop all else whereas the default rules
are more oriented towards blocking some things and allowing everything else (whatever it may be).
add action=drop chain=forward comment=“defconf: drop all from WAN not DSTNATed”
connection-nat-state=!dstnat connection-state=new in-interface-list=WAN

The default rule is basically stating drop everything from the WAN that is not in the form of a valid destination attempt to the LAN (in other words there is a dst nat rule in the config with the destination port that matches a destination port in the incoming traffic.

I prefer the cleaner more direct approach that doenst try to combine rules, which states allow dst nat packets that match dst nat rules and then the second rule which states drop ALL other traffic (be it from WAN, LAN or Mars).

In summary, the rules work as they are applied. If something is not working for you its because of a configuration error on your part or a lack of understanding on your part.
If you had not posted all the gobblity gook confusing wording and had simply stated this one line.
My config seems to allow port forwarding AND other WAN traffic which I do not understand!
Then posted the config
/export hide-sensitive file=anynameyouwish

I would have likely found the issue and pointed it out LOL.

This symbol (!) Means not ..
(1) add action=accept chain=forward connection-state=established,related
(2) add action=drop chain=forward connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
(3) add action=drop chain=forward in-interface-list=WAN comment=“drop all else”
Should this work in your opinion?
(UPDATED)

No, it shouldn’t.
Rule (2) is useless - all traffic that it drops will be dropped anyway by rule (3).
And rule (3) drops everything - including traffic originated from LAN.

This:

(1) add action=accept chain=forward connection-state=established,related
(2) add action=drop chain=forward connection-nat-state=!dstnat connection-state=new in-interface-list=WAN

Is more or less equal to this:

(1) add action=accept chain=forward connection-state=established,related
(2) add action=accept chain=forward in-interface-list=!WAN
(2) add action=accept chain=forward connection-nat-state=dstnat connection-state=new in-interface-list=WAN
(3) add action=drop chain=forward

Both ways should work.

The updated version shouldn’t work too (but now at least traffic from LAN won’t be dropped): rule (2) is still useless - all traffic from WAN will be dropped by rule (3) and not dropping some of it in rule (2) doesn’t make a difference.

The original example on help
https://help.mikrotik.com/docs/display/ROS/Building+Your+First+Firewall
have more rules, if you remove some rule and add others, the appearance of (2) is useless is because you remove the reason for what (2) exist!!!
And rule (3) on example not exist.

original example:

/ip firewall filter
add action=fasttrack-connection chain=forward comment=FastTrack connection-state=established,related
(1) add action=accept chain=forward comment="Established, Related" connection-state=established,related
add action=drop chain=forward comment="Drop invalid" connection-state=invalid log=yes log-prefix=invalid
add action=drop chain=forward comment="Drop tries to reach not public addresses from LAN" dst-address-list=not_in_internet in-interface=bridge1 log=yes log-prefix=!public_from_LAN out-interface=!bridge1
(2) add action=drop chain=forward comment="Drop incoming packets that are not NAT`ted" connection-nat-state=!dstnat connection-state=new in-interface=ether1 log=yes log-prefix=!NAT
add action=jump chain=forward protocol=icmp jump-target=icmp comment="jump to ICMP filters"
add action=drop chain=forward comment="Drop incoming from internet which is not public IP" in-interface=ether1 log=yes log-prefix=!public src-address-list=not_in_internet
add action=drop chain=forward comment="Drop packets from LAN that do not have LAN IP" in-interface=bridge1 log=yes log-prefix=LAN_!LAN src-address=!192.168.88.0/24

The problem is this mess you do than the help example

Port forwarding won’t work!

(1) add action=accept chain=forward connection-state=established,related
(2) add action=drop chain=forward connection-nat-state=!dstnat connection-state=new in-interface-list=WAN

Port forwarding will work! But the second rule is not needed for port forwarding to work.

(1) add action=accept chain=forward connection-state=established,related
(2) add action=accept chain=forward in-interface-list=!WAN
(3) add action=accept chain=forward connection-nat-state=dstnat connection-state=new in-interface-list=WAN
(4) add action=drop chain=forward in-interface-list=WAN

Sure it will. That’s the part of the default config, and it works perfectly fine.

Yes, it is not needed for port forwarding, but it bears part of the “meaning” of the initial rule (2) (with !dstnat).

Meant this: +(3)

(1) add action=accept chain=forward connection-state=established,related
(2) add action=drop chain=forward connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
(3) add action=drop chain=forward in-interface-list=WAN

As I already said, no surprise it won’t work - because of the rule (3), not because of rule (2).
Remove rule (3) and it will work as expected.

Got it, thank you all for the clarification!