{"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-10-27T20:49:41","modified_gmt":"2026-10-27T20:49:41","slug":"iptables-tutorial","status":"publish","type":"post","link":"\/au\/tutorials\/iptables-tutorial\/","title":{"rendered":"Iptables tutorial: How to configure a Linux firewall on VPS"},"content":{"rendered":"<?xml encoding=\"utf-8\" ?><p class=\"wp-block-paragraph\">Iptables is a Linux firewall tool that lets you control traffic to and from your VPS by configuring rules to allow, block, forward, and filter data packets. It works through the netfilter framework in the Linux kernel and gives you precise control over which packets reach your server.&nbsp;<\/p><p class=\"wp-block-paragraph\">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. Both UFW and nftables are viable alternatives depending on your needs.<\/p><p class=\"wp-block-paragraph\">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><h2 class=\"wp-block-heading h-t-title-2\" id=\"h-what-is-iptables\">What is iptables?<\/h2><p class=\"wp-block-paragraph\">Iptables is a command-line firewall tool that manages Linux firewall rules. It works via the netfilter framework, a packet-filtering system built into the Linux kernel. Every packet that enters or leaves your server passes through netfilter. Iptables supplies the rules that decide whether to allow, block, or handle the traffic.<\/p><p class=\"wp-block-paragraph\">Iptables handles IPv4 traffic. For IPv6, you need ip6tables. This uses the same syntax but operates on a different set of rules.<\/p><p class=\"wp-block-paragraph\">Understanding iptables starts with knowing these 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. Iptables applies the target if the packet matches,&nbsp;<\/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 class=\"wp-block-paragraph\">Basic <a data-click-id=\"hgr-post-content-link-vps-security\" href=\"\/au\/tutorials\/vps-security\/\">VPS security<\/a> configurations use the filter table containing 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 h-t-title-3\">How does iptables work?<\/h3><p class=\"wp-block-paragraph\">Iptables evaluates packets one by one, from top to bottom. For each packet, it starts at the top of a chain and checks the rules in order until it finds a match. When a packet matches a rule, iptables applies that rule&rsquo;s target (such as ACCEPT or DROP) and stops checking the remaining rules in the same chain.<\/p><p class=\"wp-block-paragraph\">Rule order is critical. An earlier rule can allow or block traffic before iptables ever evaluates later rules. If a broad DROP rule appears before your SSH allow rule, matching traffic is dropped immediately, and the SSH rule is never reached.<\/p><p class=\"wp-block-paragraph\">There are two ways to add rules:&nbsp;<\/p><ol class=\"wp-block-list\">\n<li>The <strong>-A<\/strong> flag appends a rule to the bottom of a chain.<\/li>\n\n\n\n<li>The <strong>-I<\/strong> flag inserts a rule at a specific position.&nbsp;&nbsp;<\/li>\n<\/ol><p class=\"wp-block-paragraph\">You&rsquo;ll lock yourself out if you append a broad DROP rule before your SSH allow rule. Adding rules in the right order prevents that.<\/p><p class=\"wp-block-paragraph\">Always add essential allow rules (especially for SSH) before adding restrictive firewall rules to block or drop traffic.<\/p><h3 class=\"wp-block-heading h-t-title-3\">What is the difference between iptables, ip6tables, and nftables?<\/h3><p class=\"wp-block-paragraph\">While iptables handles IPv4 firewall rules, ip6tables handles IPv6 firewall rules using the same command syntax. That said, the two rule sets are completely separate, so rules in iptables don&rsquo;t affect IPv6 traffic, and vice versa.<\/p><p class=\"wp-block-paragraph\">Nftables is the newer Linux firewall framework. It replaces both iptables and ip6tables, handling both IPv4 and IPv6 traffic in a single rule set using a cleaner syntax. On modern Ubuntu versions, iptables commands can run through an nftables backend transparently, meaning your iptables rules are actually stored and processed by nftables even though you continue using the familiar iptables syntax.<\/p><p class=\"wp-block-paragraph\">For users who want simpler firewall management on Ubuntu without writing iptables rules directly, UFW is covered later in this guide.<\/p><figure tabindex=\"0\" class=\"wp-block-table\"><table><tbody><tr><td><strong>Tool<\/strong><\/td><td><strong>Handles<\/strong><\/td><td><strong>Key points<\/strong><\/td><\/tr><tr><td><strong>iptables<\/strong><\/td><td>IPv4 only<\/td><td>Uses classic syntax. Rules apply only to IPv4 traffic and have no effect on IPv6<\/td><\/tr><tr><td><strong>ip6tables<\/strong><\/td><td>IPv6 only<\/td><td>Uses the same command syntax as iptables. Rules are completely separate from iptables and apply only to IPv6 traffic<\/td><\/tr><tr><td><strong>nftables<\/strong><\/td><td>IPv4 and IPv6<\/td><td>Newer Linux firewall framework that replaces both iptables and ip6tables. Uses a single rule set for both protocols and cleaner syntax. On modern Ubuntu, iptables commands often run through an nftables backend. Iptables rules are processed by nftables<\/td><\/tr><\/tbody><\/table><\/figure><h2 class=\"wp-block-heading h-t-title-2\" id=\"h-how-to-configure-iptables-on-ubuntu-vps\">How to configure iptables on Ubuntu VPS<\/h2><p class=\"wp-block-paragraph\">The safest way to <a data-click-id=\"hgr-post-content-link-set-up-a-vps\" href=\"\/au\/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 class=\"wp-block-paragraph\">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 h-t-title-3\">1. Check and install iptables<\/h3><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>iptables --version&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">You&rsquo;ll know iptables is already installed if the command returns a version number. 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 class=\"wp-block-paragraph\">If iptables is not installed, run:<\/p><pre class=\"wp-block-code\"><code>sudo apt update&nbsp;\n\nsudo apt install iptables&nbsp;<\/code><\/pre><h3 class=\"wp-block-heading h-t-title-3\">2. List existing iptables rules<\/h3><p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">List all current rules with verbose output and line numbers:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -L -v -n --line-numbers&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 h-t-title-3\">3. Allow SSH before changing firewall rules<\/h3><p class=\"wp-block-paragraph\">    <div class=\"announcement-block announcement-block--warning\">\n        <span class=\"announcement-block__heading\">\n            <svg width=\"24\" height=\"26\" viewBox=\"0 0 24 26\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n                d=\"M12 23.5C17.799 23.5 22.5 18.799 22.5 13C22.5 7.20101 17.799 2.5 12 2.5C6.20101 2.5 1.5 7.20101 1.5 13C1.5 18.799 6.20101 23.5 12 23.5ZM13.637 8.65198C13.637 7.74791 12.9041 7.01501 12 7.01501C11.0959 7.01501 10.363 7.74791 10.363 8.65198C10.5335 10.5375 10.875 14.383 10.875 14.383C10.875 15.0043 11.3787 15.508 12 15.508C12.6213 15.508 13.125 15.0043 13.125 14.383V14.38L13.637 8.65198ZM11.9927 16.714C11.3714 16.714 10.8677 17.2177 10.8677 17.839C10.8677 18.4603 11.3714 18.964 11.9927 18.964H12.0073C12.6286 18.964 13.1323 18.4603 13.1323 17.839C13.1323 17.2177 12.6286 16.714 12.0073 16.714H11.9927Z\"\n                fill=\"#BE1025\"\/>\n            <\/svg>\n            Warning        <\/span>\n        <p class=\"announcement-block__content\">\n            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    <\/div>\n\n    &nbsp;<\/p><p class=\"wp-block-paragraph\">Allow SSH before adding any DROP or REJECT rules. The default SSH port is 22:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">This rule allows SSH from any IP address. For stronger security, restrict it to a trusted IP or range later. If you&rsquo;ve <a data-click-id=\"hgr-post-content-link-changed-your-vps-ssh-port\" href=\"\/au\/tutorials\/how-to-change-ssh-port-vps\/\">changed your VPS SSH port<\/a>, replace 22 with that port number instead. Check your server configuration by opening this file if you&rsquo;re not sure:<\/p><pre class=\"wp-block-code\"><code>sudo nano \/etc\/ssh\/sshd_config&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">Passwords are the most common SSH authentication method, but <a data-click-id=\"hgr-post-content-link-setting-up-ssh-keys\" href=\"\/au\/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 class=\"wp-block-paragraph\">After adding the SSH rule, keep your current session open and test access from a second terminal window before saving any restrictive rules. It&rsquo;s safe to continue if the second connection succeeds.<\/p><h3 class=\"wp-block-heading h-t-title-3\">4. Add basic iptables firewall rules<\/h3><p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\"><strong>Allow localhost traffic<\/strong><\/p><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo iptables -A INPUT -i lo -j ACCEPT&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Allow established and related connections<\/strong><\/p><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Allow HTTP and HTTPS<\/strong><\/p><p class=\"wp-block-paragraph\">Open ports 80 and 443 to allow web traffic:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT&nbsp;\n\nsudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Block a specific IP address<\/strong><\/p><p class=\"wp-block-paragraph\">To drop all traffic from a single IP address:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -s 192.0.2.1 -j DROP&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Block an IP range<\/strong><\/p><p class=\"wp-block-paragraph\">Use the <strong>iprange<\/strong> module to drop traffic from a range of addresses:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -m iprange --src-range 192.0.2.1-192.0.2.254 -j DROP&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Drop invalid packets<\/strong><\/p><p class=\"wp-block-paragraph\">Invalid packets don&rsquo;t belong to any known connection and are often used in network attacks. Drop them before they reach your services:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Drop all other incoming traffic<\/strong><\/p><p class=\"wp-block-paragraph\">Add this rule last. It drops any incoming traffic that hasn&rsquo;t matched an earlier ACCEPT rule. Placing it before your allow rules will block everything, including SSH:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -A INPUT -j DROP&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">You can set the INPUT chain policy to DROP instead (`iptables -P INPUT DROP`). Both approaches work; the rule above is simpler and safer while you&rsquo;re still testing.<\/p><h3 class=\"wp-block-heading h-t-title-3\">5. Open common service ports with iptables<\/h3><p class=\"wp-block-paragraph\">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 or 587<\/td><td>Only if running a mail server (use 587 for client submission)<\/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 class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo iptables -A INPUT -p tcp --dport 3306 -s 192.0.2.1 -j ACCEPT&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">Replace <strong>192.0.2.1<\/strong> with the IP address of the machine that needs database access.<\/p><h3 class=\"wp-block-heading h-t-title-3\">6. Delete or flush iptables rules<\/h3><p class=\"wp-block-paragraph\">Deleting a specific rule removes it without touching the rest of your configuration; flushing removes all rules at once.<\/p><p class=\"wp-block-paragraph\"><strong>Deleting a specific rule<\/strong><\/p><p class=\"wp-block-paragraph\">To remove one rule without affecting the rest, use its line number. First, list rules with line numbers:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -L INPUT --line-numbers&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">Then delete the rule at the position you want to remove. To delete rule number 3 from the INPUT chain:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -D INPUT 3&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Flushing all rules<\/strong><\/p><p class=\"wp-block-paragraph\">To remove all rules at once, use the <strong>-F<\/strong> flag:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -F&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">    <div class=\"announcement-block announcement-block--warning\">\n        <span class=\"announcement-block__heading\">\n            <svg width=\"24\" height=\"26\" viewBox=\"0 0 24 26\" fill=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\n                <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n                d=\"M12 23.5C17.799 23.5 22.5 18.799 22.5 13C22.5 7.20101 17.799 2.5 12 2.5C6.20101 2.5 1.5 7.20101 1.5 13C1.5 18.799 6.20101 23.5 12 23.5ZM13.637 8.65198C13.637 7.74791 12.9041 7.01501 12 7.01501C11.0959 7.01501 10.363 7.74791 10.363 8.65198C10.5335 10.5375 10.875 14.383 10.875 14.383C10.875 15.0043 11.3787 15.508 12 15.508C12.6213 15.508 13.125 15.0043 13.125 14.383V14.38L13.637 8.65198ZM11.9927 16.714C11.3714 16.714 10.8677 17.2177 10.8677 17.839C10.8677 18.4603 11.3714 18.964 11.9927 18.964H12.0073C12.6286 18.964 13.1323 18.4603 13.1323 17.839C13.1323 17.2177 12.6286 16.714 12.0073 16.714H11.9927Z\"\n                fill=\"#BE1025\"\/>\n            <\/svg>\n            Warning        <\/span>\n        <p class=\"announcement-block__content\">\n            Flushing the rules on a remote VPS removes all allow rules and all block rules.&nbsp; Flushing leaves you locked out if your default chain policy is DROP. When the default policy is ACCEPT, flushing exposes all ports. Know your default policy before flushing.        <\/p>\n    <\/div>\n\n    &nbsp;<\/p><p class=\"wp-block-paragraph\"><strong>DROP vs REJECT<\/strong><\/p><p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Use DROP for public-facing rules where you don&rsquo;t 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 h-t-title-3\">7. Save iptables rules permanently<\/h3><p class=\"wp-block-paragraph\">Iptables rules are stored in memory and don&rsquo;t survive a reboot by default. To keep your rules after restarting the VPS, save them to a file.<\/p><p class=\"wp-block-paragraph\"><strong>Install iptables-persistent<\/strong><\/p><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo apt install iptables-persistent&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">During installation, you&rsquo;ll be prompted to save your current IPv4 and IPv6 rules. Choose <strong>Yes<\/strong> for both.<\/p><p class=\"wp-block-paragraph\"><strong>Save rules manually<\/strong><\/p><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo netfilter-persistent save <\/code><\/pre><p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\"><strong>Restore rules manually<\/strong><\/p><p class=\"wp-block-paragraph\">When you need to reload saved rules without rebooting:<\/p><pre class=\"wp-block-code\"><code>sudo iptables-restore &lt; \/etc\/iptables\/rules.v4&nbsp;\n\nsudo ip6tables-restore &lt; \/etc\/iptables\/rules.v6&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\"><strong>Verify after reboot<\/strong><\/p><p class=\"wp-block-paragraph\">After restarting your VPS, confirm that the rules loaded correctly:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -L -v -n&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">The output should match the rules you saved before rebooting.<\/p><h2 class=\"wp-block-heading h-t-title-2\" id=\"h-how-to-configure-nat-and-port-forwarding-with-iptables\">How to configure NAT and port forwarding with iptables<\/h2><p class=\"wp-block-paragraph\">NAT and port forwarding let your VPS act as a gateway, router, <a data-click-id=\"hgr-post-content-link-vpn-endpoint\" href=\"\/au\/tutorials\/how-to-set-up-a-linux-vpn-server-with-openvpn\/\">VPN endpoint<\/a>, or traffic forwarder. They route packets between networks or redirect traffic from one port to another. These rules use the NAT table, not the filter table.<\/p><p class=\"wp-block-paragraph\">Port forwarding also requires IP forwarding to be enabled in the kernel. To enable it temporarily:<\/p><pre class=\"wp-block-code\"><code>sudo sysctl -w net.ipv4.ip_forward=1&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">To make it permanent, add the following line to <strong>\/etc\/sysctl.conf<\/strong>:<\/p><pre class=\"wp-block-code\"><code>net.ipv4.ip_forward=1&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">Then apply the change:<\/p><pre class=\"wp-block-code\"><code>sudo sysctl -p&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">To forward traffic arriving on port 80 to a different host on your network:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.0.2.1:80&nbsp;\n\nsudo iptables -t nat -A POSTROUTING -j MASQUERADE&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">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=\"wp-block-code\"><code>sudo iptables -A FORWARD -p tcp -d 192.0.2.1 --dport 80 -j ACCEPT<\/code><\/pre><h2 class=\"wp-block-heading h-t-title-2\" id=\"h-iptables-vs-ufw-which-firewall-tool-should-you-use\">iptables vs UFW: Which firewall tool should you use?<\/h2><p class=\"wp-block-paragraph\">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. But that control comes at a cost &ndash; the syntax is verbose, rule order is strict, and mistakes on a remote VPS can lock you out instantly.<\/p><p class=\"wp-block-paragraph\">UFW (Uncomplicated Firewall) is a frontend for iptables that simplifies common firewall tasks on Ubuntu. When you only need to allow SSH, HTTP, and HTTPS, you can <a data-click-id=\"hgr-post-content-link-configure-a-firewall-on-ubuntu-using-ufw\" href=\"\/au\/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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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><figure tabindex=\"0\" class=\"wp-block-table\"><table><tbody><tr><td><strong>Tool<\/strong><\/td><td><strong>Best for<\/strong><\/td><td><strong>Strengths<\/strong><\/td><td><strong>Trade-offs<\/strong><\/td><\/tr><tr><td><strong>iptables<\/strong><\/td><td>Basic Ubuntu VPS rules (SSH, HTTP, HTTPS)<\/td><td>Simple commands; low risk of rule-order mistakes<\/td><td>Limited control for custom rules, NAT, or complex setups<\/td><\/tr><tr><td><strong>nftables<\/strong><\/td><td>Custom rules, NAT, port forwarding, strict rule order, or existing scripts<\/td><td>Full control over every aspect of the firewall<\/td><td>Verbose syntax; rule order is strict; easy to lock yourself out on a remote VPS<\/td><\/tr><\/tbody><\/table><\/figure><h2 class=\"wp-block-heading h-t-title-2\" id=\"h-how-to-troubleshoot-iptables-rules\">How to troubleshoot iptables rules<\/h2><p class=\"wp-block-paragraph\">When iptables rules are not behaving as expected, start by checking your active rules with verbose output and line numbers:<\/p><pre class=\"wp-block-code\"><code>sudo iptables -L -v -n --line-numbers&nbsp;<\/code><\/pre><p class=\"wp-block-paragraph\">Check three things in the command output: rule order, line numbers, and the packet and byte counters.<\/p><p class=\"wp-block-paragraph\">Rule order determines which rule applies first. Line numbers help you delete or insert rules at a specific position. Counters show whether traffic is actually matching a rule.<\/p><p class=\"wp-block-paragraph\">On modern Ubuntu, also check the active backend:<\/p><pre class=\"wp-block-code\"><code>iptables --version<\/code><\/pre><p class=\"wp-block-paragraph\">If the output includes <strong>(nf_tables)<\/strong>, your iptables commands are running through the nftables backend.<\/p><p class=\"wp-block-paragraph\">Rule order determines which rule applies first; misplaced ACCEPT or DROP rules produce unexpected results. 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 class=\"wp-block-paragraph\">On modern Ubuntu systems, verify whether iptables is running through the nftables backend. This can affect how rules are stored and applied.<\/p><p class=\"wp-block-paragraph\"><strong>SSH lockout recovery<\/strong><\/p><p class=\"wp-block-paragraph\">Getting locked out of your VPS via SSH is a common and disruptive mistake. An <a data-click-id=\"hgr-post-content-link-ssh-connection-refused\" href=\"\/au\/tutorials\/ssh-connection-refused\/\">SSH connection refused<\/a> error after applying firewall rules usually means a restrictive rule is blocking port 22 before the ACCEPT rule is reached.&nbsp;<\/p><p class=\"wp-block-paragraph\"><a data-click-id=\"hgr-post-content-link-hostinger-vps\" href=\"\/au\/vps-hosting\">Hostinger VPS<\/a> users can regain access via the browser-based hPanel terminal without an SSH connection. Then, you can delete the blocking rule or flush all rules to restore access.<\/p><figure class=\"wp-block-image size-large\"><a data-click-id=\"hgr-post-content-link-au-vps-hosting\" aria-label=\"Vps hosting\" class=\"hgr-tutorials-cta hgr-tutorials-cta-vps-hosting\" href=\"\/au\/vps-hosting\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"300\" src=\"https:\/\/imagedelivery.net\/LqiWLm-3MGbYHtFuUbcBtA\/wp-content\/uploads\/sites\/2\/2023\/02\/VPS-hosting-banner.png\/w=1024,h=1024,fit=scale-down\" alt=\"\" class=\"wp-image-77934\"  sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><p class=\"wp-block-paragraph\"><strong>When to reset rules<\/strong><\/p><p class=\"wp-block-paragraph\">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 h-t-title-2\" id=\"h-key-takeaways-for-using-iptables\">Key takeaways for using iptables<\/h2><p class=\"wp-block-paragraph\">Iptables is still a solid choice when you need precise firewall control, custom rules, NAT, port forwarding, and compatibility with existing scripts.&nbsp;<\/p><p class=\"wp-block-paragraph\">For straightforward Ubuntu VPS setups where you only need to allow SSH, HTTP, and HTTPS, UFW gets the job done with less complexity. When you&rsquo;re building a new server from scratch, nftables is worth learning as the modern long-term replacement for iptables.<\/p><p class=\"wp-block-paragraph\">Firewall rules decide which traffic reaches your VPS, but they don&rsquo;t stop repeated login attempts from addresses that are technically allowed through. To block those brute-force attacks automatically, <a data-click-id=\"hgr-post-content-link-configure-fail2ban\" href=\"\/au\/tutorials\/fail2ban-configuration\/\">configure Fail2Ban<\/a> alongside your iptables rules for stronger overall protection.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Iptables is a Linux firewall tool that lets you control traffic to and from your VPS by configuring rules to allow, block, forward, and filter data packets. It works through the netfilter framework in the Linux kernel and gives you precise control over which packets reach your server.&nbsp; Iptables organizes rules into tables, chains, matches, [&#8230;]<\/p>\n<p><a class=\"btn btn-secondary understrap-read-more-link\" href=\"\/au\/tutorials\/iptables-tutorial\/\">Read More&#8230;<\/a><\/p>\n","protected":false},"author":356,"featured_media":139619,"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","footnotes":""},"categories":[22670],"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-PH","link":"https:\/\/www.hostinger.com\/ph\/tutorials\/iptables-tutorial\/","default":0},{"locale":"en-MY","link":"https:\/\/www.hostinger.com\/my\/tutorials\/iptables-tutorial\/","default":0},{"locale":"en-GB","link":"https:\/\/www.hostinger.com\/uk\/tutorials\/iptables-tutorial\/","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},{"locale":"es-AR","link":"https:\/\/www.hostinger.com\/ar\/tutoriales\/como-asegurar-linux-con-iptables-firewall\/","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":"pt-PT","link":"https:\/\/www.hostinger.com\/pt\/tutoriais\/tutorial-iptables","default":0}],"_links":{"self":[{"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/posts\/5614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/users\/356"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/comments?post=5614"}],"version-history":[{"count":69,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/posts\/5614\/revisions"}],"predecessor-version":[{"id":151723,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/posts\/5614\/revisions\/151723"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/media\/139619"}],"wp:attachment":[{"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/media?parent=5614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/categories?post=5614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hostinger.com\/au\/tutorials\/wp-json\/wp\/v2\/tags?post=5614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}