Firewall, why is last rule of forward filter to it's own zone?


I'm configuring OpenWRT firewall with a couple zones, some zones I restrict on what they can do.

My current firewall config is, General Settings: input reject, output accept, forward reject. I'll take one restrictive zone as example, I call it guests. This one is also configured with input reject, output acept and forward reject. In the traffic rules I've defined targets it can connect to and that it's allowed to have dns and dhcp from openwrt. It works good.

My question is about how openwrt has setup the firewall. The chain it follows to get to reject policy is FORWARD -> zone_guests_forward and as reject rule it has zone_guests_dest_REJECT where it logs and rejects based on that traffic being outputted to the zone interface. How I see it, it enters a chain based on his input interface (This is expected) and for the reject part the firewall only matched on the output interface beining the interface of the zone itself. I don't believe openwrt would ever forward traffic back to it's own zone, because alle traffic from guests to guests stays on the L2 segment in the network.
Rejecting of traffic is based on the final rule in the FORWARD chain (reject) because of no prior hits

My expectation would be if forwarding traffic is rejected as policy in openwrt, the rejecting for a single zone would be not filtered on an outgoing interface. The last rule in chain zone_guests_forward should be zone_guests_src_REJECT instead of dst_REJECT

Is this a bug? Or am I perhaps misunderstanding how the firewall is working?

Relevant /etc/config/firewall config:

config defaults
        option output 'ACCEPT'
        option synflood_protect '1'
        option input 'REJECT'
        option forward 'REJECT'

config zone
        option name 'guests'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'guests'
        option log '1'

config rule
        option target 'ACCEPT'
        option dest_port '53 67 68'
        option name 'DNS, DHCP Allow: guests'
        option src 'guests'

# config rules to only go to certain fixed ip addresses 

You're half right here... OpenWrt (and all routers) will not forward traffic on the same network back to itself because that traffic stays on L2 and thus doesn't go through the firewall. However, in a zone based firewall, you can assign multiple networks to the same zone. So you could have 3 guest networks that have the same general restrictions and are thus assigned to a guest firewall zone. The global firewall rule for that zone that would determine the inter-VLAN routing between those guest networks is the Forward rule. If set to accept, the multiple guest networks would be able to connect to each other. If drop/reject, it would not be possible.

You can do the same global zone allowance/restriction via the traffic rules, but you could alternatively create a more granular rule -- for example, maybe guest1 can initiate connections to guest2, but not the other way around, and guest3 is totally isolated. For that, you might set the global zone forward rule to drop, then accept a traffic rule that accepts source guest1 (in network notation) to destination guest2 (also in network notation).

The difference here is that we're talking about zones versus networks. Zones can contain multiple networks.

1 Like

The multiple interfaces 1 zone scenario I had not in mind, it makes more sense.

The first issue I encountered was there was no logging when a packet should be rejected when forwarding. The zone config is set to log packets. I see that all rejected packets in input are logged, but rejected forward packets not. Here I found the reject chain was filtering on the outgoing interface. Traffic to other interfaces would continue in iptables and only be reject by the global rule (without any possibility of logging). Rejected forwarded packets in the same zone is done as you explain.

In my view if I define a zone with a forward reject, I expect toreject all forwards on that point independend of the global settings.

I'm not exactly following your problem statement here... maybe you can give specific examples and show your configuration (/etc/config/firewall)

The global "Forward" control only applies to multiple networks in the same zone. If you are talking about inter-zone forwards, those are controlled separately.

EDIT: For clarity, the global forward control I am referring to is the zone-global, not the overall global. Maybe there I should have used a different word than global, but I'm not sure if it would be 'local' in this case.

You have only one interface in guest zone, so you cannot have any intra-zone forwarding rejected to see some logs.
If you had guest1 and guest2 interfaces in guest zone and one host in guest1 tried to access a host in guest2, then you'd see the rule working.

Regarding Global FORWARD, this applies to:

  1. Interfaces not belonging to any zone
  2. Inter-zone

The default is to REJECT globally, therefore interfaces not belonging to a zone are not allowed to forward anywhere, and you need to add forwardings to explicitly allow unidirectional inter-zone traffic, e.g lan->wan, but not wan->lan.

1 Like