firewalld and restricted zone traffic

My background is one where the networking environment is to disallow all network traffic unless specifically allowed. I just revolt against the philosophy of block everything in and allow everything out.

Be warned that my example will break many things in your environment so be prepared to utilize tcpdump or wireshark to resolve issues. Also, my example is completely IPv4. IPv6 is certainly supported by firewalld.

Some understanding of firewalld is required to understand my configuration example. The documentation is at:

https://firewalld.org/documentation/

An understanding of iptables rules is required since that is the format firewalld utilizes in this example.

I am going to leave it to the reader to decide how they want to create zones, rules, etc. The options are to utilize firewall-cmd, firewall-config, or direct xml file manipulation. Purists will probably dislike the last option. However, the xml files are what firewalld reads to build the configurations, and the syntax of those files is what I am going to deal with, not how to use firewall-cmd or a GUI.

Put another way: I expect the reader to understand firewalld. What you use to get to the final xml file generation I will leave to you.

NOTE: If you need to NAT your internal connections to the Internet utilize firewalld to implement this masquerading functionality. You will notice in my example I create no special rules to NAT, and it is probably a bad idea to. Yet, all my connections to the Internet use NAT through eth0.

firewalld allows you to comment xml files. I have no idea if they survive when utilizing running to permanent operations in the GUI, but I will utilize the syntax in my xml files as an inline documentation process.

Finally: You may wonder why I even documented this. The reasoning is quite simple. The Rich Language, or services interface, in firewalld is utilized for allowing traffic into a zone. Direct Options are utilized for allowing traffic out of a “restricted” zone. Because my configuration blocks both forms of traffic I had to utilize direct options. Since, I was utilizing direct options I avoided configuring services and rich rules by how I created my direct rules. You will notice this in my xml files.

The firewall-cmd manpage states:
**The direct options give a more direct access to the firewall. These options require user to know basic iptables concepts, i.e. table (filter/mangle/nat/…), chain (INPUT/OUTPUT/FORWARD/…), commands (-A/-D/-I/…), parameters (-p/-s/-d/-j/…) and targets (ACCEPT/DROP/REJECT/…).

Direct options should be used only as a last resort when it’s not possible to use for example --add-service=service or --add-rich-rule=‘rule’.
**
My example network is:


                           Internet
                               |
                              eth0
                               |
dvbro (http server network)---------svbro (DNS server network)
                               |
                     ivbr0 (desktop network)

I created specific zones for the web server and dns server. I utilized the external zone for eth0. For the desktop network I utilized the internal zone and just restricted the zone.

The two server zones are very similar. Here is the web server zone:


<?xml version="1.0" encoding="utf-8"?>
<zone target="%%REJECT%%">
  <!-- 
     A completely trusted zone uses target="ACCEPT". 
     REJECT in my example sends back an ICMP packet when dropping connections.
     target="DROP" just discards the connection and sends back no response.
     Leaving out the target all together allows nothing into the zone, unless specified, and all traffic out of the zone.
  -->
  <short>External Webserver</short>
  <interface name="dvbr0"/>
</zone>

The dns server zone is identical other than the interface name is svbr0.

Finally the internal zone was modified to also have the target="%%REJECT%%". I now have 3 very broken zones because REJECT or DROP allow no connections unless there is a specific rule to allow.

If you log into the dns server that is connected to the network interface svbr0 and try to connect with nslookup or wget http://google.com they will fail. So, will ntp.

So, let’s add a rule for dns out with firewall-cmd to help understand the syntax:


firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i svbr0 -o eth0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

Reload your firewall (firewall-cmd --reload) and nslookup or dig should now work from your dns server to external dns servers. The rule is stored in the /etc/firewalls/direct.xml file, and looks like:


<?xml version="1.0" encoding="utf-8"?>
<direct>
  <!--
    dns rules to allow traffic out
  -->
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="0">-i svbr0 -o eth0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
</direct>

Depending upon how you like to configure rules this has gotten you to a point where you can either start firewall-config, go under the View menu and check the Direct box to see how rules are entered, continue on with firewall-cmd to add more rules, or duplicate and modify lines in the xml file.

Here is my direct.xml file that allows my:

  1. dns zone to send dns traffic out to the Internet and respond to queries from my web server and internal zones
  2. web server and internal zone to query my dns zone
  3. zones to patch and access web sites through http and https

I have also specifically not granted my dns or my internal zones any http access to my web server.


<?xml version="1.0" encoding="utf-8"?>
<direct>
  <!--
    dns and dhcp rules for dns_dhcp.xml zone to allow traffic out
  -->
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="0">-i svbr0 -o eth0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="0">-i svbr0 -o dvbr0 -p udp -m multiport --sport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="0">-i svbr0 -o ivbr0 -p udp -m multiport --sport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <!--
    dns and dhcp rules to allow traffic between zones
  -->
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="1">-i eth0 -o svbr0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="1">-i dvbr0 -o svbr0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="1">-i ivbr0 -o svbr0 -p udp -m multiport --dport 53 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <!--
    http and https rules for all zone to allow traffic out for patching
  -->
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="2">-i svbr0 -o eth0 -p tcp -m multiport --dport 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="2">-i dvbr0 -o eth0 -p tcp -m multiport --dport 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="2">-i ivbr0 -o eth0 -p tcp -m multiport --dport 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <!--
    ntp rules for all zone to allow traffic out for time
  -->
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="3">-i svbr0 -o eth0 -p udp -m multiport --dport 123 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="3">-i dvbr0 -o eth0 -p udp -m multiport --dport 123 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
  <rule ipv="ipv4" table="filter" chain="FORWARD" priority="3">-i ivbr0 -o eth0 -p udp -m multiport --dport 123 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT</rule>
</direct>

I realize this is not a complete handholding post. I just hopes it saves someone else from having to hunt for a few hours in the search engines on how to pass traffic around zones.