How to set up a firewall using FirewallD on RHEL 8
I am a new Red Hat Enterprise Linux sysadmin. How do I set up a firewall using FirwallD on RHEL 8?
Introduction – A Linux firewall used to protect your workstation or server from unwanted traffic. You can set up rules to either block traffic or allow through. RHEL 8 comes with a dynamic, customizable host-based firewall with a D-Bus interface. You can add or delete or update firewall rules without restarting the firewall daemon or service. firewall-cmd act as a frontend for the nftables. In RHEL 8 nftables replaces iptables as the default Linux network packet filtering framework. This page shows how to set up a firewall for your RHEL 8 and manage with the help of firewall-cmd administrative tool.
Basic concepts of FirewallD
firewalld simplifies the concepts of network traffic management. You have two main ideas as follows when it comes to firewalld on RHEL 8.
Firewalld zones are nothing but predefined sets of rules. You can see all zones by running the following ls command: $ ls -l /usr/lib/firewalld/zones/ Use the cat command to view drop zone: $ cat /usr/lib/firewalld/zones/drop.xml
Understanding predefined zones
block – All incoming network connections rejected. Only network connections initiated from within the system are possible.
dmz – Classic demilitarized zone (DMZ) zone that provided limited access to your LAN and only allows selected incoming ports.
drop – All incoming network connections dropped, and only outgoing network connections allowed.
external – Useful for router type of connections. You need LAN and WAN interfaces too for masquerading (NAT) to work correctly.
home – Useful for home computers such as laptops and desktops within your LAN where you trust other computers. Allows only selected TCP/IP ports.
internal – For use on internal networks when you mostly trust the other servers or computers on the LAN.
public – You do not trust any other computers and servers on the network. You only allow the required ports and services. For cloud servers or server hosted at your place always use public zone.
trusted – All network connections are accepted. I do not recommend this zone for dedicated servers or VMs connected to WAN.
work – For use at your workplace where you trust your coworkers and other servers.
Simply run the following command to see all zones: $ firewall-cmd --get-zones Sample outputs:
block dmz drop external home internal public trusted work
How to find out your default zone
One can assign network interface and source to a zone. One of these zones set as the default zone. To get your default zone run: $ firewall-cmd --get-default-zone To see your network interface names run either ip command or nmcli command: $ ip link show $ nmcli device status When new interface connection added (such as eth0 or ens3) to NetworkManager, they are attached to the default zone. Verify it by running the following command: $ firewall-cmd --get-active-zones
A service is nothing but a list of local ports, protocols, source ports, destinations, and firewall helper modules. Some examples:
Port – 80
Service – SSH
Protocols – ICMP
How to see firewall rules or services associated with the public zone
The above commands indicate that my default zone is public and I am allowing incoming SSH connections (port 22), dhcpv6-client, and cockpit service port on RHEL 8. All other traffic dropped by default. If I configure Apache or Nginx on RHEL 8, I need to open port 80/443 using firewall-cmd. Say you do not want unnecessary services such as cockpit or dhcpv6-client, you can drop them by modifying rules. For example, remove services dhcpv6-client and cockpit $ sudo firewall-cmd --remove-service=cockpit --permanent $ sudo firewall-cmd --remove-service=dhcpv6-client --permanent $ sudo firewall-cmd --reload $ firewall-cmd --list-services
How to see which services are allowed in the current zone
Command to reload a firewalld configuration when you make change to rules
$ sudo firewall-cmd --reload
Get the status of the firewalld service
$ sudo systemctl status firewalld
Understanding runtime and permanent firewall rule sets
Runtime firewalld configuration changes are temporary. When you reboot the RHEL 8 box, they are gone. For example, the following will temporarily open port 80/https for the Nginx web server: $ sudo firewall-cmd --zone=public --add-service=http Above rule is not retained when you reboot the Linux box or upon restarting firewalld services itself.
How to add the rule to the permanent set and reload firewalld
Let us add rule (HTTPS/443) permanently and reload firewalld: $ sudo firewall-cmd --zone=public --add-service=https --permanent $ sudo firewall-cmd --reload Verify it: $ sudo firewall-cmd --list-services $ sudo firewall-cmd --list-services --permanent
How to find of list of services supported by firewalld
The syntax is $ sudo firewall-cmd --get-services $ sudo firewall-cmd --get-services | grep mysql $ ls -l /usr/lib/firewalld/services/ $ cat /usr/lib/firewalld/services/dns.xml
Firewalld rule sets examples
Let us see some common examples of firewalld for your default zone.
How to add a service to your zone
Add dns service (TCP/UDP port 53): sudo firewall-cmd --zone=public --add-service=dns --permanent
How to remove (delete) service from your zone
Delete vnc server service (TCP port range 5900-5903): sudo firewall-cmd --zone=public --remove-service=vnc-server --permanent
How to allow/open TCP/UDP port/protocol
Open TCP port # 9009: sudo firewall-cmd --zone=public --add-port=9009/tcp --permanent To view added ports, run: $ sudo firewall-cmd --zone=internal --list-ports
How to deny/block TCP/UDP port/protocol
Open TCP port # 23: sudo firewall-cmd --zone=public --remove-port=23/tcp --permanent
How to write port forwarding firewalld rule
Forward TCP port 443 to 8080 on the same server: $ sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080 --permanent To delete above port forwarding, run $ sudo firewall-cmd --zone=public --remove-forward-port=port=80:proto=tcp:toport=8080 Turn on masquerading if you need to forward traffic (port 443) to lxd server/container hosted at 192.168.2.42 port 443: $ sudo firewall-cmd --zone=public --add-masquerade $ sudo firewall-cmd --zone=public --add-forward-port=port=443:proto=tcp:toport=443:toaddr=192.168.2.42 --permanent To delete above masquerading rules, run: $ sudo firewall-cmd --zone=public --remove-masquerade $ firewall-cmd --zone=public --remove-forward-port=port=443:proto=tcp:toport=443:toaddr=192.168.2.42 --permanent As usual use the following to list rules: $ firewall-cmd --zone=public --list-all --permanent
Rich rule example
Say you want to allow access to SSH port 22 only from 10.8.0.8 IP address, run: sudo firewall-cmd --permanent --zone=public --add-rich-rule 'rule family="ipv4" source address="10.8.0.8" port port=22 protocol=tcp accept' To verify new rules, run: $ sudo firewall-cmd --list-rich-rules --permanent In this following example allow 192.168.1.0/24 sub/net to access tcp port 11211:
The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.