{"id":5614,"date":"2019-11-29T03:51:46","date_gmt":"2019-11-29T03:51:46","guid":{"rendered":"https:\/\/www.hostinger.com\/tutorials\/?p=5614"},"modified":"2026-05-28T17:46:30","modified_gmt":"2026-05-28T17:46:30","slug":"iptables-tutorial","status":"publish","type":"post","link":"\/my\/tutorials\/iptables-tutorial","title":{"rendered":"Iptables tutorial: securing VPS with Linux firewall"},"content":{"rendered":"<p>Iptables is a Linux firewall tool that lets you control which traffic reaches your VPS by configuring rules for allowing, blocking, forwarding, and filtering packets.&nbsp;<\/p><p>It works through the netfilter framework built into the Linux kernel and remains one of the most widely used firewall solutions for Linux servers.<\/p><p>Iptables organizes rules into tables, chains, matches, and targets. The safest setup order starts with allowing SSH and established connections before applying any DROP rules. Rules must be saved explicitly to persist after a reboot.&nbsp;<\/p><p>Both UFW and nftables are viable alternatives depending on your needs.<\/p><p>The main steps to configure iptables are:<\/p><ol class=\"wp-block-list\">\n<li>Check and install iptables.<\/li>\n\n\n\n<li>List existing rules.<\/li>\n\n\n\n<li>Allow SSH before applying restrictive rules.<\/li>\n\n\n\n<li>Add basic firewall rules.<\/li>\n\n\n\n<li>Open common service ports.<\/li>\n\n\n\n<li>Delete or flush rules.<\/li>\n\n\n\n<li>Save rules permanently.<\/li>\n<\/ol><p><\/p><h2 class=\"wp-block-heading\" id=\"h-what-is-iptables\">What is iptables?<\/h2><p>Iptables is a command-line firewall tool that manages Linux firewall rules via the netfilter framework, a packet-filtering system built directly into the Linux kernel. Every packet that enters or leaves your server passes through netfilter, and iptables gives you the rules that decide what happens to it.<\/p><p>Iptables handles IPv4 traffic. For IPv6, you need ip6tables, which uses the same syntax but operates on a separate rule set.<\/p><p>Understanding iptables starts with five core concepts:<\/p><figure tabindex=\"0\" class=\"wp-block-table\"><table><tbody><tr><td><strong>Concept<\/strong><\/td><td><strong>What it is<\/strong><\/td><\/tr><tr><td>Table<\/td><td>A collection of chains grouped by purpose. The main tables are <strong>filter<\/strong>, <strong>nat<\/strong>, and <strong>mangle<\/strong>.<\/td><\/tr><tr><td>Chain<\/td><td>A list of rules within a table. Built-in chains include <strong>INPUT<\/strong>, <strong>OUTPUT<\/strong>, and <strong>FORWARD<\/strong>.<\/td><\/tr><tr><td>Rule<\/td><td>A condition that a packet is checked against. If the packet matches, iptables applies the target.<\/td><\/tr><tr><td>Match<\/td><td>The criteria used to evaluate a packet &ndash; source IP, destination port, protocol, and so on.<\/td><\/tr><tr><td>Target<\/td><td>The action taken when a packet matches a rule: <strong>ACCEPT<\/strong>, <strong>DROP<\/strong>, <strong>RETURN<\/strong>, or <strong>REJECT<\/strong>.<\/td><\/tr><\/tbody><\/table><\/figure><p>Most basic <a href=\"\/my\/tutorials\/vps-security\">VPS security<\/a> configurations use the filter table, which contains three default chains. INPUT handles incoming packets to the server. OUTPUT handles packets leaving the server. FORWARD handles packets routed to a destination other than the server.<\/p><h3 class=\"wp-block-heading\">How does iptables work?<\/h3><p>Iptables checks each packet against rules in a chain from top to bottom. The first rule that matches the packet applies, and iptables stops checking the rest of that chain. Rule order matters because an earlier rule can allow or block traffic before any later rules are evaluated.<\/p><p>There are two ways to add rules: the <strong>-A<\/strong> flag appends a rule to the bottom of a chain, and the <strong>-I<\/strong> flag inserts a rule at a specific position. That&rsquo;s useful when you need a rule evaluated before existing ones. If you append a broad DROP rule before your SSH allow rule, you will lock yourself out; adding rules in the right order prevents that.<\/p><p>Always add essential allow rules &ndash; especially for SSH &ndash; before any rules that block or drop traffic.<\/p><h3 class=\"wp-block-heading\">What is the difference between iptables, ip6tables, and nftables?<\/h3><p>Iptables handles IPv4 firewall rules. ip6tables handles IPv6 firewall rules using the same command syntax, but the two rule sets are completely separate &ndash; a rule in iptables has no effect on IPv6 traffic, and vice versa.<\/p><p>Nftables is the newer Linux firewall framework that replaces both iptables and ip6tables. It handles IPv4 and IPv6 in a single rule set and uses a cleaner syntax. On modern Ubuntu versions, iptables commands may run through an nftables backend transparently, meaning your iptables rules are actually stored and processed by nftables under the hood.<\/p><p>For users who want simpler firewall management on Ubuntu without writing iptables rules directly, UFW is covered later in this guide.<\/p><h2 class=\"wp-block-heading\" id=\"h-how-to-configure-iptables-on-ubuntu-vps\">How to configure iptables on Ubuntu VPS<\/h2><p>The safest way to<a href=\"\/my\/tutorials\/how-to-set-up-vps\"> set up a VPS<\/a> firewall with iptables is to build rules in a specific order: check existing rules first, then allow SSH, established connections, and required service ports before blocking anything.&nbsp;<\/p><p>Apply DROP rules last &ndash; skipping this order can lock administrators out of a server they can no longer reach.<\/p><h3 class=\"wp-block-heading\">1. Check and install iptables<\/h3><p>Iptables comes preinstalled on most Linux distributions. This tutorial uses Ubuntu VPS as the main example. To check whether iptables is already available on your system, run:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">iptables --version<\/pre><p>If the command returns a version number, iptables is already installed. On modern Ubuntu versions, this may show a reference to the nftables backend, meaning iptables commands are processed by nftables under the hood. The syntax stays the same either way.<\/p><p>If iptables is not installed, run:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt update\n\nsudo apt install iptables<\/pre><h3 class=\"wp-block-heading\">2. List existing iptables rules<\/h3><p>Check your existing rules before adding new ones. An existing rule may already allow or block traffic you intend to configure, and adding duplicate or conflicting rules causes unpredictable behavior.<\/p><p>List all current rules with verbose output and line numbers:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -L -v -n --line-numbers<\/pre><p>The <strong>-n<\/strong> flag prints IP addresses and port numbers numerically instead of resolving them to hostnames, which is faster and easier to read. Line numbers identify each rule&rsquo;s position in the chain &ndash; you will need them to delete or insert rules at specific positions.&nbsp;<\/p><p>The packet and byte counters in the output show whether traffic actually matches each rule, which helps with troubleshooting.<\/p><h3 class=\"wp-block-heading\">3. Allow SSH before changing firewall rules<\/h3><p>    <p class=\"warning\">\n        <strong>Warning! <\/strong>Applying restrictive firewall rules before allowing SSH will lock you out of your VPS. There is no error message &ndash; the connection simply drops, and you lose access.    <\/p>\n    \n\n\n\n<\/p><p>Allow SSH before adding any DROP or REJECT rules. The default SSH port is 22:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT<\/pre><p>If you&rsquo;ve <a href=\"\/my\/tutorials\/how-to-change-ssh-port-vps\">changed your VPS&rsquo; SSH port<\/a>, replace <strong>22<\/strong> with that port number instead. If you&rsquo;re not sure, check your server configuration by opening this file:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo nano \/etc\/ssh\/sshd_config<\/pre><p>Passwords are the most common SSH authentication method, but <a href=\"\/my\/tutorials\/how-to-set-up-ssh-keys\">setting up SSH keys<\/a> is more secure and worth doing before you lock down your firewall.<\/p><p>After adding the SSH rule, keep your current session open and test access from a second terminal window before saving any restrictive rules. If the second connection succeeds, it is safe to continue.<\/p><h3 class=\"wp-block-heading\">4. Add basic iptables firewall rules<\/h3><p>The remaining rules build out your firewall in order of priority. Add them in the sequence below to avoid blocking traffic you need.<\/p><p><strong>Allow localhost traffic<\/strong><\/p><p>Traffic on the loopback interface stays within the server itself. Blocking it breaks internal communication between services running on the same machine, such as a web application connecting to a local database:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -i lo -j ACCEPT<\/pre><p><strong>Allow established and related connections<\/strong><\/p><p>This rule allows traffic that belongs to connections your server already initiated or accepted. Without it, responses to outgoing requests get blocked:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT<\/pre><p><strong>Allow HTTP and HTTPS<\/strong><\/p><p>Open ports 80 and 443 to allow web traffic:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT\n\nsudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT<\/pre><p><strong>Block a specific IP address<\/strong><\/p><p>To drop all traffic from a single IP address:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -s 192.0.2.1 -j DROP<\/pre><p><strong>Block an IP range<\/strong><\/p><p>Use the <strong>iprange<\/strong> module to drop traffic from a range of addresses:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -m iprange --src-range 192.0.2.1-192.0.2.254 -j DROP<\/pre><p><strong>Drop invalid packets<\/strong><\/p><p>Invalid packets do not belong to any known connection and are often used in network attacks. Drop them before they reach your services:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP<\/pre><p><strong>Drop all other incoming traffic<\/strong><\/p><p>Add this rule last. It drops any incoming traffic that has not matched an earlier ACCEPT rule. Placing it before your allow rules will block everything, including SSH:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -j DROP<\/pre><h3 class=\"wp-block-heading\">5. Open common service ports with iptables<\/h3><p>Each service running on your VPS uses a specific port, and iptables needs an explicit rule to allow traffic on that port:<\/p><figure tabindex=\"0\" class=\"wp-block-table\"><table><tbody><tr><td><strong>Service<\/strong><\/td><td><strong>Protocol<\/strong><\/td><td><strong>Port<\/strong><\/td><td><strong>Notes<\/strong><\/td><\/tr><tr><td>SSH<\/td><td>TCP<\/td><td>22<\/td><td>Change the default port if possible<\/td><\/tr><tr><td>HTTP<\/td><td>TCP<\/td><td>80<\/td><td>Required for unencrypted web traffic<\/td><\/tr><tr><td>HTTPS<\/td><td>TCP<\/td><td>443<\/td><td>Required for encrypted web traffic<\/td><\/tr><tr><td>MySQL<\/td><td>TCP<\/td><td>3306<\/td><td>Restrict to trusted IPs only<\/td><\/tr><tr><td>PostgreSQL<\/td><td>TCP<\/td><td>5432<\/td><td>Restrict to trusted IPs only<\/td><\/tr><tr><td>SMTP<\/td><td>TCP<\/td><td>25<\/td><td>Only if running a mail server<\/td><\/tr><tr><td>IMAP<\/td><td>TCP<\/td><td>993<\/td><td>Only if running a mail server<\/td><\/tr><\/tbody><\/table><\/figure><p>Database ports like 3306 and 5432 should never be opened to the public internet. Restrict them to a trusted IP address or a private network interface instead:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A INPUT -p tcp --dport 3306 -s 192.0.2.1 -j ACCEPT<\/pre><p>Replace <strong>192.0.2.1<\/strong> with the IP address of the machine that needs database access.<\/p><h3 class=\"wp-block-heading\">6. Delete or flush iptables rules<\/h3><p>Deleting a specific rule removes it without touching the rest of your configuration; flushing removes all rules at once.<\/p><p><strong>Deleting a specific rule<\/strong><\/p><p>To remove one rule without affecting the rest, use its line number. First, list rules with line numbers:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -L INPUT --line-numbers<\/pre><p>Then delete the rule at the position you want to remove. To delete rule number 3 from the INPUT chain:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -D INPUT 3<\/pre><p><strong>Flushing all rules<\/strong><\/p><p>To remove all rules at once, use the <strong>-F<\/strong> flag:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -F<\/pre><p>    <p class=\"warning\">\n        <strong>Warning!<\/strong> Flushing the rules on a remote VPS removes all allow rules and all block rules. If your default chain policy is DROP, flushing leaves you locked out. If the default policy is ACCEPT, flushing exposes all ports. Know your default policy before flushing.    <\/p>\n    \n\n\n\n<\/p><p><strong>DROP vs REJECT<\/strong><\/p><p>When blocking traffic, you have two options. DROP silently discards the packet: the sender gets no response and the connection eventually times out. REJECT discards the packet and sends an error response to the sender, making troubleshooting easier but also confirming to the sender that the port exists.<\/p><p>Use DROP for public-facing rules where you do not want to reveal information about your server. Use REJECT in internal or development environments where faster feedback is useful.<\/p><h3 class=\"wp-block-heading\">7. Save iptables rules permanently<\/h3><p>Iptables rules are stored in memory and do not survive a reboot by default. To keep your rules after restarting the VPS, save them to a file.<\/p><p><strong>Install iptables-persistent<\/strong><\/p><p>The <strong>iptables-persistent<\/strong> package automatically saves and loads rules. On Ubuntu, installing it also installs <strong>netfilter-persistent<\/strong>, which is the underlying service that loads the saved rules at boot:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo apt install iptables-persistent<\/pre><p>During installation, you will be prompted to save your current IPv4 and IPv6 rules. Choose <strong>Yes<\/strong> for both.<\/p><p><strong>Save rules manually<\/strong><\/p><p>If you installed <strong>iptables-persistent<\/strong>, the <strong>\/etc\/iptables\/<\/strong> directory already exists. After adding or changing rules, save them so they persist through reboots:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo netfilter-persistent save<\/pre><p>This writes both IPv4 and IPv6 rules to <strong>\/etc\/iptables\/rules.v4<\/strong> and <strong>\/etc\/iptables\/rules.v6<\/strong>, respectively.&rdquo;<\/p><p><strong>Restore rules manually<\/strong><\/p><p>If you need to reload saved rules without rebooting:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables-restore &lt; \/etc\/iptables\/rules.v4\n\nsudo ip6tables-restore &lt; \/etc\/iptables\/rules.v6<\/pre><p><strong>Verify after reboot<\/strong><\/p><p>After restarting your VPS, confirm that the rules loaded correctly:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -L -v -n<\/pre><p>The output should match the rules you saved before rebooting.<\/p><h2 class=\"wp-block-heading\" id=\"h-how-to-configure-nat-and-port-forwarding-with-iptables\">How to configure NAT and port forwarding with iptables<\/h2><p>NAT and port forwarding are used when your VPS acts as a gateway, router,<a href=\"\/my\/tutorials\/how-to-set-up-a-linux-vpn-server-with-openvpn\"> VPN endpoint<\/a>, or traffic forwarder &ndash; routing packets between networks or redirecting traffic from one port to another. These rules use the NAT table rather than the filter table used in the steps above.<\/p><p>Port forwarding also requires IP forwarding to be enabled at the kernel level. To enable it temporarily:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo sysctl -w net.ipv4.ip_forward=1<\/pre><p>To make it permanent, add the following line to <strong>\/etc\/sysctl.conf<\/strong>:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">net.ipv4.ip_forward=1<\/pre><p>Then apply the change:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo sysctl -p<\/pre><p>To forward traffic arriving on port 80 to a different host on your network:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.0.2.1:80\n\nsudo iptables -t nat -A POSTROUTING -j MASQUERADE<\/pre><p>If your <strong>FORWARD<\/strong> chain policy is set to <strong>DROP<\/strong>, you also need to allow the forwarded traffic explicitly:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -A FORWARD -p tcp -d 192.0.2.1 --dport 80 -j ACCEPT<\/pre><h2 class=\"wp-block-heading\" id=\"h-iptables-vs-ufw-which-firewall-tool-should-you-use\">iptables vs UFW: Which firewall tool should you use?<\/h2><p>Iptables gives you direct control over every aspect of your firewall, such as rule order, NAT, port forwarding, custom chains, and compatibility with existing scripts. That control comes at a cost: the syntax is verbose, rule order is unforgiving, and mistakes on a remote VPS can lock you out instantly.<\/p><p>UFW (Uncomplicated Firewall) is a frontend for iptables that simplifies common firewall tasks on Ubuntu. If you only need to allow SSH, HTTP, and HTTPS, you can <a href=\"\/my\/tutorials\/how-to-configure-firewall-on-ubuntu-using-ufw\">configure a firewall on Ubuntu using UFW<\/a> with a handful of commands and no risk of rule-ordering mistakes.<\/p><p>Nftables is the more modern long-term replacement for iptables. It handles IPv4 and IPv6 in a single rule set and uses a cleaner syntax, but it requires learning a new framework from scratch.<\/p><p>The right tool depends on what you need:<\/p><ul class=\"wp-block-list\">\n<li><strong>Use UFW if you only need basic rules<\/strong> like SSH, HTTP, and HTTPS on an Ubuntu VPS.<\/li>\n\n\n\n<li><strong>Use iptables if you need custom rules<\/strong>, NAT, port forwarding, strict rule order, or compatibility with existing scripts.<\/li>\n\n\n\n<li><strong>Use nftables if you are setting up a new server<\/strong> and want a modern firewall framework without legacy constraints.<\/li>\n<\/ul><h2 class=\"wp-block-heading\" id=\"h-how-to-troubleshoot-iptables-rules\">How to troubleshoot iptables rules<\/h2><p>When iptables rules are not behaving as expected, start by checking your active rules with verbose output and line numbers:<\/p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">sudo iptables -L -v -n --line-numbers<\/pre><p>Check four things: rule order, line numbers, packet and byte counters, and the active backend.&nbsp;<\/p><p>Rule order determines which rule applies first; misplaced ACCEPT or DROP rules are the most common source of unexpected behavior. Counters show whether traffic is actually matching a rule, which helps you confirm whether a rule is working or being bypassed entirely.&nbsp;<\/p><p>On modern Ubuntu systems, also verify whether iptables is running through the nftables backend, as this can affect how rules are stored and applied.<\/p><p><strong>SSH lockout recovery<\/strong><\/p><p>Getting locked out of your VPS via SSH is the most disruptive iptables mistake. An<a href=\"\/my\/tutorials\/ssh-connection-refused\"> SSH connection refused<\/a> error after applying firewall rules usually means an overly restrictive rule is blocking port 22 before the ACCEPT rule is reached.&nbsp;<\/p><p><a href=\"\/my\/vps-hosting\">Hostinger VPS<\/a> users can regain access via the browser-based hPanel terminal without an SSH connection. From there, you can delete the blocking rule or flush all rules to restore access.<\/p><?xml encoding=\"utf-8\" ?><figure class=\"wp-block-image size-large\"><a href=\"\/my\/vps-hosting\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"1024\" height=\"300\" src=\"https:\/\/www.hostinger.com\/tutorials\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner-1024x300.png\" alt=\"\" class=\"wp-image-77934\" srcset=\"https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner.png 1024w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-300x88.png 300w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-150x44.png 150w, https:\/\/www.hostinger.com\/my\/tutorials\/wp-content\/uploads\/sites\/45\/2023\/02\/VPS-hosting-banner-768x225.png 768w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><p><strong>When to reset rules<\/strong><\/p><p>Resetting all rules with <strong>iptables -F<\/strong> is useful when your rule set has become too complex to debug or when you want to start from a clean state.<\/p><h2 class=\"wp-block-heading\" id=\"h-key-takeaways-for-using-iptables\">Key takeaways for using iptables<\/h2><p>Iptables remains a solid choice for precise firewall control, custom rules, NAT, port forwarding, and compatibility with existing scripts.&nbsp;<\/p><p>For straightforward Ubuntu VPS setups where you only need to allow SSH, HTTP, and HTTPS, UFW gets the job done with less complexity. If you are building a new server from scratch, nftables is worth learning as the modern long-term replacement for iptables.<\/p><p>Firewall rules control which traffic reaches your VPS, but they do not stop repeated login attempts from addresses that are technically allowed through. To automatically block brute-force attacks, <a href=\"\/my\/tutorials\/fail2ban-configuration\">configure Fail2Ban<\/a> alongside your iptables rules for a more comprehensive security setup.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Iptables is a Linux firewall tool that lets you control which traffic reaches your VPS by configuring rules for allowing, blocking, forwarding, and filtering packets.&nbsp; It works through the netfilter framework built into the Linux kernel and remains one of the most widely used firewall solutions for Linux servers. Iptables organizes rules into tables, chains, [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"\/my\/tutorials\/iptables-tutorial\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":356,"featured_media":43073,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Iptables tutorial: How to set up and use Linux firewall","rank_math_description":"Iptables is a powerful firewall tool for Linux. Read our Iptables tutorial and learn everything you need to know to secure your server.","rank_math_focus_keyword":"iptables tutorial, linux firewall","footnotes":""},"categories":[22639],"tags":[],"class_list":["post-5614","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vps"],"hreflangs":[{"locale":"en-US","link":"https:\/\/www.hostinger.com\/tutorials\/iptables-tutorial","default":0},{"locale":"pt-BR","link":"https:\/\/www.hostinger.com\/br\/tutoriais\/tutorial-iptables","default":0},{"locale":"fr-FR","link":"https:\/\/www.hostinger.com\/fr\/tutoriels\/iptables","default":0},{"locale":"es-ES","link":"https:\/\/www.hostinger.com\/es\/tutoriales\/como-asegurar-linux-con-iptables-firewall","default":0},{"locale":"id-ID","link":"https:\/\/www.hostinger.com\/id\/tutorial\/iptables-tutorial","default":0},{"locale":"en-UK","link":"https:\/\/www.hostinger.com\/uk\/tutorials\/iptables-tutorial","default":0},{"locale":"en-MY","link":"https:\/\/www.hostinger.com\/my\/tutorials\/iptables-tutorial","default":0},{"locale":"en-PH","link":"https:\/\/www.hostinger.com\/ph\/tutorials\/iptables-tutorial","default":0},{"locale":"es-MX","link":"https:\/\/www.hostinger.com\/mx\/tutoriales\/como-asegurar-linux-con-iptables-firewall","default":0},{"locale":"es-CO","link":"https:\/\/www.hostinger.com\/co\/tutoriales\/como-asegurar-linux-con-iptables-firewall","default":0},{"locale":"es-AR","link":"https:\/\/www.hostinger.com\/ar\/tutoriales\/como-asegurar-linux-con-iptables-firewall","default":0},{"locale":"pt-PT","link":"https:\/\/www.hostinger.com\/pt\/tutoriais\/tutorial-iptables","default":0},{"locale":"en-IN","link":"https:\/\/www.hostinger.com\/in\/tutorials\/iptables-tutorial","default":0},{"locale":"en-CA","link":"https:\/\/www.hostinger.com\/ca\/tutorials\/iptables-tutorial","default":0},{"locale":"en-AU","link":"https:\/\/www.hostinger.com\/au\/tutorials\/iptables-tutorial","default":0},{"locale":"en-NG","link":"https:\/\/www.hostinger.com\/ng\/tutorials\/iptables-tutorial","default":0}],"_links":{"self":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/5614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/users\/356"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/comments?post=5614"}],"version-history":[{"count":63,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/5614\/revisions"}],"predecessor-version":[{"id":130555,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/posts\/5614\/revisions\/130555"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/media\/43073"}],"wp:attachment":[{"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/media?parent=5614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/categories?post=5614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostinger.com\/my\/tutorials\/wp-json\/wp\/v2\/tags?post=5614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}