Most Linux servers sit on networks where a perimeter firewall cannot see east-west traffic, so the host firewall is often the only control between a compromised neighbour and an exposed database, admin port or debug service. The tooling has changed underneath administrators: nftables replaced iptables as the kernel's packet filtering framework, firewalld and ufw are front ends that manage it, and container runtimes add rules of their own. This guide explains who can change a Linux host firewall and how that access should be controlled, how to build a default-deny nftables, firewalld or ufw policy, how to migrate from iptables without leaving two rule engines running, and what to log and measure. It is written for Linux administrators, platform engineers and security teams standardising host-based filtering.
Key takeaways
- Use one framework. The nftables project warns against running nft and the legacy iptables tools at the same time, because both kernel subsystems then filter packets with unexpected results.
- Default deny inbound, both address families. A single
inettable covers IPv4 and IPv6; an input chain withpolicy drop, connection tracking and explicit service rules is the baseline. - Pick the front end by platform. firewalld (zones, runtime and permanent configuration, D-Bus API) suits RHEL-family servers; ufw suits Ubuntu hosts with simple needs; raw nftables suits appliances and code-managed fleets.
- Firewall rights are root-level rights. Changing rules needs
CAP_NET_ADMINor firewalld's D-Bus authorisation, and anything holding them, including automation accounts and containers, can open the host. - Restrict management ports by source. SSH and agents should accept connections only from named sets of bastion and management addresses, not from anywhere.
How identity and access work in Linux host firewalls
The kernel's netfilter framework does the filtering. Changing its rules requires the CAP_NET_ADMIN capability in the relevant network namespace, which in practice means root, a process granted that capability, or a privileged daemon acting on someone's behalf.
| Tool | How changes are made | Who is authorised | Persistence |
|---|---|---|---|
nftables (nft) | Direct netlink calls; scripts loaded with nft -f | Root or CAP_NET_ADMIN | Ruleset file loaded at boot, for example /etc/nftables.conf by the distribution's nftables service |
| firewalld | firewall-cmd, firewall-config or other clients over D-Bus | D-Bus callers authorised by polkit (typically root and administrators) | Separate runtime and permanent configuration; --permanent plus --reload |
| ufw | ufw command writing rule files under /etc/ufw | Root via sudo | Rules files reloaded at boot when ufw is enabled |
| iptables-nft | Legacy iptables syntax translated onto nf_tables | Root or CAP_NET_ADMIN | Distribution save and restore services |
- Namespaces: Each network namespace has its own ruleset. A container with
CAP_NET_ADMINin its own namespace changes only that namespace, but a container run with host networking and that capability can rewrite the host firewall. - firewalld's API: Because firewalld exposes a D-Bus interface, any local process allowed by polkit can change the firewall without touching files. Review polkit rules on hosts where unprivileged users have desktop or remote sessions.
- Read access matters too:
nft list rulesetreveals which management networks and services a host trusts, which is useful reconnaissance. Treat ruleset exports and backups as sensitive.
For the capability model behind this, see the Linux Capabilities Guide.
Admin roles and privileged access
- Named administrators only: Grant firewall changes through
sudorules for named accounts (or through your PAM tooling), not through shared root. Command-limited rules such as allowing onlyfirewall-cmdare weak if the same account has a general shell as root, so keep firewall administration within the normal privileged access process. - Separate policy from operations: Security engineering owns the baseline ruleset; operations can add service rules through change-controlled configuration management. Ad hoc
nft add ruleorufw allowon production should be an exception with a ticket. - Use firewalld's runtime layer safely: A runtime-only change disappears on the next reload or restart. That is useful for testing and dangerous as an emergency fix that silently reverts.
- Protect your own access: Before applying a default-deny policy remotely, schedule an automatic rollback (for example a timed reload of the previous ruleset) and confirm console or out-of-band access. Lock-outs push teams back to permissive rules.
See the Linux PAM Guide and the Privileged Access Management Guide.
Integrations, API tokens and service accounts
Several non-human actors routinely change host firewalls, and each is a path for an attacker to do the same.
| Actor | What it changes | Control |
|---|---|---|
| Configuration management (Ansible, Puppet, Salt) | The whole ruleset | Ruleset in version control with review; automation credentials in a vault; drift alerts. See the Configuration Drift and Baseline Enforcement Guide. |
| Container runtimes and Kubernetes networking | NAT and forwarding chains for published ports and pod traffic | Know that published container ports may be handled in chains your host policy does not inspect; test exposure from outside rather than trusting the front end's status output |
| Intrusion prevention tools (for example fail2ban) | Dynamic block sets | Run with the least access needed; use dedicated sets or tables so it cannot alter the baseline |
| Cloud-init and image builders | Initial ruleset at first boot | Bake the baseline into the image; do not open ports in user data |
| Monitoring and backup agents | Usually nothing, but need inbound ports | Allow only from the collector's addresses via a named set |
Record each of these as a machine identity with an owner. A configuration management account that can push firewall rules to every server is as privileged as a domain administrator. See the Linux Service Accounts and Keytab Management Guide.
Choosing between nftables, firewalld and ufw
| Need | nftables directly | firewalld | ufw |
|---|---|---|---|
| Typical platform | Any distribution, appliances, routers | RHEL, Fedora, SUSE family | Ubuntu, Debian |
| Model | Tables, chains, rules, sets and maps | Zones (trust levels) and unidirectional policies between zones | Ordered allow and deny rules, application profiles |
| Change without disruption | Atomic ruleset replacement with nft -f | --reload keeps existing connections | Reload of rule files |
| Programmatic API | Netlink, JSON output | D-Bus | Command line |
| Best for | Code-managed fleets, complex sets | Servers with multiple interfaces or zones, NetworkManager integration | Single-purpose hosts and small teams |
| Watch out for | No guard rails; easy to omit IPv6 or loopback | Runtime changes lost on reload | Disabled by default; current backend uses iptables-restore |
Do not mix front ends on one host. firewalld, ufw and a hand-written nftables.conf all assume they own the ruleset. Small organisations should take the distribution default; large fleets usually benefit from one approach per OS family, generated from a shared policy definition.
Hardening baseline
A default-deny nftables policy
The nftables project's example server ruleset shows the essential structure:
- One
inettable: Covers IPv4 and IPv6 together, avoiding the classic gap where only IPv4 is filtered. - Input base chain: Hook
input, priority 0,policy drop. - State rules first: Accept
ct state established,related; dropct state invalid. - Loopback: Accept traffic on
lo. - ICMPv6 neighbour discovery: Accept it, because IPv6 connectivity depends on it. Rate limit echo requests if you allow them.
- Explicit services: Accept only the listening services the host provides (for a web server, TCP 80 and 443), and SSH only from management sources.
- Forward chain:
policy dropunless the host routes traffic or runs containers that need forwarding. - Output: The example leaves output open. For high-value servers add an output policy that permits only required destinations (DNS, NTP, update mirrors, log collectors), which limits command and control and data theft.
Sets for allow lists
Use named sets with the interval flag for management networks and collector addresses, referenced as ip saddr @mgmt_v4. Named sets can be updated without rewriting rules; set names are limited to 16 characters. The timeout flag supports temporary entries, useful for time-boxed access that removes itself.
The same baseline in firewalld
- Zones as trust levels: Traffic enters through exactly one zone. Bind the production interface to a restrictive zone and add only the services the role needs with
--add-service(for examplehttps), always with--permanentand then--reload. - Source-based zones: Put management networks in their own zone by source address and allow
sshonly there, rather than in the interface zone. - Policies for forwarding: Traffic within a zone is allowed by default and traffic between zones denied. Use firewalld policies, which are stateful and one-directional, for any inter-zone or forwarded flows, and consider
--remove-forwardwhere intra-zone forwarding is not wanted. - Verify the effective state: Compare
firewall-cmd --list-allfor runtime and permanent views; a difference between them is unreviewed drift.
The same baseline in ufw
- Enable it: ufw is disabled by default on Ubuntu;
sudo ufw enableafter rules are in place, and confirm withsudo ufw status verbose. - Restrict by source:
sudo ufw allow proto tcp from 192.168.0.0/24 to any port 22rather thanufw allow 22. - Preview:
--dry-runprints the resulting rules without applying them; use it in change reviews. - Application profiles: Profiles in
/etc/ufw/applications.dname a service's ports. Check them after package upgrades, since a profile can open more ports than you expect. - Turn logging on:
sudo ufw logging on, then ship the kernel log entries to your collector.
Rollout steps
- Discover listeners: Record listening sockets (
ss -tulpn) and actual inbound flows for a representative period before writing rules. - Write the policy as code: One ruleset file or firewalld zone definition per server role, in version control.
- Log before you drop: Add a counted, prefixed log rule before the final policy drop and run in a pilot ring to find missed services.
- Apply atomically with a safety net: Load with
nft -f(or firewalld--permanentthen--reload) with a scheduled automatic restore of the previous ruleset that you cancel once access is confirmed. - Expand by role: Roll out one server role at a time, keeping the previous ruleset as the rollback artefact.
- Retire legacy tools: Remove or disable the legacy iptables service once nftables is authoritative.
Migrating from iptables
- Translate:
iptables-translateconverts a single rule;iptables-restore-translateconverts a fulliptables-saveexport into an nft script fornft -f. - Compatibility layer:
iptables-nftkeeps iptables syntax on the nf_tables backend; rules without a native translation appear commented innft list ruleset, which is a signal to rewrite them. - Never run both: The legacy x_tables tools have been considered legacy since June 2018. Mixing them with nft runs two filtering subsystems.
Framework mapping
| Framework | Reference |
|---|---|
| CIS Controls v8.1 | Safeguard 4.4 Implement and Manage a Firewall on Servers; 4.5 on End-User Devices |
| NIST SP 800-53 Rev. 5 | SC-7 Boundary Protection; CM-7 Least Functionality; AU-12 Audit Record Generation |
| NIST CSF 2.0 | PR.IR-01 Networks and environments are protected from unauthorized logical access and usage |
| ISO/IEC 27001:2022 | Annex A 8.20 Networks security; 8.22 Segregation of networks |
| MITRE ATT&CK v20 | T1686 Disable or Modify System Firewall; T1021 Remote Services |
Logging and detection
- Log statement: nftables'
logstatement takes aprefixand a sysloglevel(defaultwarn), or sends to nflog withgroupfor user-space collectors such as ulogd. Rules evaluate left to right, so placelogafter the matches you mean. - Limit volume: Add a
limit ratebefore logging dropped packets so a scan cannot flood the journal. - Rule changes: Watch for
nft,firewall-cmd,ufwandiptablesexecutions with auditd, and for writes to ruleset files. Disabling the host firewall maps to ATT&CK T1686 Disable or Modify System Firewall. See the Linux Logging and auditd for Defenders Guide. - Ruleset fingerprint: Periodically hash
nft list rulesetoutput and compare it with the expected policy for the role. - External validation: Scan hosts from the networks they should not trust; this catches ports opened by container runtimes outside the front end.
| Metric | Target |
|---|---|
| Servers with an active default-deny inbound policy for IPv4 and IPv6 | 100% |
| Hosts running both legacy iptables and nftables rules | Zero |
| Management ports reachable from non-management networks | Zero in external scans |
| Rulesets matching the version-controlled policy | 100%, drift alerted within a day |
| Ad hoc rule changes without a change record | Trending to zero |
Common misconfigurations
- IPv4 only: An
ipfamily table with no IPv6 equivalent, leaving every service open over IPv6. - Two engines: Legacy iptables rules loaded alongside nftables or firewalld, so the effective policy is not the one anyone reviewed.
- ufw never enabled: Rules written but the firewall left in its default disabled state.
- Runtime-only fixes: firewalld changes without
--permanentthat vanish on the next reload, or permanent changes never reloaded. - SSH open to the world: Management ports accepted from any source because the source set was "temporary".
- Container exposure: Published container ports reachable despite a front end reporting them closed. Firewall gaps on internal hosts are what turn one foothold into many; see the Lateral Movement Guide.
Practitioner checklist
- Choose one firewall front end per OS family and remove the others.
- Deploy a default-deny inbound
inetpolicy with state, loopback and ICMPv6 rules. - Restrict SSH and agent ports to named management sets.
- Add egress allow lists to high-value servers.
- Keep rulesets in version control and apply them atomically with an automatic rollback.
- Migrate iptables rules with the translate tools and retire legacy services.
- Limit who and what holds firewall change rights, including automation and containers.
- Log drops with rate limits and audit every rule change.
- Validate exposure with external scans after each change window.
Standards and references
- nftables wiki: Simple ruleset for a server
- nftables wiki: Moving from iptables to nftables
- nftables wiki: Sets
- nftables wiki: Logging traffic
- firewalld: Concepts
- Ubuntu Server documentation: Firewalls
- NIST: SP 800-53 Rev. 5
- MITRE ATT&CK: Disable or Modify System Firewall
Related NHI Mgmt Group resources: Linux Server Hardening Guide · CompTIA Linux+ Certification Guide · Windows Defender Firewall Guide · Network Segmentation Guide · Firewall Management Guide