Rulesets, chains, and rule evaluation¶
A ruleset is composed of chains, rules, and matchers:
A chain is a set of rules to match the packet against. It will use the rules to filter packets at a specific location in the kernel: a hook. Chains also have a policy, which specifies the action to take with a packet once it went through all the rules.
A rule defines an action to take on a packet if it matches all its matchers.
A matcher is a matching criterion within a rule. It can match a specific protocol, a specific field, a network interface…
Let’s see how they work together.
How does a rule match?¶
A rule contains one or more matchers, and the packet has to match all of them. For example, a rule defined with an IPv4 source address matcher and a TCP destination port matcher will only match the TCP packets coming from this address and sent to this port.
What if you want to match one address or another? Adding two ip4.saddr matchers to the same rule won’t work: a packet only has one source address, so the rule would never match. Use two rules, or a set. A set contains multiple elements of the same type, and the rule will match if the packet’s data is one of them. A named set is also defined outside of the rule: you can use it from multiple rules, and change its content without writing the whole chain again.
The order matters¶
The rules are processed in the order they are defined in the chain:
If every matcher of the rule matches the packet, it means the rule itself matched the packet: its
log,counter, andmarkactions are executed, then its verdict is applied.If at least one of the matchers doesn’t match the packet, bpfilter stops processing the current rule and continues with the next one.
What happens next depends on the verdict of the rule that matched:
ACCEPTandDROPstop the processing: the packet is accepted or dropped, and the subsequent rules won’t see it.REDIRECTstops the processing too, and sends the packet to another interface. Not all the hooks support it.NEXTstops the processing, and lets the next BPF program attached to the hook decide. Only TC hooks make a difference betweenNEXTandACCEPT.CONTINUEdoesn’t stop anything: the packet goes on to the next rule.
Hence, the rules’ order matters. If a rule accepting every TCP packet comes first, a rule dropping the TCP packets sent to port 22 defined after it will never match. CONTINUE is useful if you want to count or log packets before another rule decides what to do with them. It also means a packet can be counted more than once.
And what about the policy?¶
Once the packet went through all the rules, if none of them stopped the processing, the chain’s policy is applied. Use ACCEPT if your rules define the packets you want to block, and DROP if they define the packets you want to allow.
Keep in mind a chain only decides for its own hook. A packet accepted by your chain can still be dropped later by another BPF program, or by another firewall.
Not everything is a packet¶
Most hooks process packets, but the BF_HOOK_CGROUP_SOCK_ADDR_* hooks are different: they are called when a process calls connect(), or sendmsg() on a UDP socket. There is no packet yet, so fewer matchers are available, and the counters will count calls instead of packets and bytes.
See Where filtering happens to choose a hook, Rules, actions, and verdicts for the details about actions and verdicts, and Sets for the sets syntax.