How to Use Netfilter on Your Linux System: Enabling a Packet-Filtering Firewall
The Linux kernel has built-in packet filtering software in the form of something called
netfilter. You use the
iptables command to set up the rules for what happens to the packets based on the IP addresses in their header and the network connection type.
To find out more about
iptables, visit the documentation section of the
The built-in packet filtering capability is handy when you don’t have a dedicated firewall between your Linux system and the Internet, such as when you connect your Linux system to the Internet through a DSL or cable modem. Essentially, you can have a packet filtering firewall inside your Linux system sitting between the kernel and the applications.
The security level configuration tool in Linux
Most Linux distributions, such as Fedora and SUSE, now include GUI tools to turn on a packet filtering firewall and simplify the configuration experience for the user.
In some distributions, you need to install ufw (an acronym for Uncomplicated Firewall), which lets you manage a net-filter firewall and simplify configuration. ufw serves as a front end to
iptables, which allows you to enter commands in a terminal window directly through it. The command
sudo ufw enable
turns the firewall on, and the command
sudo ufw status verbose
displays such information as the following:
Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip
The default settings are exactly what you’re looking for in most cases for a client machine: allowing outgoing traffic and denying incoming traffic.
You can allow incoming packets meant for specific Internet services such as SSH, Telnet, and FTP. If you select a network interface such as
eth0 (the first Ethernet card) as trusted, all network traffic over that interface is allowed without any filtering.
In SUSE, to set up a firewall, choose Main Menu→ System→ YaST. In the YaST Control Center window that appears, click Security and Users on the left side of the window and then click Firewall on the right side. YaST opens a window that you can use to configure the firewall.
You can designate network interfaces (by device name, such as
ppp0, and so on) to one of three zones: internal, external, or demilitarized zone. Then, for that zone, you can specify what services (such as HTTP, FTP, and SSH) are allowed. If you have two or more network interfaces, and you use the Linux system as a gateway (a router), you can enable forwarding packets between network interfaces (a feature called masquerading).
You can also turn on different levels of logging, such as logging all dropped packets that attempt connection at specific ports. If you change the firewall settings, choose the Startup category and click Save Settings and Restart Firewall Now.
The iptables command in Linux
The graphical user interface (GUI) firewall configuration tools are just front ends that use the
iptables command to implement the firewall. If your Linux system doesn’t have a GUI tool, you can use
iptables directly to configure firewalling on your Linux system.
iptables command is somewhat complex. The command uses the concept of a chain, which is a sequence of rules. Each rule says what to do with a packet if the header contains certain information, such as the source or destination IP address. If a rule doesn’t apply,
iptables consults the next rule in the chain. By default, there are three chains:
- INPUT chain: Contains the first set of rules against which packets are tested. The packets continue to the next chain only if the
INPUTchain doesn’t specify
- FORWARD chain: Contains the rules that apply to packets attempting to pass through this system to another system (when you use your Linux system as a router between your LAN and the Internet, for example).
- OUTPUT chain: Includes the rules applied to packets before they’re sent out (either to another network or to an application).
When an incoming packet arrives, the kernel uses
iptables to make a routing decision based on the destination IP address of the packet. If the packet is for this server, the kernel passes the packet to the
INPUT chain. If the packet satisfies all the rules in the
INPUT chain, the packet is processed by local processes such as an Internet server that’s listening for packets of this type.
If the kernel has IP forwarding enabled, and the packet has a destination IP address of a different network, the kernel passes the packet to the
FORWARD chain. If the packet satisfies the rules in the
FORWARD chain, it’s sent out to the other network. If the kernel doesn’t have IP forwarding enabled, and the packet’s destination address isn’t for this server, the packet is dropped.
If the local processing programs that receive the input packets want to send network packets out, those packets pass through the
OUTPUT chain. If the
OUTPUT chain accepts those packets, they’re sent out to the specified destination network.
You can view the current chains, add rules to the existing chains, or create new chains of rules by using the
iptables command, which normally requires you to be root to interact with. When you view the current chains, you can save them to a file. If you’ve configured nothing else, and your system has no firewall configured, typing iptables -L should show the following:
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
In this case, all three chains —
OUTPUT — show the same
ACCEPT policy, which means that everything is wide open.
If you’re setting up a packet filter, the first thing you do is specify the packets that you want to accept. To accept packets from the 192.168.0.0 network address, add the following rule to the
iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT
Now add a rule to drop everything except local loopback (the
lo network interface) traffic and stop all forwarding with the following commands:
iptables -A INPUT -i ! lo -j REJECT iptables -A FORWARD -j REJECT
iptables command, for example, appends to the
INPUT chain (
-A INPUT) the rule that if the packet doesn’t come from the
lo interface (
-i ! lo),
iptables rejects the packet (
Before rejecting all other packets, you may add more rules to each
INPUT chain to allow specific packets in. You can select packets to accept or reject based on many parameters, such as IP addresses, protocol types (TCP, UDP), network interface, and port numbers.
You can do all sorts of specialized packet filtering with
iptables. Suppose that you set up a web server and want to accept packets meant for only HTTP (port 80) and SSH services. The SSH service (port 22) is for you to securely log in and administer the server. Also suppose that the server’s IP address is 192.168.0.10. Here’s how you might set up the rules for this server:
iptables -P INPUT DROP iptables -A INPUT -s 0/0 -d 192.168.0.10 -p tcp --dport 80 -j ACCEPT iptables -A INPUT -s 0/0 -d 192.168.0.10 -p tcp --dport 22 -j ACCEPT
In this case, the first rulesets up the default policy of the
INPUT chain to
DROP, which means that if none of the specific rules matches, the packet is dropped. The next two rules say that packets addressed to 192.168.0.10 and meant for ports 80 and 22 are accepted.
iptables commands from a remote login session. A rule that begins denying packets from all addresses can also stop what you type from reaching the system; in that case, you may have no way of accessing the system over the network. To avoid unpleasant surprises, always type
iptables rules at the console — the keyboard and monitor connected directly to your Linux PC that’s running the packet filter. If you want to delete all filtering rules in a hurry, type iptables -F to flush them. To change the default policy for the
INPUT chain to
ACCEPT, type iptables -t filter -P INPUT ACCEPT. This command causes
iptables to accept all incoming packets by default.
iptables command is discussed here. You can type man iptables to read a summary of the commands. You can also read about
After you define the rules by using the
iptables command, those rules are in memory and are gone when you reboot the system. Use the
iptables-save command to store the rules in a file. You can save the rules in a file named
iptables.rules by using the following command:
iptables-save > iptables.rules
Here’s a listing of the iptables.rules file generated on a Fedora system:
# Generated by iptables-save v1.3.0 on Sun Dec 28 16:10:12 2019 *filter :FORWARD ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [6:636] -A FORWARD -j REJECT --reject-with icmp-port-unreachable -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT -A INPUT -i ! lo -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Sun Dec 28 16:10:12 2019
These rules correspond to the following
iptables commands used to configure the filter:
iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT iptables -A INPUT -i ! lo -j REJECT iptables -A FORWARD -j REJECT
If you want to load these saved rules into
iptables, use the following command:
iptables-restore < iptables.rules