How to convert RHEL6 iptables-service rules with state into firewalld rules?

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 7

Issue

  • How to convert iptables rules to firewalld?
  • How to convert the following rules to firewalld rules:

    # bacula backup
    -A INPUT -m state --state NEW -m tcp -p tcp --src 192.168.0.1 --dport 9102 -j ACCEPT
    -A INPUT -m state --state NEW -m tcp -p tcp --src 192.168.1.1 --dport 9102 -j ACCEPT
    -A INPUT -m state --state NEW -m tcp -p tcp --src 192.168.2.1 --dport 9102 -j ACCEPT
    

Resolution

  • To allow traffic to a particular port say TCP port 8080, run:

    # firewall-cmd --permanent --add-port=8080/tcp
    
  • To filter traffic to a port on the basis of source or destination ip addresses, use Firewalld Rich Rules as below:

    # firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.0.1" service name="bacula-client" accept'
    # firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.1" service name="bacula-client" accept'
    # firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.2.1" service name="bacula-client" accept'
    # firewall-cmd --reload
    
  • Once the rules has been added, they will appear in the respective zone file as below:

    # cat /etc/firewalld/zones/public.xml
    .
    .
    <rule family="ipv4">
        <source address="192.168.2.1"/>
        <service name="bacula-client"/>
        <accept/>
      </rule>
      <rule family="ipv4">
        <source address="192.168.0.1"/>
        <service name="bacula-client"/>
        <accept/>
      </rule>
      <rule family="ipv4">
        <source address="192.168.1.1"/>
        <service name="bacula-client"/>
        <accept/>
      </rule>
    
  • Reload the rules so that they are read from the respective zone files and applied:

    # firewall-cmd --reload
    
Note: The rules get added to the default zone(unless changed will be "public"). To add them to a different zone, use "--zone="

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

3 Comments

In this case you can also use rich-rules:

# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.0.1" service name="bacula-client" accept'
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.1" service name="bacula-client" accept'
# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.2.1" service name="bacula-client" accept'

This adds the rules into default (called 'public' if you haven't changed it) zone.
If you want to add them into different zone add --zone=

Now see /etc/firewalld/zones/public.xml:

  <rule family="ipv4">
    <source address="192.168.2.1"/>
    <service name="bacula-client"/>
    <accept/>
  </rule>
  <rule family="ipv4">
    <source address="192.168.0.1"/>
    <service name="bacula-client"/>
    <accept/>
  </rule>
  <rule family="ipv4">
    <source address="192.168.1.1"/>
    <service name="bacula-client"/>
    <accept/>
  </rule>

You also have to either reload firewalld (which reads the zone xml file and applies the rules)

# systemctl reload firewalld

or add the rules also into runtime configuration (only if you don't want to reload firewalld)

# firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.0.1" service name="bacula-client" accept'
# firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.1.1" service name="bacula-client" accept'
# firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.168.2.1" service name="bacula-client" accept'

Now check underlying iptables:

# iptables-save
-A IN_public_allow -s 192.168.1.1/32 -p tcp -m tcp --dport 9102 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -s 192.168.2.1/32 -p tcp -m tcp --dport 9102 -m conntrack --ctstate NEW -j ACCEPT
-A IN_public_allow -s 192.168.0.1/32 -p tcp -m tcp --dport 9102 -m conntrack --ctstate NEW -j ACCEPT

Thanks for the information Jiri. This is excellent for the solution.

How would you translate iptables rules that use STATE? Such as:

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT

Thanks