On a linux networked machine, i would like to restrict the set of addresses on the "public" zone (firewalld concept), that are allowed to reach it. So the end result would be no other machine can access any port or protocol, except those explicitly allowed, sort of a mix of

  --add-rich-rule='rule family="ipv4" source not  address="" drop'

  --add-rich-rule='rule family="ipv4" source not  address="" drop'

The problem above is that this is not a real list, it will block everything since if its one address its blocked by not being the same as the other, generating an accidental "drop all" effect, how would i "unblock" a specific non contiguous set? does source accept a list of addresses? i have not see anything in my look at the docs or google result so far.

EDIT: I just created this:

# firewall-cmd  --zone=encrypt --list-all
encrypt (active)
  interfaces: eth1
  services: ssh
  ports: 6000/tcp
  masquerade: no
  rich rules: 

But i can still reach port 6000 from .123 my intention was that if a source is not listed, it should not be able to reach any service or port

5 Answers 5


The rich rules aren't necessary at all.

If you want to restrict a zone to a specific set of IPs, simply define those IPs as sources for the zone itself (and remove any interface definition that may be present, as they override source IPs).

You probably don't want to do this to the "public" zone, though, since that's semantically meant for public facing services to be open to the world.

Instead, try using a different zone such as "internal" for mostly trusted IP addresses to access potentially sensitive services such as sshd. (You can also create your own zones.)

Warning: don't mistake the special "trusted" zone with the normal "internal" zone. Any sources added to the "trusted" zone will be allowed through on all ports; adding services to "trusted" zone is allowed but it doesn't make any sense to do so.

firewall-cmd --zone=internal --add-service=ssh
firewall-cmd --zone=internal --add-source=
firewall-cmd --zone=internal --add-source=
firewall-cmd --zone=public --remove-service=ssh

The result of this will be a "internal" zone which permits access to ssh, but only from the two given IP addresses. To make it persistent, re-run each command with --permanent appended, or better, by using firewall-cmd --runtime-to-permanent.

  • please clarify what you mean by "interface definition that may be present", iv tried your suggestion, please see my edit.
    – mike
    Apr 6, 2015 at 21:20
  • @mike Like I said, you need to remove eth1 from the zone. firewall-cmd --zone=encrypt --remove-interface=eth1 Apr 6, 2015 at 21:24
  • well, the encrypt zone is the new zone, before eth1 was in public, i moved it from public to encrypt, so encrypt has the source .120, i thought only 120 should be able to reach the port, what im i missing?
    – mike
    Apr 6, 2015 at 21:30
  • 1
    If you put the interface in the zone, then anything arriving via the interface can access whatever ports and services are added to the zone, regardless of IP address. So it probably belongs in public, where it was originally. Apr 6, 2015 at 21:37
  • ahh, so the accepted sources will still be allowed in even if the interface is placed in public, and the accept sources are placed in a different trusted source?
    – mike
    Apr 6, 2015 at 21:43

First install and start firewalld service

sudo yum install -y firewalld
sudo systemctl start firewalld 

Then open source IP addresses and

Open ssh 22 for remote shell if needed and use [--permanent] flag to keep changes after system reboot.

sudo firewall-cmd --zone=public --permanent --add-service=ssh
sudo firewall-cmd --zone=public --permanent --add-source=
sudo firewall-cmd --zone=public --permanent --add-source=

Then reload firewalld service to activate new configuration

sudo systemctl reload firewalld

You can also mix incoming address and destination port using rich rules feature of firewall-cmd

  • 2
    Do not use --permanent to create firewall rules then reload later. This causes a mistake to lock you out, permanently as the name implies, and it is extremely difficult to recover from this. Mar 15, 2021 at 16:32

As per firewalld.richlanguage:

Source source [not] address="address[/mask]"

   With the source address the origin of a connection attempt can be limited to the source address. An address is either a single IP address, or a network IP address. The address has to match the rule family (IPv4/IPv6). Subnet mask is expressed in either
   dot-decimal (/x.x.x.x) or prefix (/x) notations for IPv4, and in prefix notation (/x) for IPv6 network addresses. It is possible to invert the sense of an address by adding not before address. All but the specified address will match then.

Specify a netmask for the address to allow contiguous blocks.

Other than that, you could try creating an ipset for a non-contiguous list of allowed IPs.

For example, in /etc/firewalld/direct.xml:

<?xml version="1.0" encoding="utf-8"?>
   <rule ipv="ipv4" table="filter" chain="INPUT" priority="0">-m set --match-set whitelist src -j ACCEPT</rule>

The actual ipset has to be created separately.

  • this would reject, what i need is the inverse, accept if in the set,
    – mike
    Apr 6, 2015 at 22:29

You can manage easily by Rich Rule.

First Step

firewall-cmd --permanent --set-default-zone=home
firewall-cmd --permanent --zone=drop --change-interface=eth0

Second Step - Add Rich Rule

firewall-cmd --permanent --zone=home --add-rich-rule='rule family="ipv4" source address="" accept'

All port is accessible by once you add rich rule and blocked every port from other source.

If you will add any port or service by below command then it will accessible by all sources.

firewall-cmd --zone=public --add-service=ssh
firewall-cmd --zone=public --add-port=8080

If you want to open specific port for specific Ip than below command

firewall-cmd --permanent --zone=home --add-rich-rule='rule family="ipv4" port="8080/tcp" source address="" accept'
  • sudo firewall-cmd --permanent --set-default-zone=internal usage: see firewall-cmd man page Can't use stand-alone options with other options.
    – rGA145
    Dec 1, 2020 at 12:22

deny all connect

firewall-cmd --permanent --zone=drop --change-interface=eth0

accept special connect

    firewall-cmd --permanent --zone=home --add-source=
    firewall-cmd --permanent --zone=drop --add-rich-rule='rule family="ipv4" source address="" accept'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .