Firewall rules for WLAN/LAN subnets only work in one direction

Hi,
I’ve set up separate subnets on my hap AC3 for LAN (ether2…ether5) and WLAN (wlan1…wlan2) using two bridges with addresses .88/24 (bridge) and .89/24 (bridge-ap). I’m trying to restrict any traffic flowing flowing between those subnets with forward rules:

/ip firewall
add action=reject chain=forward comment=\
    "wlan: reject traffic from LAN to AP clients" in-interface=bridge log=yes \
    out-interface=bridge-ap reject-with=icmp-network-unreachable
add action=reject chain=forward comment=\
    "wlan: reject traffic from AP clients to LAN" in-interface=bridge-ap log=\
    yes out-interface-list=!WAN reject-with=icmp-network-unreachable

The direction bridge → bridge-ap works as expected:

ping 192.168.88.254
Pinging 192.168.88.254 with 32 bytes of data:
Reply from 192.168.89.1: Destination net unreachable.

In the opposing direction however, pings are dropped (not rejected) and nmap scans work:

$ nmap -Pn 192.168.89.252
Starting Nmap 7.80 ( https://nmap.org ) at 2022-12-26 13:12 CET
Nmap scan report for 192.168.89.252
Host is up (0.033s latency).
Not shown: 999 filtered ports
PORT   STATE SERVICE
53/tcp open  domain

Nmap done: 1 IP address (1 host up) scanned in 4.87 seconds

Router export is attached. What am I doing wrong?
export.rsc (10.3 KB)

I assume this rule will match:

add action=drop chain=forward comment=\
    "docs: drop packets from LAN that do not have LAN IP" disabled=yes \
    in-interface-list=LAN log=yes src-address=!192.168.88.0/24

It machts against your 192.168.89.0/24-net as source. Any frames from .89.0/24 to .88.0./24 are dropped and not rejected.

Seriously recommend you modify your firewall rules as follows…

/ip firewall filter
{input chain}
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

add action=accept chain=input comment=“accept LAN traffic”
in-interface-list=LAN
add action=drop chain=input comment=“drop all else”

{forward chain}
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 hw-offload=yes
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

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

The rest is not required and not doing anything for you.
If you want to add Non RFC traffic do it in routes vice firewall rules.

/ip route
add blackhole disabled=no dst-address=10.0.0.0/8
add blackhole disabled=no dst-address=172.16.0.0/12
add blackhole disabled=no dst-address=169.254.0.0/16

(NOTE1: add more bogon addresses as you see fit.)
++++++++++++++

I say this because it appears to me you copied stuff not knowing what it really does for example in your list of bogons you include subnets which
covers your own private subnets so that is a big error in the config!!!
You also have a rule for capsman or other uses as a default rule in the input chain, nothing wrong with that, but then its not copacetic to have the other bogon in the config…

/ip firewall address-list
add address=0.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=172.16.0.0/12 comment=RFC6890 list=not_in_internet
add address=192.168.0.0/16 comment=RFC6890 list=not_in_internet
add address=10.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=169.254.0.0/16 comment=RFC6890 list=not_in_internet
add address=127.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=224.0.0.0/4 comment=Multicast list=not_in_internet
add address=198.18.0.0/15 comment=RFC6890 list=not_in_internet
add address=192.0.0.0/24 comment=RFC6890 list=not_in_internet
add address=192.0.2.0/24 comment=RFC6890 list=not_in_internet
add address=198.51.100.0/24 comment=RFC6890 list=not_in_internet
add address=203.0.113.0/24 comment=RFC6890 list=not_in_internet
add address=100.64.0.0/10 comment=RFC6890 list=not_in_internet
add address=240.0.0.0/4 comment=RFC6890 list=not_in_internet
add address=192.88.99.0/24 comment=“6to4 relay Anycast [RFC 3068]” list=
not_in_internet

Solved. The issue was the LAN client configuration. The client connected to a Wireguard VPN with AllowedIPs = 0.0.0.0/0, and the routing tables were not updated for 192.168.89.0/24 (WLAN subnet). All packets thus went through the VPN, leading to my mistaken belief of a firewall misconfiguration.


Seriously recommend you modify your firewall rules as follows…

I took the default configuration and extended it with https://help.mikrotik.com/docs/display/ROS/Building+Your+First+Firewall. The proposed modifications to the default look a bit easier to extend, but otherwise equivalent. The NetBIOS rules also block any outgoing traffic from LAN clients forwarded to WAN. I like to have the not_in_internet rules in /ip filter, because unlike /ip route it allows logging.


I say this because it appears to me you copied stuff not knowing what it really does for example in your list of bogons you include subnets which
covers your own private subnets so that is a big error in the config!!!

Traffic between clients in the same subnet isn’t forwarded:

$ ip route
default via 192.168.88.1 dev eno1 proto dhcp metric 100 
169.254.0.0/16 dev eno1 scope link metric 1000 
192.168.88.0/24 dev eno1 proto kernel scope link src 192.168.88.254 metric 100

Furthermore, traffic between different subnets configured on the hap AC3 does not have WAN as destination. The non_in_internet rules then apply to traffic to unknown subnets. Demonstration on the LAN client (now with VPN disabled):

$ traceroute 192.168.89.252  # rejected (matched rule: /ip firewall add action=reject chain=forward in-interface=bridge log=yes out-interface=bridge-ap reject-with=icmp-network-unreachable)
traceroute to 192.168.89.252 (192.168.89.252), 30 hops max, 60 byte packets
 1  router.lan (192.168.88.1)  0.927 ms  0.875 ms  0.832 ms
 2  router.lan (192.168.88.1)  0.790 ms !N  0.747 ms !N  0.705 ms !N

$ traceroute 192.168.1.1 # dropped (matched rule: /ip firewall add action=drop chain=forward dst-address-list=not_in_internet log=yes out-interface-list=WAN)
 traceroute to 192.168.1.1 (192.168.1.1), 30 hops max, 60 byte packets
 1  router.lan (192.168.88.1)  0.932 ms  0.880 ms  0.838 ms
 2  * * *
 3  * * *
 4  * * *
 5  * * *
 6  * * *
 7  * * *
 8  * * *
 9  * * *
10  * * *
11  * * *
12  * * *
13  * * *
14  * * *
15  * * *
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  * * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
30  * * *

One place I noticed this were programs making requests to 192.168.1.1 (presumably for UPnP), which were subsequently dropped.

Make all the reasons you went, its all BS…
For example the proper way to block lan clients to the input chain is simple.

add chain=input action=accept in-interface-list=LAN src-address=list=authorized { to allow admin access to the router for config purposes )
add chain=input action=accept in-interface-list=LAN dst-port=53 protocol=tcp ( to allow all user access to DNS services for example )
add chain=input action=accept in-interface-list=LAN dst-port=53 protocol=udp
add chain=input action=drop comment=“drop all else”

Whatever you say buddy. Engaging with you was a waste of time from the start. The input and forward chain are completely different things.

Advice is free, take it any way you want.