Rocky 10: interfaces, sources and zones — one REJECT investigated
Test scope
Section titled “Test scope”A Rocky Linux 10.2 Server VM with firewalld 2.4.0; ens18 is managed by NetworkManager.
Experiment: put source 192.168.2.2/32 into a new zone with 8089/tcp allowed, connect from that address, and record both the result and the kernel chain. Screenshot: public/evidence/firewalld/rocky-zone-match.png.
Symptom: the rule exists, the connection is rejected
Section titled “Symptom: the rule exists, the connection is rejected”$ firewall-cmd --get-active-zoneslabzone sources: 192.168.2.2/32public (default) interfaces: ens18$ firewall-cmd --zone=labzone --list-all | grep -E "^ (sources|ports)" sources: 192.168.2.2/32 ports: 8089/tcpFrom 192.168.2.2:
$ curl -v --max-time 6 http://192.168.2.241:8089/* connect ... failed: No route to hostcurl: (7) Failed to connect ... No route to hostA No route to host returned in 0 ms is a REJECT (ICMP admin-prohibited) — not a broken network, not a dropped packet.
Tell the three failure modes apart first
Section titled “Tell the three failure modes apart first”| Symptom | Meaning | Where to look |
|---|---|---|
No route to host, 0 ms | REJECT | firewall-cmd --get-active-zones, nft chain |
Connection timed out, seconds | DROP or path loss | routing, upstream ACLs |
Connection refused, 0 ms | nothing listening | ss -ltn, service state |
Mistaking a REJECT for a network fault is the most common detour.
The kernel chain explains it
Section titled “The kernel chain explains it”$ nft list chain inet firewalld filter_INPUT_POLICIESchain filter_INPUT_POLICIES { ip saddr 192.168.2.2 jump filter_IN_policy_allow-host-ipv6 ip saddr 192.168.2.2 jump filter_IN_labzone ip saddr 192.168.2.2 reject with icmpx admin-prohibited iifname "ens18" jump filter_IN_policy_allow-host-ipv6 iifname "ens18" jump filter_IN_public iifname "ens18" reject with icmpx admin-prohibited}Source and interface each form a segment ending in reject; only the segment that matches decides. Two active zones do not mean two sets of rules are combined.

Interface membership is owned by NetworkManager
Section titled “Interface membership is owned by NetworkManager”$ firewall-cmd --permanent --zone=public --remove-interface=ens18The interface is under control of NetworkManager, setting zone to default.$ firewall-cmd --reload && firewall-cmd --get-active-zonespublic (default) interfaces: ens18The zone is an NM connection property; --remove-interface is rewritten on reload while NM is in control.
The correct change
Section titled “The correct change”nmcli -g connection.zone connection show lab-static # current valuesudo nmcli connection modify lab-static connection.zone labzonesudo nmcli connection up lab-staticfirewall-cmd --get-active-zones # ens18 must moveFor combined source/interface control, use firewalld 2.x policies instead of juggling zone membership.
Three commands worth remembering
Section titled “Three commands worth remembering”firewall-cmd --get-active-zones # who is active, matched hownmcli -g connection.zone connection show <connection> # NM's viewnft list chain inet firewalld filter_INPUT_POLICIES # the final kernel orderCommon traps
Section titled “Common traps”- Reading
--list-allwithout--get-active-zones: the rule may live in a zone the traffic never reaches; - Treating REJECT as a network failure: 0 ms already tells you otherwise;
- Skipping the reload and the re-check: NM restores the default zone;
- Adding rules to both the interface zone and a source zone: decide which one handles the traffic first.
Practice: locate with three commands
Section titled “Practice: locate with three commands”firewall-cmd --get-active-zonesnmcli -g connection.zone connection show lab-staticsudo nft list chain inet firewalld filter_INPUT_POLICIES | head -8Checks:
- Which zone lists the interface;
- Whether NM agrees;
- Where the
iifnameandip saddrsegments and their rejects sit; - Conclusion: this traffic is handled by the interface segment, so the source zone’s allow never applies.
常见问题
Can one interface belong to two zones?
No. One interface belongs to one zone; use policies or rich rules for multiple sources with different treatment.
Why bring the connection up after changing the zone?
The zone is a connection property; reactivating applies it. A firewalld reload plus a re-check is the safer habit.
Is No route to host always firewalld?
Not always, but when it returns in 0 ms and the port is listening, it is almost certainly a local REJECT; confirm with the nft chain.
Next steps
Section titled “Next steps”- Zones and services: /en/firewalld-zones/
- Rich rules: /en/firewalld-rich-rules/
- Direct rules and policies: /en/firewalld-direct-rules/