How does (my) firewalling/routing work?

Hi,

I’m new to the Mikrotik and came here as a long time FortiGate user. I would say I would know how firewall policies work, but I don’t really know what is happening on my Mikrotik.
I’m certain this is something weird and simple I’m not looking at. I tried various things, but one by one. This request is not a “please make it work”, but rather “why does it work”.
This is an RB5009. It has a Unifi AP (replaced a FortiAP) on port1.
I have a server on port8 and one Linux box (I called it “Playstation”) behind the AP and another behind port7 (called “Mars”). The Router is online with an uplink through the ISP-provided router (since I have no choice).
Playstation, Saturn and Mars are all in different /24 subnets.

Now during some setup and testing, this thing runs fine and fast. I however was then asking myself how my “Playstation” is able to connect to my server. I intended to mount an NFS drive, which worked fine. However after the migration from FortiGate to Mikrotik I didn’t set up a firewall policy for this. Asking myself how these were communicating, I started testing.

Many tests later I basically disabled all except one firewall policy (which is to input chain). 4 DENY policies remain.
The export output doesn’t contain the “enable” state, excuse my beginners output, there may be better ways. I add manually a D, to show I disabled them and a number.

/ip firewall filter
00: D add action=accept chain=forward comment="DNS to internal" disabled=yes dst-port=53 in-interface-list=all log=yes out-interface=8_Saturn protocol=udp
01: D add action=accept chain=forward comment="DNS to external" disabled=yes dst-address-list=DNS dst-port=53 in-interface=8_Saturn log=yes out-interface=Internet protocol=udp
02: D add action=drop chain=forward comment="DNS deny else" disabled=yes dst-port=53 in-interface=all-ethernet log=yes out-interface-list=WAN protocol=udp
03: D add action=accept chain=forward comment=AP-controller disabled=yes in-interface=1_AP log=yes out-interface=Internet
04: D add action=accept chain=forward comment="Mars to Internet" disabled=yes in-interface=7_Mars log=yes out-interface-list=WAN src-address-list=Mars
05: D add action=accept chain=forward comment="Saturn to WAN" disabled=yes in-interface=8_Saturn log=yes out-interface-list=WAN src-address-list=Saturn
06: D add action=accept chain=forward comment="Playstation to Saturn" disabled=yes dst-address-list=Saturn src-address-list=Playstation
07: D add action=accept chain=forward comment="Scanner to Saturn" disabled=yes dst-address-list=Saturn in-interface=5_Print_Scan out-interface=8_Saturn
08: D add action=accept chain=forward comment="LAN/AP to Printer" disabled=yes dst-address-list="" in-interface-list=LAN_AP log=yes out-interface=5_Print_Scan src-address-list=""
09: D add action=fasttrack-connection chain=forward comment=fasttrack connection-state=established,related disabled=yes hw-offload=yes
10: D add action=accept chain=input comment="defconf: accept ICMP" disabled=yes protocol=icmp
11: add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
12: add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
13: add action=drop chain=forward comment="drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN
14: add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid in-interface-list=WAN
15: add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=WAN
16: D add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" disabled=yes dst-address=127.0.0.1 log=yes
17: D add action=accept chain=forward comment="defconf: accept in ipsec policy" disabled=yes ipsec-policy=in,ipsec
18: D add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked disabled=yes
19: D add action=accept chain=forward comment="defconf: accept out ipsec policy" disabled=yes ipsec-policy=out,ipsec
20: D add action=accept chain=input connection-state=established,related,new,untracked disabled=yes dst-limit=1,5,dst-address/1m40s fragment=no in-interface-list=!WAN ipv4-options=any limit=1,5:packet time=0s-1d,sun,mon,tue,wed,thu,fri,sat ttl=equal:0

I should be online with Mars through policy #04, but it is disabled. Mars is online
Saturn should be online through policy #05, but it is disabled. Saturn is online.
Playstation should be online through policy #03, but it is disabled. Playstation is online. My phone is also online through the same policy.
Playstation should be able to reach Saturn through policy #06. It didn’t matter that policy #06 was created, because they could communicate bidirectional even before that policy in one direction was created.

