Security: Firewalls iptables and firewall-cmd

Netfilter is a part of the kernel that includes a suite of applications that help manage how packets flow in and out of a server or internet connected device. iptables is the command line user interface to netfilter and is one of the main firewall applications on many Linux distributions.

Fedora/RedHat offers a more user friendly interface to iptables called firewall-cmd that I'll discuss below. Ubuntu offers its own user friendly interface called ufw. In this lecture, I'll discuss iptables and firewall-cmd.


There are five predefined tables (operations) and five chains that come with iptables. Tables define the kinds of operations that you use to control the firewall and the packets that come in and out of the system or through a system. The filter and nat tables are the most commonly used ones.

The five chains are lists of rules that act on packets flowing through the system. Finally, there are also targets. These are the actions to be performed on packets. The main targets include ACCEPT, DROP, and RETURN.

From man iptables, the tables and respective chains include:

  • filter (the default table)
    • INPUT: for packets destined to local sockets
    • FORWARD: for packets being routed through the box
    • OUTPUT: for locally-generated packets
  • nat
    • PREROUTING: for altering packets as soon as they come in
    • INPUT: for altering packets destined for local sockets
    • OUTPUT: for altering locally-generated packets
    • POSTROUTING: for altering packets as they are about to go out
  • mangle
    • OUTPUT
    • INPUT
  • raw
    • OUTPUT
  • security
    • INPUT
    • OUTPUT

We'll cover the filter tables and the nat tables.


First, we'll look at the default parameters for the filter table. You need to be root to run this commands, or use sudo:

sudo su
# -L: List all rules in the selected chain;
# if no chain is selected, then list all chains; and,
# -v: be verbose
iptables -L -v | less
iptables -L | grep policy
# specify a table
iptables -t filter -L -v

Allow connections only from subnet

We can change the firewall to only allow communication on a subnet. Of course, in order to do this, we need the subnet Network ID and the CIDR number:

ip a

Now that we have the Network ID and the CIDR number, we can set the firewall (don't follow along here if you're connecting via SSH because this will end your connection):

# comment: first, set policy to drop all incoming, forwarding, and
# outgoing
# packets; this means we're starting from a baseline
iptables --policy INPUT DROP
iptables --policy FORWARD DROP
iptables --policy OUTPUT DROP

# comment: review new policies for the above chains
iptables -L | grep policy

# comment: now accept only input, forwarding, and output from the
# following
# comment: network ranges:

iptables -A INPUT -s -j ACCEPT
iptables -A FORWARD -s -j ACCEPT
iptables -A OUTPUT -s -j ACCEPT

To test this, we can try to connect to a remote server:


There are lots of examples on the web. Examples from:


Here is an example where we forward all traffic to port 25 to port 2525. Here we use the NAT table, since NAT is responsible for network address translation:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j REDIRECT --to-port 2525


Here is an example where we disable outgoing email by disabling the ports that are commonly associated with email. Of course, this could be bypassed by using non-standard ports for email, but for out case, it's a decent demonstration:

## iptables -A OUTPUT -p tcp --dports 25,465,587 -j REJECT


firewall-cmd documentation

firewalld is a more user friendly interface to netfilters/iptables in Red Hat based distros.

In firewalld, we use zones to manage internet traffic. It is possible to define custom zones with firewalld, but it does come included with the following predefined zones, and in many cases, these might be all that we need:

  • DROP : strictest. All incoming network packets are dropped
  • BLOCK : all very strict
  • PUBLIC : only selected incoming connections are accepted. Good zone for web server, email server, etc.
  • EXTERNAL : external networks (useful for NAT)
  • DMZ : computers located in DMZ
  • work : trust most computers in network and accept some services
  • home : trust most computers in network and accept some services
  • trusted : trust all machines in network

Check if running:

firewall-cmd --state

Get active zones and interfaces attached to them:

firewall-cmd --get-zones
firewall-cmd --get-default-zone
firewall-cmd --get-active-zones
  interfaces: enp0s3

Allow port 22, list ports, remove services by name, add services by name:

firewall-cmd --zone=FedoraServer --add-port=22/tcp
firewall-cmd --zone=FedoraServer --list-ports
firewall-cmd --zone=FedoraServer --remove-service=ssh --permanent
firewall-cmd --zone=FedoraServer --add-service=smtp --permanent
firewall-cmd --reload

Go into panic mode (drop all incoming/outgoing packets):

firewall-cmd --panic-on
firewall-cmd --panic-off

To change default zone:

firewall-cmd --permanent --set-default-zone=public