Linux firewalld zones logic and priority

I'm trying to understand the logic behind the Linux firewalld zones, and the way they are evaluated.

  1. To my understanding, a zone is defined as a list of interfaces and IP ranges, which allow/deny rules can be applied on. Is this correct? For a zone that includes an interface and an additional IP range. Do services that are allowed for this zone will be allowed for the IP range even if the traffic will reach the machine from IP within that range, but through a different interface?

  2. In what order zones are evaluated? What will happen to incoming traffic that is matched by two (possibly contradicting) zones? For example, zone "Z1" that allows nfs to the machine from a given interface, and zone "Z2" that denies all incoming traffic from an IP. What will happen to a NFS traffic that reaches the machine through the interface defined in "Z1" but from the IP defined in "Z2"?


Solution 1:

  1. Zone is just a layer of abstraction based on netfilter. In language of netfilter rules its set of chains which give you this feeling as end user of firewalld that your packets are within some "zone". You can always check the exact behaviour of zone running:

    iptables -L

  2. Order in which firewalld matching packets is:

    • direct rules
    • routing to zones based on source ip
    • routing to zones based on interface packets are coming from

This basically means that if final destination for packets is not decided by direct rules they will enter some zone. First firewalld is trying to route them based on source ip. If there is no match firewalld will attempt to route them based on interface they came in. If this also fails they enter the default zone. In case you have more zones set with source ip and these ip ranges overlap zone which source rule was added as first will win because its rule will be first checked for match.

Examples:

lets have system with interfaces:

  • eth0 with ip address 192.168.0.1/24
  • eth1 with ip address 192.168.100.1/24

Firewalld setting 1:

firewall-cmd --zone=home --add-interface=eth0
firewall-cmd --zone=internal --add-source=192.168.0.0/16

Packets coming from address 192.168.0.2 via eth0 will be routed into the internal zone.

Firewalld setting 2:

firewall-cmd --zone=internal --add-source=192.168.0.0/16
firewall-cmd --zone=home --add-source=192.168.0.2/32

Packets coming from 192.168.0.2 will be routed into the internal zone again. It works this way because firewalld is adding source rules for routing zones one by one in order we are running related commands.