Notes (not sure if they’re of importance and if I understand it correct; happy to be corrected):

  • Mikrotik is the DNS server for the whole network, it works well. This would basically not concern the forward chain, but the input chain. The DNS servers option in IP/DNS had been enabled “Allow Remote Requests”.
    a) I removed the bridge setup completely as I didn’t really see the need in it. I don’t intend using the router as switch or bridge in any way.
    b) I have the switch configuration there, but cannot get rid of it. All ports are member of the “Switch1”.
    c) Even they would be happily switching stuff, I don’t see how the different subnets are able to reach each other. The Mikrotik is the router and a tracepath from one Linux to another confirms that.
    d) You can see interface/address lists, these do not contain what they’re not supposed to.
    e) I’m aware of the basic packet flow here: https://help.mikrotik.com/docs/spaces/ROS/pages/328227/Packet+Flow+in+RouterOS but I believe the MT is routing, as it should, I don’t see why it does.
    I understand that interface, interface lists and address lists in the policy are equally valued. The presence of one makes this a mandatory criterion to match.
    f) Coming from FortiGate, I did have the notion to reboot the Mikrotik.
    g) A sniffer on MT-CLI (ip-address=192.168.200.200 as filter) shows me also that a packet is ingressing and egressing where it should be:
7_Mars     7.661  536  <-   A0:29:19:33:EA:30  D4:01:C3:B7:FD:68  192.168.111.2:57596     
8_Saturn   7.661  537  ->   D4:01:C3:B7:FD:69  D4:3D:7E:4F:0C:01  192.168.111.2:57596     
8_Saturn   7.662  538  <-   D4:3D:7E:4F:0C:01  D4:01:C3:B7:FD:69  192.168.200.200:22 (ssh)
7_Mars     7.662  539  ->   D4:01:C3:B7:FD:68  A0:29:19:33:EA:30  192.168.200.200:22 (ssh)

8_Saturn   64.937  663  <-   D4:3D:7E:4F:0C:01  D4:01:C3:B7:FD:69  192.168.200.200:8080 (http-alt)
1_AP       64.938  664  ->   D4:01:C3:B7:FD:62  28:70:4E:4B:46:D9  192.168.200.200:8080 (http-alt)

The first set is plain SSH from Mars to Saturn.
The second is the unifi AP communicating with its controller on Saturn. Confirms me thinking that the MT is receiving a packet and routing it to its other connected interface. It seems to skip FW policies, for all I can guess.

So what am I not seeing here? Why am I online?

Thanks in advance for just reading that post.

Best regards,

carrotik

Where is your default-drop (eg. on your forwarding-chain) ? As you move sequentially through the rules top-bottom finally the packet will be allowed unless explicitly blocked.
I don’t see that in your rules.

Mine looks like this. So no references to any interfaces, just across the whole forwarding-chain.

add action=drop chain=forward comment=“Drop Anything Else” log=yes log-prefix=IP4-FWD-DEFAULT-DROP


Can you print your NAT rules ? They are responsible for actual Internet access so…

Only as a side note, your exported entries are just fine, “disabled=yes” is Mikrotik’s way to explicit the enable state and your D marked lines sport “disabled=yes” just fine.

The advised approach, as jvanhambelgium stated, is to have a set of explicit rules targeting the traffic that you want to allow and a final rule dropping all else.

It is a good habit to “group” the rules by their chain, i.e. first all “input”, then all “forward” (each one having its own “drop all else” rule as last one) as they are then easier to read/review.

If you prefer, it is safer to start with a basic setup i.e. like:
/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” disabled=no 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=“LAN access” in-interface-list=LAN
add action=drop chain=input comment=“drop all other input”
#forward chain
add action=accept chain=forward comment=“defconf: accept established,related, untracked” connection-state=established,related,untracked
add action=fasttrack-connection chain=forward comment=“defconf: fasttrack” connection-state=established,related hw-offload=yes
add action=drop chain=forward comment=“drop all other forward”

and then adding before the last rule in each chain the desired accept rules.

Be careful with rules and their comments using the ! operator can sometimes help, this one:
add action=drop chain=input comment=“defconf: drop all not coming from LAN” in-interface-list=WAN
is not actually doing what is in the comment, this one will:
add action=drop chain=input comment=“defconf: drop all not coming from LAN” in-interface-list=!LAN

If modifying (for whatever reason) a “defconf:” rule, remember to always change the comment beginning (from defconf to - say - myconf) otherwise you might find yourself believing that a rule is the defconf one while it is not.

Edit: added rule “add action=accept chain=input comment=“LAN access” in-interface-list=LAN” previously missing and potentially dangerous (locking oneself out), thanks anav.

To add to jaclaz, slight modification, NEVER put the drop all rule onto the input chain until the very end.… Basically ensuring you as admin or the LAN has access to config the router so I would amend his list, to be safe.

