Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: October 2, 2024
When working on a Linux-based server or firewall, understanding how to manage and filter network traffic is crucial. One of the most powerful tools available for this purpose is iptables. It allows us to define rules that control the flow of traffic through network ports, ensuring that only legitimate and authorized traffic can reach our system.
In this article, we’ll go through how to use iptables to manage multiple ports efficiently. We’ll begin by covering the theoretical aspects of iptables and then demonstrate practical code examples to illustrate how we can manipulate port-based traffic filtering.
Before diving into managing multiple ports, it’s important to understand the fundamentals of how iptables works. At its core, iptables operates by organizing traffic filtering into tables, chains, and rules:
In the context of managing network ports, we’re primarily concerned with the INPUT chain, as this controls the traffic coming into our system.
Let’s start by adding a rule to allow incoming traffic on a single port, such as port 80 to allow HTTP requests:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Next, let’s analyze the command above:
If we run this command and inspect the rules with iptables -L, we’ll see the new rule added:
$ iptables -L
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:http
This allows incoming HTTP traffic. In the upcoming sections, we’ll explore how to manage multiple ports.
Handling a few ports individually is manageable, but what if we need to manage several ports, such as HTTP, HTTPS, and SSH? Instead of creating separate rules for each port, we can use the multiport module to group them into a single rule.
The multiport module in iptables enables us to specify multiple ports in one rule, simplifying configuration and improving readability. For example, let’s look at an example where we allow traffic on ports 80 (HTTP), 443 (HTTPS), and 22 (SSH):
$ sudo iptables -A INPUT -p tcp -m multiport --dports 80,443,22 -j ACCEPT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere multiport dports http,https,ssh
In the above snippet, we’ve used the -m multiport option, which in turn loads the multiport module that consequently enables us to specify multiple ports during our configuration. In addition, –dports 80,443,22 specifies the list of destination ports (80, 443, and 22).
On the other hand, one may not want to specify specific ports for known protocols. In this particular situation, we can use –dport 1000:2000 to open up inbound traffic to TCP ports numbered from 1000 to 2000 inclusive.
Now, we have a single rule that allows traffic on all three critical ports. Essentially, using multiport saves time and reduces clutter in our firewall rules.
There are situations where we may need to handle both TCP and UDP protocols for different services. For example, DNS commonly uses both UDP and TCP. In essence, DNS uses UDP for quick lookups and TCP for larger queries. In addition, we can add rules to manage these protocols separately, even for the same ports:
$ sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
$ sudo iptables -A INPUT -p udp -m multiport --dports 53 -j ACCEPT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere multiport dports http,https
ACCEPT udp -- anywhere anywhere udp dpt:domain
Here, we can see that the first rule allows HTTP and HTTPS traffic over TCP. However, the second rule allows DNS queries over UDP specifically on port 53. Finally, we can easily see how both protocols are managed with separate rules. This level of control is critical for handling services that operate across different transport layers.
In this section, we’ll get to understand some of the security best practices to be able to manage your configurations effectively using multiports.
In some use cases, we may need to allow traffic on multiple ports but only from specific IP addresses. For instance, we might want to limit access to SSH and web services to a trusted internal network.
To do this, we can combine the multiport module with IP-based filtering. Let’s say we only want to allow traffic from 192.168.1.100 to ports 22 (SSH), 80 (HTTP), and 443 (HTTPS).
Let’s check out an example illustrating how to meet our inquiry:
$ sudo iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -s 192.168.1.100 -j ACCEPT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 192.168.1.100 anywhere multiport dports ssh,http,https
From the output, we can see that the source column is now populated with the IP address value of 192.168.1.100. In this matter, we specify our source and leave the destination without any constraints, as it still shows anywhere. In particular, this restricts traffic on the specified ports to a single trusted IP. Notably, this is a highly effective way to secure sensitive services like SSH or any other protocol.
Blocking traffic on certain ports is just as important as allowing it. For example, we may want to block access to unused or vulnerable ports like 8080 (alternative HTTP), 8443 (alternative HTTPS), or 3306 (MySQL).
Let’s understand how to utilize the iptables options to meet our goal:
$ sudo iptables -A INPUT -p tcp -m multiport --dports 8080,8443,3306 -j DROP
Chain INPUT (policy DROP)
target prot opt source destination
DROP tcp -- anywhere anywhere multiport dports 8080,8443,mysql
Here, we’re able to utilize the -j DROP option, which is very useful as it silently drops the traffic without sending a response. Wrapping up, the DROP action is useful for completely ignoring traffic on these ports, improving the system’s security.
By default, iptables rules do not persist across reboots. To ensure that our rules are saved and restored on boot, we need to save them manually. On most systems, we can save the rules using iptables-save:
$ sudo iptables-save > /etc/iptables/rules.v4
# Generated by iptables-save
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp -m multiport --dports 80,443,22 -j ACCEPT
COMMIT
This command writes the current rule set to a file (/etc/iptables/rules.v4) that will be loaded when the system boots. By saving our rules, we ensure that our configuration persists even after the server restarts.
Even though iptables is powerful, it’s easy to make mistakes that can disrupt traffic or leave systems vulnerable. Regularly, common issues include:
To tackle the issues above, we can use the following command to debug and review our rules in detail:
$ sudo iptables -L -v -n
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
100 6000 ACCEPT tcp -- * * anywhere anywhere multiport dports http,https,ssh
In the example above, we utilized three important options that come with the iptables command:
This output provides a detailed view of the traffic counters, protocols, and IP addresses involved. We can use it to verify that our rules are working as expected.
In this article, we explored how to use iptables to manage multiple ports efficiently. Furthermore, we covered everything from basic rules to handling multiple ports with the multiport module, combining protocols, restricting access by IP, and persisting our configurations.
By mastering these techniques, we can fine-tune network traffic and enhance the security and performance of Linux systems. Whether managing a single server or an entire network, iptables remains an indispensable tool for systems administrators.