Fence with sign “Private: No public right of way”

Tutorial: Configuring zones bound by source IPs in FirewallD

Some network services should only be exposed to other computers on the same trusted network. Here is how you set that up with trusted zones in FirewallD for centOS, Fedora, and RHEL.

Note: I’ll demonstrates usage of both the classic firewall-cmd command as well as the newer firewallctl command line interfaces. You can compare the syntax of the two and use the one you prefer. You can also apply the concepts discussed in this tutorial from the firewall-config GUI program. Variable values will be quoted in all examples, although it’s not strictly required to quote these as used in the example commands.

You can use the predefined zones, get a complete list of the default zones by running the command firewall-cmd --list-all-zones, or create a new zone with the command firewallctl new --permanent zone --name "myownzone" or firewall-cmd --permanent --new-zone="myownzone" (avoid special characters and spaces when naming for simplicity). For this article, I’ll use the predefined zones home and public to represent a trusted and an untrusted network.


FirewallD uses zones to manage networks. You can bind a zone to a network interface or a set of source IP addresses. You can have multiple active zones, and when no zone is applicable to an incoming connection, the default zone (public) is used. Having too many active zones can impact network performance, but for many cases you’ll only need one trusted an an untrusted network.

I’ll now go through how to configure a trusted and untrusted zone step-by-step, and then demonstrate how you can add services to the two zones.

First off, add your IPv4 and IPv6 subnet(s) to your trusted zone (home). Rules in the home zone will be applied to any source IPs from these subnets.

firewallctl zone "home" --permanent add source "198.51.100.0/24"
firewallctl zone "home" --permanent add source "2001:0DB8::/32"
firewallctl reload

firewall-cmd --permanent --zone="home" --add-source="198.51.100.0/24"
firewall-cmd --permanent --zone="home" --add-source="2001:0DB8::/32"
firewall-cmd --reload

You can then verify that the zones are correctly associated with the source IP/subnets you specified by querying for information about the currently active zones:

firewallctl info zones --active

firewall-cmd --get-active-zones

You should see your source IPs listed under the desired zones.

If you try to assign the same source IPs to different zones, you’ll run into a Error: ZONE_CONFLICT error. It’s undesirable to assign the same source IPs to different zones: a network can’t be both trusted and untrusted at the same time. Instead, you’ll want to configure more granular zones with varying levels of trust for each IP address range.


Now that you’ve configured your trusted zones and bound them to your IP subnets, you’ll want to configure different service availability for your different network zones. Start by listing the services that are already associated with your zones:

firewallctl zone "home" --permanent list services
firewallctl zone "public" --permanent list services

firewall-cmd --permanent --zone="home" --list-services
firewall-cmd --permanent --zone="public" --list-services

To manage services, all you have to do is to specify which zone they belong to. For example, assuming that the SSH service is available on the public untrusted zone, and you want to make it accessible only to hosts coming from the home trusted zone:

firewallctl zone "home" --permanent add service "ssh"
firewallctl zone "public" --permanent remove service "ssh"
firewallctl reload

firewall-cmd --permanent --zone="home" --add-service="ssh"
firewall-cmd --permanent --zone="public" --remove-service="ssh"
firewall-cmd --reload

—and that is all there is too it. Configuring zones in the firewall-config GUI program can be a bit fiddly so I recommend sticking with one of the command line tools.

2 comments

  1. This is rather nice and clean.

    Since all my Linux boxes are Ubuntu-based, I’ve only been using iptables. So to make it easy to save and restore the rules across reboots, I use the iptables-persistent package. If I want to deal with groups of IPs/subnets, there is the ipset package which allows iptables to refer to those groups.

    But iptables-persistent isn’t compatible with ipset. So it’s a bit of a mess, frankly. If FirewallD does everything I need in one nifty package, then I think it might be worth trying out.

    1. FirewallD is quite neat in many ways, but the documentation can be kind of hard to understand (compare the relevant section of the referenced man page to this tutorial, for example).

      You can do everything with iptables. The problem is that you’ll want to die before you’ve accomplished much with iptables. The syntax is a real pain to deal with. As an Ubuntu user, you could have a look at ufw. Not powerful, but far less painful than working with iptable rulesets.

Leave a Reply

Your email address will not be published. Be courteous and on-topic. Comments are moderated prior to publication.