#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” disabled=no protocol=icmp
add action=accept chain=input comment=“defconf: accept to local loopback (for CAPsMAN)” dst-address=127.0.0.1
add action=drop chain=input comment=“drop all other input”
#forward chain
add action=accept chain=forward comment=“defconf: accept established,related, untracked” connection-state=established,related,untracked
add action=fasttrack-connection chain=forward comment=“defconf: fasttrack” connection-state=established,related hw-offload=yes
add action=drop chain=forward comment=“drop all other forward”

RECOMMENDED DEFAULT START
/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” disabled=no 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=“LAN access” in-interface-list=LAN
#forward chain
add action=accept chain=forward comment=“defconf: accept established,related, untracked” connection-state=established,related,untracked
add action=fasttrack-connection chain=forward comment=“defconf: fasttrack” connection-state=established,related hw-offload=yes
add action=drop chain=forward comment=“drop all other forward”

Then ON the input chain side, if you now add the drop all rule, you wont be locked out!!

As a next step, there is no need to allow the entire LAN full access to the input chain. Its not the optimal good security practice.
They only need access to services like DNS. SO add some user rules.

add action=accept chain=input comment=“full lan access” in-interface-list=LAN
add action=accept chain=input comment=“users to services” in-interface-list=LAN dst-port=53 protocol=udp
add action=accept chain=input comment=“users to services” in-interface-list=LAN dst-port=53 protocol=tcp

I
The next step in logic, is to limit full access only to the admin, to do this we identify all the IP addresses that the admin uses and then make those IPs static/fixed in DHCP leases.
/firewall address-list
add address=192.168.88.3 list=AUTHORIZED comment=“admin desktop wired”
add address=192.168.88.4 list=AUTHORIZED comment=“admin laptop wired”
add address=192.168.88.4 list=AUTHORIZED comment=“admin laptop WIFI”
add address=192.168.88.5 list=AUTHORIZED comment=“admin smartphone/ipad WIFI”
add address=10.10.10.2 list=AUTHORIZED comment=“remote admin laptop VPN”

etc…

Then you are ready to modify the rule allowing LAN full access to only the admin IPs with full access:
add action=accept chain=input comment=“admin access” src-address-list=AUTHORIZED
add action=accept chain=input comment=“users to services” in-interface-list=LAN dst-port=53 protocol=udp
add action=accept chain=input comment=“users to services” in-interface-list=LAN dst-port=53 protocol=tcp

Once confirmed you can access the router as admin, it is safe to add the BLOCK all rule at the end of the input chain.

anav, you probably have a typo, those “AUTHORIZED” and “DNS/port 53” rules should be on input chain, not forward, right? :confused:

Yolks on me, much thanks!!!

You are welcome :slight_smile: , but you still have to correct the first three.
(I am worrying about people that may copy and paste these rules without critically checking them)

MF, hahah done!

Wow, this is more responses than I expected. I believe the first comment is already what I’m missing. FortiGate has an implicit deny rule that is always there. Logic would fit very well to behave like that… darn.
The routerOS doesn’t have it, unless hidden. It has an active drop on invalid packets on the forwarding chain. The implicit deny I’d expect to read to drop “new” sessions only, but I don’t have such a rule.

I had already experienced locking myself out when removing interfaces of the bridge. I’ll work on that later when wife is in bed. I want to stay married.

Thanks!

I can relate !!!

If you are doing multiple vlans and vlan-filtering on a single bridge, then to not get kicked out of the router from time to time,
suggest using one etherport for an OffBridge access.
If interested let me know.

Well, JFYI, if you happen to accidentally cut off internet, it is unlikely that the marriage will break up :astonished: , the outcome is usually either that of wife not talking to you for several days or deciding - since there is nothing better to do - to actually talk to you for several days, it depends :wink: .
:laughing:

Black Friday sales are coming soon, he wants to be on the good side… How much better the house internet will be with a CCR2004 router.

Usually I do the reverse: the first thing I do is insert one rule giving me access. THEN I start fiddling with the firewall. And only AFTER I validate that the rule giving me access works.
Of course, “safe mode” is your friend. Always.

Well, that was it. Not my marriage, but the implicit deny rule. Now this box behaves like I expect it to and I can enable policies to allow traffic; instant reaction, lovely. Basically, I ran this box as a security nightmare (or closer to normalcy…) for some days. Better check what the server is doing now.
Thank you guys. There’s a lot of wisdom in the posts already made, I’ll go through those, there might be more to discover.