Vault/NOTES/firewall_preoblems.md
2026-08-20 03:27:03 +02:00

37 lines
No EOL
5.3 KiB
Markdown

## Two Firewalls Silently Coexisting — UFW + firewalld
### What we did
- Debugged KDE Connect pairing failing between desktop and phone, both on the same LAN subnet
- Ruled out kdeconnectd itself (found and fixed a separate, unrelated bug: `LanLinkProvider` was disabled in `~/.config/kdeconnect/config`, so the daemon registered on DBus but never opened a network socket)
- Ruled out UFW rules being wrong — `sudo ufw status verbose` and `iptables -L -n -v` with zeroed counters showed our UFW rule for ports 1714:1764 correctly matching and ACCEPTing packets
- Traffic was still being rejected. `tcpdump` showed the desktop responding with `ICMP host unreachable - admin prohibited filter` — a different reject signature than UFW's own (`icmp-port-unreachable`)
- Searched the *entire* nftables ruleset (`sudo nft list ruleset`), not just UFW's chains — found zone-based chains (`filter_IN_public_to_HOST`, zones "public"/"trusted"/"docker") that don't belong to UFW's naming convention at all
- Confirmed firewalld was active and enabled (`systemctl is-active/is-enabled firewalld`), silently filtering `enp14s0` (LAN) under its restrictive default "public" zone this whole time — while `wt0` (NetBird) sat in the permissive "trusted" zone, which is why mesh traffic was never affected and this went unnoticed until now
- Traced its origin via `pacman.log`: installed automatically as part of EndeavourOS's default KDE Plasma install batch, months before this project's UFW work began — never installed on purpose
- Disabled firewalld (`sudo systemctl disable --now firewalld`) — KDE Connect paired immediately afterward
### Key distinction / Mental model
A firewall rule that looks completely correct in the tool you're actively managing can still be silently overridden by a **second, forgotten firewall manager** running underneath it. UFW and firewalld are both just front-ends to the same underlying nftables/iptables engine — they don't know about each other, don't conflict at install time, and both can be "active" simultaneously without either one erroring out. The system just enforces both, in sequence, and whichever one restricts something first wins.
**The diagnostic tell:** different firewall tools use different default ICMP reject types. UFW's own reject rule uses `icmp-port-unreachable`. firewalld's default zone reject uses `admin-prohibited`. When a rejection's ICMP type doesn't match what your known tool would produce, that mismatch itself is the clue that a *different* enforcement layer is responsible — worth checking before assuming your own rule is wrong.
**Why it went unnoticed for weeks:** firewalld's zone model meant the interface that mattered for existing testing (`wt0`, NetBird mesh) happened to land in the permissive "trusted" zone by default, while the interface that mattered for this new test (`enp14s0`, plain LAN) landed in the restrictive "public" zone. Different interfaces, different default zones, different outcomes — nothing about prior UFW-only testing would have surfaced this.
### Commands / syntax
| Command | What it does |
|---|---|
| `systemctl list-unit-files --state=enabled \| grep -v "^UNIT"` | Lists everything set to start automatically at boot — surfaces "silent" services you never configured yourself, not just ones you remember installing |
| `systemctl is-active firewalld` / `systemctl is-enabled firewalld` | Quick check whether firewalld specifically is running and will survive reboot |
| `sudo firewall-cmd --get-active-zones` | Shows which network interface is assigned to which firewalld zone — reveals why some interfaces behave differently than others |
| `sudo nft list ruleset \| grep -B5 -i "admin-prohibited\|reject"` | Searches the *entire* nftables ruleset (all tables/managers), not just one tool's chains — the way to find a rule regardless of which front-end created it |
| `sudo iptables -Z` then retry, then `sudo iptables -L -n -v --line-numbers \| grep -v " 0 0 "` | Zeroes all packet/byte counters, lets you trigger the failure once, then shows only the rules that actually matched — pinpoints the exact chain/rule responsible instead of reasoning about it indirectly |
| `grep -i <package> /var/log/pacman.log` | Finds exactly when and how a package was installed — reveals whether something was pulled in deliberately, as a dependency, or as part of a base-install batch |
| `sudo systemctl disable --now firewalld` | Stops firewalld immediately and prevents it from starting on future boots |
### When to use this
- Any time a firewall rule you've configured *looks* correct (matches in the tool's own status output, counters increment) but traffic is still blocked
- Whenever inheriting, rebuilding, or auditing a machine — before trusting "what I configured" as "everything that's active," check what's actually enabled at boot
- Specifically worth checking on any EndeavourOS/Arch machine with the default KDE Plasma install group, since firewalld ships enabled-by-default there alongside UFW being added later for this project (check laptop and VPS too)
### Index line
`two_firewalls_ufw_firewalld_conflict.md` — UFW rules can be silently overridden by a second, forgotten firewall (firewalld) running underneath; diagnose via ICMP reject-type mismatch and a full nftables ruleset search, not just the tool you think is in charge.