By Mitchell Anicas and Manikandan Kurup

The iptables utility is a software firewall for Linux distributions that lets you control how network traffic is handled by the Linux kernel. With iptables, you can define rules that match traffic by properties like protocol, port, source or destination address, and network interface, and then decide whether to allow it, block it, or log it. These rules are organized into tables and chains (such as the INPUT, OUTPUT, and FORWARD chains) and are evaluated from top to bottom, which makes rule order an important part of getting the behavior you expect.
This cheat sheet-style guide provides a quick reference to iptables commands for common, everyday scenarios on Ubuntu 24.04. It includes examples of allowing and blocking services by port, network interface, and source IP address, along with guidance on rule ordering, persistence, and basic safety checks.
Note: Modern Ubuntu releases (including Ubuntu 24.04) use the nftables backend through the iptables-nft compatibility layer. The commands in this guide continue to work as written, but nftables is the recommended long-term firewall framework on Linux systems.
Note: The rules in this guide apply only to IPv4 traffic. Ubuntu 24.04 enables IPv6 by default. If IPv6 is active on your server, you should also configure ip6tables or nftables to avoid leaving services exposed over IPv6.
Key Takeaways:
iptables remains a powerful low-level firewall tool on Ubuntu 24.04, typically running through the iptables-nft compatibility layer backed by nftables.-A versus -I can significantly affect how traffic is handled.iptables rules are not persistent by default; using iptables-persistent and netfilter-persistent ensures rules survive reboots.INPUT and OUTPUT rules.nat table in addition to standard filter rules.iptables may leave services exposed unless ip6tables or nftables is also configured.iptables is better suited for advanced, fine-grained network control.Note: Throughout this guide, replace example interfaces like eth0/eth1 with the actual interface names on your system. On modern Ubuntu releases these use predictable names (for example ens3, enp0s3, and similar). To list your current interfaces, run:
- ip a
Keep in mind that rule order matters. All of the iptables commands in this guide use the -A option to append a new rule to the end of a chain. If you want to put a rule somewhere else in the chain, you can use the -I option, which allows you to specify the position of the new rule (or place it at the beginning of the chain by omitting a rule number).
Note: When working with firewalls, take care not to lock yourself out of your own server by blocking SSH traffic (port 22, by default). If you lose access due to your firewall settings, you may need to connect to it via a web-based console to fix your access. If you’re using DigitalOcean, you can read our Recovery Console product documentation for more information. Once you are connected via the console, you can change your firewall rules to allow SSH access (or allow all traffic). If your saved firewall rules allow SSH access, another method is to reboot your server.
Remember that you can check your current iptables ruleset with sudo iptables -S and sudo iptables -L.
Let’s take a look at the iptables commands.
iptables rules are ephemeral, which means they need to be manually saved if you want them to persist after a reboot. Because iptables rules are not persistent by default, remember to save your rules after making changes.
On Ubuntu 24.04, one common way to save iptables rules is to use the iptables-persistent package, which installs the netfilter-persistent service. This works with the iptables-nft compatibility layer used by modern Ubuntu systems.
Install it with apt like this:
- sudo apt install iptables-persistent
During the installation, you will be asked if you want to save your current firewall rules.
If you update your firewall rules and want to save the changes, run this command:
- sudo netfilter-persistent save
After saving, it is a good practice to verify that your rules are loaded correctly:
- sudo iptables -L -n -v
Other Linux distributions may have alternate ways of making your iptables changes permanent. Please refer to the relevant documentation for more information.
After rebooting your server, verify that your rules are still active to confirm persistence.
If you want to learn how to list and delete iptables rules, check out this tutorial: How To List and Delete Iptables Firewall Rules.
This section includes a variety of iptables commands that will create rules that are generally useful on most servers.
The loopback interface, also referred to as lo, is what a computer uses to forward network connections to itself. For example, if you run ping localhost or ping 127.0.0.1, your server will ping itself using the loopback. The loopback interface is also used if you configure your application server to connect to a database server with a localhost address. As such, you will want to be sure that your firewall is allowing these connections.
To accept all traffic on your loopback interface, run these commands:
- sudo iptables -A INPUT -i lo -j ACCEPT
- sudo iptables -A OUTPUT -o lo -j ACCEPT
Because network traffic generally needs to be two-way (incoming and outgoing) to work properly, it is typical to create a firewall rule that allows established and related incoming traffic. This ensures the server allows return traffic for outgoing connections initiated by the server itself. This command will allow that:
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
You may want to allow outgoing traffic of all established connections, which are typically the response to legitimate incoming connections. This command will allow that:
- sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
Note: This rule is rarely required on typical Ubuntu hosts because the OUTPUT policy is usually ACCEPT.
Assuming eth0 is your external interface and eth1 is your internal interface, this rule allows your internal network to access the external network:
- sudo iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
Note: Adjust eth0 and eth1 to match your system’s actual interface names, as described in the earlier note on predictable network interface names.
Note: This rule allows forwarding between interfaces but is typically only one part of a complete gateway or NAT configuration. In many real-world setups, you may also need to:
net.ipv4.ip_forward=1)RELATED,ESTABLISHED traffic in the FORWARD chainMASQUERADE rule in the nat tableThe exact requirements depend on your network architecture.
Some network traffic packets get marked as invalid. Sometimes it can be useful to log this type of packet, but often it is fine to drop it. Do so with this command:
- sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
To block network connections that originate from a specific IP address, 203.0.113.51 for example, run this command:
- sudo iptables -A INPUT -s 203.0.113.51 -j DROP
In this example, -s 203.0.113.51 specifies a source IP address of “203.0.113.51”. The source IP address can be specified in any firewall rule, including an allow rule.
If you want to reject the connection instead, which will respond to the connection request with a “connection refused” error, replace “DROP” with “REJECT” like this:
- sudo iptables -A INPUT -s 203.0.113.51 -j REJECT
To block connections from a specific IP address, e.g. 203.0.113.51, to a specific network interface, e.g. eth0, use this command:
- sudo iptables -A INPUT -i eth0 -s 203.0.113.51 -j DROP
This is the same as the previous example, with the addition of -i eth0. The network interface can be specified in any firewall rule, and is a great way to limit the rule to a particular network.
If you’re using a server without a local console, you will probably want to allow incoming SSH connections (port 22) so you can connect to and manage your server. This section covers how to configure your firewall with various SSH-related rules.
Warning: Before applying firewall rules on a remote server, ensure that SSH access (usually port 22) is allowed from your current IP address. Applying restrictive rules without allowing SSH may lock you out of your server.
A common safe workflow is to:
To allow all incoming SSH connections, run these commands:
- sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established SSH connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow incoming SSH connections from a specific IP address or subnet, specify the source. For example, if you want to allow the entire 203.0.113.0/24 subnet, run these commands:
- sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established SSH connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
If your firewall OUTPUT policy is not set to ACCEPT, and you want to allow outgoing SSH connections—your server initiating an SSH connection to another server—you can run these commands:
- sudo iptables -A OUTPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
Rsync, which runs on port 873, can be used to transfer files from one computer to another.
To allow incoming rsync connections from a specific IP address or subnet, specify the source IP address and the destination port. For example, if you want to allow the entire 203.0.113.0/24 subnet to be able to rsync to your server, run these commands:
- sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 873 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 873 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established rsync connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
Web servers, such as Apache and Nginx, typically listen for requests on port 80 and 443 for HTTP and HTTPS connections, respectively. If your default policy for incoming traffic is set to drop or deny, you will want to create rules that will allow your server to respond to those requests.
To allow all incoming HTTP (port 80) connections, run these commands:
- sudo iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established HTTP connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow all incoming HTTPS (port 443) connections, run these commands:
- sudo iptables -A INPUT -p tcp --dport 443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established HTTPS connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
If you want to allow both HTTP and HTTPS traffic, you can use the multiport module to create a rule that allows both ports. To allow all incoming HTTP and HTTPS (ports 80 and 443) connections, run these commands:
- sudo iptables -A INPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp -m multiport --sports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established HTTP and HTTPS connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
MySQL listens for client connections on port 3306. If your MySQL database server is being used by a client on a remote server, you need to be sure to allow that traffic.
To allow incoming MySQL connections from a specific IP address or subnet, specify the source. For example, if you want to allow the entire 203.0.113.0/24 subnet, run these commands:
- sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 3306 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established MySQL connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow MySQL connections to a specific network interface (for example, a private interface on a cloud server), use these commands. Replace the interface name with your own (you can check with ip link):
- sudo iptables -A INPUT -i eth1 -p tcp --dport 3306 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -o eth1 -p tcp --sport 3306 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established MySQL connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
PostgreSQL listens for client connections on port 5432. If your PostgreSQL database server is being used by a client on a remote server, you need to be sure to allow that traffic.
To allow incoming PostgreSQL connections from a specific IP address or subnet, specify the source. For example, if you want to allow the entire 203.0.113.0/24 subnet, run these commands:
- sudo iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 5432 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 5432 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established PostgreSQL connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow PostgreSQL connections to a specific network interface, use these commands. Replace the interface name with your own (you can check with ip link):
- sudo iptables -A INPUT -i eth1 -p tcp --dport 5432 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -o eth1 -p tcp --sport 5432 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established PostgreSQL connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
Mail servers, such as Sendmail and Postfix, listen on a variety of ports depending on the protocols being used for mail delivery. If you are running a mail server, determine which protocols you are using and allow the appropriate types of traffic. We will also show you how to create a rule to block outgoing SMTP mail.
If your server shouldn’t be sending outgoing mail, you may want to block that kind of traffic. To block outgoing SMTP mail, which uses port 25, run this command:
- sudo iptables -A OUTPUT -p tcp --dport 25 -j REJECT
This configures iptables to reject all outgoing traffic on port 25. If you need to reject a different service by its port number, instead of port 25, substitute that port number for the 25 above.
To allow your server to respond to SMTP connections on port 25, run these commands:
- sudo iptables -A INPUT -p tcp --dport 25 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 25 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established SMTP connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow your server to respond to IMAP connections, port 143, run these commands:
- sudo iptables -A INPUT -p tcp --dport 143 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 143 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established IMAP connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow your server to respond to IMAPS connections, port 993, run these commands:
- sudo iptables -A INPUT -p tcp --dport 993 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 993 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established IMAPS connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow your server to respond to POP3 connections, port 110, run these commands:
- sudo iptables -A INPUT -p tcp --dport 110 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 110 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established POP3 connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
To allow your server to respond to POP3S connections, port 995, run these commands:
- sudo iptables -A INPUT -p tcp --dport 995 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
- sudo iptables -A OUTPUT -p tcp --sport 995 -m conntrack --ctstate ESTABLISHED -j ACCEPT
The second command, which allows the outgoing traffic of established POP3S connections, is only necessary if the OUTPUT policy is not set to ACCEPT.
Network Address Translation (NAT) allows a Linux server to modify packet addresses as traffic passes through it. NAT is commonly used when a server acts as a gateway between networks or when you need to forward traffic from one port to another internal host.
On Ubuntu 24.04, iptables commands typically run through the iptables-nft compatibility layer, but the syntax shown here continues to work as expected.
Before configuring NAT or port forwarding, you must enable IPv4 forwarding so the kernel can route packets between interfaces:
- sudo sysctl -w net.ipv4.ip_forward=1
To make this change persistent across reboots, edit /etc/sysctl.conf and ensure the following line is present:
net.ipv4.ip_forward=1
Then apply the settings:
- sudo sysctl -p
A common NAT setup allows hosts on a private network to access external networks through a gateway server.
Assuming:
eth0 -> external interfaceeth1 -> internal interfaceYou can enable source NAT (masquerading) with:
- sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
You will typically also need a forwarding rule:
- sudo iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate NEW -j ACCEPT
- sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Replace eth0 and eth1 with your actual interface names. Modern Ubuntu systems often use names such as ens3 or enp0s3 (check with ip a).
Port forwarding (DNAT) allows incoming traffic on one interface and port to be redirected to another internal host.
For example, to forward incoming HTTP traffic on eth0 to an internal server at 10.0.0.5:
- sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.5:80
You must also allow forwarding for the traffic:
- # Allow return traffic for established/related connections
- sudo iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-
- # Allow new incoming connections to the internal web server
- sudo iptables -A FORWARD -p tcp -d 10.0.0.5 --dport 80 -m conntrack --ctstate NEW -j ACCEPT
To review NAT table rules, run:
- sudo iptables -t nat -L -n -v
As with other iptables rules, remember to save your configuration using netfilter-persistent if you want the rules to persist after reboot.
Ubuntu includes UFW (Uncomplicated Firewall), a higher-level firewall management tool that simplifies common firewall tasks. On Ubuntu, both UFW and iptables ultimately configure the kernel’s netfilter firewalling system. In most cases, iptables commands run via the iptables-nft compatibility layer, with nftables as the underlying backend.
iptables is a low-level rule management utility that exposes netfilter concepts directly (tables, chains, rule ordering, conntrack matches, and targets). It is best suited to advanced scenarios where you need precise control over evaluation order, complex match conditions, custom chains, NAT and forwarding behavior, or when troubleshooting very specific traffic patterns. It is also common in scripted environments and tooling that expects direct rule manipulation.
UFW is designed for straightforward server policies with sensible defaults and a more approachable interface. It is typically easier to maintain for common requirements like “deny incoming by default, allow SSH, allow HTTP/HTTPS,” and it can use application profiles on many systems. It’s a good choice when you want a readable, higher-level configuration that’s simpler to audit and less error-prone than managing many individual iptables rules.
Here’s a quick comparison table:
| Aspect | UFW | iptables |
|---|---|---|
| Abstraction level | High-level, opinionated interface | Low-level, explicit rule management |
| Best for | Common host firewall policies on single servers | Fine-grained control, custom chains, complex matching, NAT/forwarding |
| Rule ordering control | Limited/indirect | Direct and explicit |
| Auditability/readability | Usually easier for typical policies | Can become complex without careful structure and documentation |
| Tooling/integration | Simple CLI; integrates well with typical Ubuntu workflows | Often used by scripts, config management, containers/network tooling |
| Backend on Ubuntu 24.04 | Programs netfilter (typically via nftables underneath) |
Typically iptables-nft compatibility layer over nftables |
| Common pitfalls | Enabling before allowing SSH; misunderstanding profiles | Lockouts due to rule order/policy; persistence not configured |
In practice, UFW is often the better starting point on Ubuntu for typical requirements because it reduces the chance of mistakes and makes routine changes faster. iptables remains useful when you require fine-grained behavior that doesn’t map cleanly to UFW’s abstractions, when you need to integrate with existing rule sets and operational procedures, or when implementing specialized networking patterns (for example, more complex forwarding and NAT rules).
Whichever tool you choose, validate the effective rules on production systems, and ensure critical access paths (like SSH) are allowed before enabling restrictive policies. If you choose iptables, also plan for rule persistence (for example, using iptables-persistent) and document rule intent so troubleshooting is manageable.
When working with iptables, small mistakes can quickly disrupt network access. The following tips can help you troubleshoot issues and apply firewall rules more safely on Ubuntu systems.
Before applying restrictive firewall rules on a remote server, always ensure that SSH access (typically port 22) is explicitly allowed from your current IP address. A common safe workflow is:
If you lose access, you may need to use your provider’s recovery or web console to restore connectivity.
iptables evaluates rules from top to bottom within each chain. Because of this:
-A adds them to the end of the chain, while inserting rules with -I places them earlier, which can change how traffic is matched.If traffic is not matching as expected, review the rule order with:
- sudo iptables -L -n --line-numbers
After modifying firewall rules, always confirm that they are active and behaving as expected:
- sudo iptables -L -n -v
Test connectivity to critical services, especially SSH and any web services you rely on, from another session or from a separate host before closing your current terminal.
Remember that iptables rules are not persistent by default. After saving your rules with netfilter-persistent, reboot your server and verify that the rules are still loaded:
- sudo iptables -L -n -v
This verification step helps ensure that your firewall configuration survives system restarts and that no rules were missed when you saved your changes.
The examples in this guide configure IPv4 rules only. On Ubuntu 24.04, IPv6 is typically enabled by default. If you do not configure ip6tables or nftables, services may still be reachable over IPv6 even when IPv4 appears locked down.
If you are not sure whether IPv6 is active on your server, check your network interfaces and listening services, and make sure your firewall policy covers the protocols you are using.
When building or modifying a firewall:
Taking an incremental approach reduces the risk of accidental outages and makes debugging much easier.
iptables is used to create and manage firewall rules on Linux systems. You can use it to allow or block traffic based on criteria such as ports, protocols, source or destination IP addresses, and network interfaces. It is also commonly used to manage NAT rules for scenarios like masquerading and port forwarding, and to control forwarding behavior when a host routes traffic between networks.
In other words, it can protect a single server’s services (host firewalling) and it can help implement gateway-style networking features when needed.
Yes. Many systems and tools still rely on iptables, and on Ubuntu 24.04 the iptables command is commonly used through the iptables-nft compatibility layer. You will also still see it used in automation, troubleshooting, and environments that expect an iptables-style interface.
That said, nftables is the recommended long-term framework for Linux firewalling, so it is worth learning if you are building new policies from scratch.
iptables is the traditional interface for configuring netfilter firewall rules, while nftables is the newer framework designed to replace it. On modern Ubuntu releases, iptables commands often program rules via nftables under the hood, but the configuration model and tooling are different.
In practice, this means you may see differences when you inspect rules (for example, with nft list ruleset) even if you created them with iptables. If you want to confirm which backend you are using, check sudo iptables --version and look for nf_tables in the output on Ubuntu 24.04.
You typically allow inbound SSH on port 22 with a rule like the one shown in the SSH section of this guide. If your OUTPUT policy is not ACCEPT, you may also need the corresponding rule that allows established outbound traffic for SSH responses.
If you are connecting from a fixed IP address, restricting SSH to your source IP or subnet is a safer default than allowing SSH from anywhere. After adding rules, confirm that they are in place with sudo iptables -L -n -v and test connectivity from a second session before you close your existing SSH connection.
You can block an IP address by adding a rule to drop (or reject) traffic from that source address. This guide includes an example that drops all traffic from a specific source IP using the -s option.
If you want the client to get an immediate “connection refused” instead of a silent drop, use REJECT instead of DROP. If the IP is still getting through, check rule order and consider inserting the rule near the top of the chain with -I so it matches before broader allow rules.
Resetting rules typically means flushing the current rules, deleting any custom chains, and restoring your default policies. A common approach is to flush rules (iptables -F) and delete user-defined chains (iptables -X), then set your default policies explicitly.
If you have configured NAT rules, you may also need to clear those separately (for example, by flushing the nat table) so you do not leave old forwarding behavior behind.
Be careful when doing this on a remote server, because clearing rules or setting a restrictive default policy can immediately disconnect your SSH session.
On Ubuntu, a common approach is to install iptables-persistent and save your rules with netfilter-persistent so they are restored on boot. After saving, reboot and verify that the rules are still present to confirm persistence.
On many systems, these rules are stored in files such as /etc/iptables/rules.v4 and /etc/iptables/rules.v6.
If you maintain separate IPv6 rules, make sure you also save and restore those rules, because IPv4 persistence alone will not cover IPv6 traffic.
If you block SSH or related access by mistake, you may lose remote connectivity to the server. In that situation, use your provider’s recovery console or web console to log in and correct the firewall rules, then verify that SSH access is allowed before re-applying any restrictive policies.
When you regain console access, listing rules with line numbers (for example, sudo iptables -L -n --line-numbers) can make it easier to identify and remove the rule that caused the lockout.
If you are using saved rules for persistence, you can often recover by fixing the saved ruleset and rebooting, but you should still confirm access from a second session before you rely on a reboot.
In this guide, we covered common iptables commands, including safe baseline rules, service-specific allow rules, and examples for NAT and port forwarding. Because modern Ubuntu releases typically run iptables through the iptables-nft compatibility layer, these commands still apply, but it is also worth becoming familiar with nftables for long-term firewall management.
As you apply changes, remember to validate your effective ruleset, avoid SSH lockouts, account for IPv6 if it is enabled, and configure persistence with iptables-persistent and netfilter-persistent so your rules survive reboots.
If you’re looking for help determining how your firewall should be set up, check out this tutorial: How To Choose an Effective Firewall Policy to Secure your Servers.
To learn more about iptables and Linux, check out the following articles:
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Software Engineer @ DigitalOcean. Former Señor Technical Writer (I no longer update articles or respond to comments). Expertise in areas including Ubuntu, PostgreSQL, MySQL, and more.
With over 6 years of experience in tech publishing, Mani has edited and published more than 75 books covering a wide range of data science topics. Known for his strong attention to detail and technical knowledge, Mani specializes in creating clear, concise, and easy-to-understand content tailored for developers.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hello, Thanks again for your tutorial, as usual they are very good and very clear. Just a problem I have, I read it on my android phone (Samsung Galaxy Note 4) under chrome and the message box about “Infrastructure as a Newsletter” can’t be removed…
Thanks for this really good tutorial! Question: If I block ALL ports except ssh and 80, and even then restrict 80 to only allow incoming connections from Cloudflare’s range, I know it’ll work. But will it interfere with any of DigitalOcean’s management tools like backups and monitoring? Or do they operate at a lower, more direct level?
By the way, I think it would be useful to add to the tutorial the ability to block a range. For example, as I understand it:
Block 15.15.15.x sudo iptables -A INPUT -s 15.15.15.0/24 -j DROP
Block 15.15.x.x sudo iptables -A INPUT -s 15.15.0.0/16 -j DROP
Block entire 15.x.x.x (use with caution!) sudo iptables -A INPUT -s 15.0.0.0/8 -j DROP
Someone correct me if I’m wrong, but I’ve been using /16 to block ranges of baddies with success in the past!
Hey, correct me if I’m wrong, but in the section ‘Allow All Incoming HTTP and HTTPS’, shouldn’t the second firewall rule be:
sudo iptables -A OUTPUT -p tcp -m multiport --sports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
as opposed to
sudo iptables -A OUTPUT -p tcp -m multiport --dports 80,443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
?
Hi, great article - well written and easy to follow as always. Small note - when i was testing out the rules for POP3,
sudo iptables -A INPUT -i -p tcp --dport 110 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
i encountered the error
"Bad argument `tcp’ "
The problem seems to lie with the “-i” after “INPUT”. You might want to double check that command - what worked for me is
sudo iptables -A INPUT -p tcp --dport 110 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
This is a great tutorial series! Not only is it well written, but it seems to be the only one on the net that explains the basics, and gives the steps necessary to succeed.
But… I followed the instructions above for iptables & iptables-persistent on Ubuntu 15.10, I get this error:
$ sudo invoke-rc.d iptables-persistent save
/usr/sbin/invoke-rc.d: 631: /usr/sbin/invoke-rc.d: /etc/init.d/iptables-persistent: not found
invoke-rc.d: initscript iptables-persistent, action "save" failed.
Any ideas what to do about that? Thanks!
Is there a way to allow SFTP from specific IP but block ssh for all incoming traffic at port 22. Traffic for SSH is anyways moved to a different port but I want SFTP to run for specific IP’s on port 22.
Hi Just a quick addition to this…
You can use the invoke method to save the iptables rules or this:
service iptables save
Tested on centOS7 and Ubuntu14.04
I’m loving the tutorial, everything has worked first time around using a Raspberry PI & headless Raspian.
I was wondering if you could help me with the IPTables rules though, I’m trying to add a second VPN connection (tun1), this connection will be accepting incoming connections so I can access my network when away from home. Could you provide some guidance on I how I could add this functionality?
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.