FIREWALLD.DIRECT(5)
π firewalld.direct β the direct config file π
okay bestie, sit down, hydrate, because we're talking about firewalld.direct, aka the manual page for the firewalld direct configuration file. this one's the "I know exactly what I'm doing with iptables" page. it's giving expert mode. it's giving "I read the netfilter docs for fun." let's get into it π«Ά
β¨ NAME β¨
firewalld.direct β the firewalld direct configuration file. that's the whole name. short, sweet, iconic π
π SYNOPSIS π
/etc/firewalld/direct.xml
that's the file. that's the vibe. one path, all the power π
π DEPRECATED π
bestie. listen. the direct interface has been deprecated. it will be removed in a future release. it is superseded by policies β go look at firewalld.policies(5) instead.
not me crying a little. it's fine. it's fine. (it's not fine.) π
π DESCRIPTION π
okay so direct configuration gives you a more direct access to the firewall. raw, unfiltered, no middleman. but β and this is the part where I hold your hand β it requires you to already know basic ip(6)tables/ebtables concepts, like:
- table β
filter/mangle/nat/... - chain β
INPUT/OUTPUT/FORWARD/... - commands β
-A/-D/-I/... - parameters β
-p/-s/-d/-j/... - targets β
ACCEPT/DROP/REJECT/...
direct configuration should be used only as a last resort when it's genuinely not possible to use firewalld.zone(5). like, last resort last resort. try the other doors first, bestie πͺβ¨ also, see also Direct Options in firewall-cmd(1).
a firewalld direct configuration file contains information about permanent direct chains, rules and passthrough ...
here's the structure of a direct configuration file, copy it exactly, don't freestyle it:
<?xml version="1.0" encoding="utf-8"?>
<direct>
[ <chain ipv="ipv4|ipv6|eb" table="table" chain="chain"/> ]
[ <rule ipv="ipv4|ipv6|eb" table="table" chain="chain" priority="priority"> args </rule> ]
[ <passthrough ipv="ipv4|ipv6|eb"> args </passthrough> ]
</direct>
π direct π
the mandatory start and end tag that defines the direct. this tag can only be used once in a direct configuration file. no attributes for direct. none. zero. it's just there to hold everything together like a good bestie π
π¦ chain π¦
an optional empty-element tag, and you can use it several times. it's how you define names for additional chains. a chain entry has exactly three attributes:
ipv="ipv4|ipv6|eb"β the IP family where the chain will be created. can be eitheripv4,ipv6oreb.table="table"β the table name where the chain will be created. this can be one of the tables usable for iptables, ip6tables or ebtables. for the possible values, see the TABLES section in theiptables,ip6tablesorebtablesman pages.chain="chain"β the name of the chain that will be created. please make sure there's no other chain with this name already. seriously. please. π
and bestie, remember to add a rule or passthrough rule with an --jump or --goto option to connect the chain to another one. a chain floating out there with no connection is giving main character with no plot. connect her π€
β rule β
an optional element tag and can be used several times. it adds rules to a built-in or added chain. a rule entry has exactly four attributes:
ipv="ipv4|ipv6|eb"β the IP family where the rule will be added. can be eitheripv4,ipv6oreb.table="table"β the table name where the rule will be added. one of the tables usable for iptables, ip6tables or ebtables. for the possible values, see the TABLES section in theiptables,ip6tablesorebtablesman pages.chain="chain"β the name of the chain where the rule will be added. this can be either a built-in chain or a chain created with thechaintag. if the chain name is a built-in chain, then the rule will be added tochain_direct, else the supplied chain name is used.chain_directis created internally for all built-in chains to make sure the added rules do not conflict with the rules created by firewalld. she's a buffer zone. she's a peacekeeper. we love her ποΈpriority="priority"β used to order rules. priority0means add the rule on top of the chain, and with a higher priority the rule gets added further down. rules with the same priority are on the same level and the order of those rules is not fixed and may change. so if you need one rule to land after another, use a low priority for the first and a higher one for the following. don't leave it to fate, bestie, fate is messy π
the args can be any arguments of iptables or ip6tables that do not conflict with the table or chain attributes.
π§ passthrough π§
an optional element tag and can be used several times. it adds rules to a built-in or added chain. a rule entry has exactly one attribute:
ipv="ipv4|ipv6|eb"β the IP family where the passthrough rule will be added. can be eitheripv4,ipv6oreb.
the args can be any arguments of iptables or ip6tables.
the passthrough rule gets added to the chain directly. there is no mechanism like for the direct rule above. so you, the user of the passthrough rule, have to make sure there's no conflict with the rules created by firewalld. it's just you out here. no safety net. no chain_direct. be careful πΈ
β οΈ CAVEATS β οΈ
depending on the value of FirewallBackend (see firewalld.conf(5)) direct rules behave differently in some scenarios. buckle up, this is the spicy section πΆοΈ
π₯ Packet accept/drop precedence π₯
due to implementation details of netfilter inside the kernel, if FirewallBackend=nftables is used, direct rules that ACCEPT packets don't actually cause the packets to be immediately accepted by the system. those packets are still subject to firewalld's nftables ruleset. basically: there are two independent firewalls and packets must be accepted by both (iptables and nftables). as an aside, this scenario also occurs inside of nftables (again, due to netfilter) if there are multiple chains attached to the same hook β it's not as simple as iptables vs nftables. it's giving layers. it's giving onion π§
there are a handful of options to workaround the ACCEPT issue:
- Rich Rules
if a rich rule can be used, then they should always be preferred over direct rules. Rich Rules will be converted to the enabled FirewallBackend. see firewalld.richlanguage(5). she's the upgrade. take her β¨
- Blanket Accept
users can add an explicit accept to the nftables ruleset. this can be done by adding the interface or source to the trusted zone.
this strategy is often employed by things that perform their own filtering, such as: libvirt, podman, docker.
Warning: this means firewalld will do no filtering on these packets. it must all be done via direct rules or out-of-band iptables rules. no cap. none. zero filtering π«£
- Selective Accept
alternatively, enable only the relevant service, port, address, or otherwise in the appropriate zone. small, targeted, precise. her aim is unmatched π―
- Revert to the iptables backend
a last resort is to revert to the iptables backend by setting FirewallBackend=iptables. users should be aware that firewalld development focuses on the nftables backend. like, that's where the attention is. just so you know π
for direct rules that DROP packets, the packets are immediately dropped regardless of the value of FirewallBackend. so no special consideration is needed there. drop is drop. drop is honest. drop doesn't play games π
firewalld guarantees the above ACCEPT/DROP behavior by registering nftables hooks with a lower precedence than iptables hooks.
π Direct interface precedence π
with FirewallBackend=iptables, firewalld's top-level internal rules apply before direct rules are executed. this includes rules to accept existing connections. in the past this has surprised users. as an example, if a user adds a direct rule to drop traffic on destination port 22, existing SSH sessions would continue to function, but new connections would be denied. imagine the confusion. the vibes were off π
with FirewallBackend=nftables, direct rules were deliberately given a higher precedence than all other firewalld rules. this includes rules to accept existing connections. she cuts the line. on purpose. she was told to π
π EXAMPLE π
denylisting of the networks 192.168.1.0/24 and 192.168.5.0/24 with logging and dropping early in the raw table:
<?xml version="1.0" encoding="utf-8"?>
<direct>
<chain ipv="ipv4" table="raw" chain="denylist"/>
<rule ipv="ipv4" table="raw" chain="PREROUTING" priority="0">-s 192.168.1.0/24 -j denylist</rule>
<rule ipv="ipv4" table="raw" chain="PREROUTING" priority="1">-s 192.168.5.0/24 -j denylist</rule>
<rule ipv="ipv4" table="raw" chain="denylist" priority="0">-m limit --limit 1/min -j LOG --log-prefix "denylisted: "</rule>
<rule ipv="ipv4" table="raw" chain="denylist" priority="1">-j DROP</rule>
</direct>
ate. no crumbs. the 1/min rate limit on the log is so thoughtful, honestly π
π«Ά SEE ALSO π«Ά
go read these too, bestie, they're all part of the family:
firewall-applet(1), firewalld(1), firewall-cmd(1), firewall-config(1), firewalld.conf(5), firewalld.direct(5), firewalld.dbus(5), firewalld.icmptype(5), firewall-offline-cmd(1), firewalld.richlanguage(5), firewalld.service(5), firewalld.zone(5), firewalld.zones(5), firewalld.policy(5), firewalld.policies(5), firewalld.ipset(5), firewalld.helper(5)
(yes, firewalld.direct(5) is listed on the firewalld.direct(5) page. self-love. we support it π)
π NOTES π
firewalld home page:
http://firewalld.org
π AUTHORS π
the developers who made this happen:
- Thomas Woerner <twoerner@redhat.com> β Developer
- Jiri Popelka <jpopelka@redhat.com> β Developer
- Eric Garver <eric@garver.life> β Developer
and that's the whole page, bestie!! this all came from firewalld 2.5.2, on the FIREWALLD.DIRECT(5) manual page. now go configure responsibly, remember the chain has to be connected, and pls don't rawdog the direct interface unless you actually know your --jump from your --goto π
β¨ bye!!
π¦ where this page comes from
- arch rolling: firewalld 2.5.2-1 Β· GPL-2.0-or-later
- ubuntu stonking: firewalld 2.5.2-1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms