firewalld source-based access rules
noteHistorical technical note from 2018. Environment-specific identifiers and credentials have been anonymized. Commands reflect the technology and operating-system generation used at the time and should be reviewed before reuse on a current system.
This note shows two ways to restrict SSH with firewalld: bind trusted source addresses to a dedicated zone, or use a rich rule that matches source, destination and port.
Source-based zone
$ firewall-cmd --permanent --new-zone=src-admin $ firewall-cmd --permanent --zone=src-admin --add-source=192.0.2.10/32 $ firewall-cmd --permanent --zone=src-admin --add-source=2001:db8:10::10/128 $ firewall-cmd --permanent --zone=src-admin --add-service=ssh $ firewall-cmd --reload
Inspect:
$ firewall-cmd --get-active-zones $ firewall-cmd --zone=src-admin --list-all
A source address and an interface/connection are different zone selectors. Avoid assigning the same traffic ambiguously to multiple zones.
Rich-rule alternative
$ firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.0.2.10/32" destination address="198.51.100.20/32" service name="ssh" accept' $ firewall-cmd --reload
For IPv6 host addresses use /128, not /64, unless the intention is to match a whole subnet.
Validate before disconnecting
$ firewall-cmd --check-config $ firewall-cmd --zone=public --list-rich-rules
Keep an existing administrative session open until the new rule has been tested.
References
- firewalld zones: https://firewalld.org/documentation/zone/
- firewalld rich language: https://firewalld.org/documentation/man-pages/firewalld.richlanguage.html
- firewalld documentation: https://firewalld.org/documentation/
Current practice (checked 2026-10)
noteThe article above is kept as it was written in 2018. This section lists what has changed since and what to do instead today.
- Still valid: source-bound zones, rich rules and
--check-configwork the same way in current firewalld; the commands above need no change. - SSH stays open in the default zone: adding
sshtosrc-admin(or adding an accepting rich rule) does not restrict anything while thepubliczone still carries thesshservice, which it does by default. Remove it there once the trusted-source access is confirmed to work. - Backend: the note was written for the iptables backend. nftables is the default backend since firewalld 0.6.0 and the iptables backend is now marked deprecated in
firewalld.conf(5), so inspect the generated rules withnft list ruleset, notiptables -L. - Zone ordering: source-based zones are evaluated before interface-based zones and are sorted by zone name. Current firewalld also has zone priorities (
--set-priority), which is the explicit way to resolve the "ambiguous assignment" the note warns about. - Policies: since firewalld 0.9.0 policy objects filter traffic between zones (forwarded traffic, and traffic to or from the host via the symbolic zone
HOST). Zones alone only cover traffic terminating on the host, so use a policy when the same source restriction must apply to routed traffic. - Rich rules:
familyis mandatory when a source or destination address is used, as in the example; an IPv6 source needs its own rule withfamily="ipv6". Rich rules now accept apriorityattribute (-32768 to 32767, lower wins) when ordering between rules matters.
$ # firewall-cmd --permanent --zone=public --remove-service=ssh $ # firewall-cmd --reload $ # nft list ruleset
Sources: