{"id":164,"date":"2026-10-19T22:09:05","date_gmt":"2026-10-19T20:09:05","guid":{"rendered":"https:\/\/nodeguard.io\/blog\/?p=164"},"modified":"2026-10-19T22:09:07","modified_gmt":"2026-10-19T20:09:07","slug":"how-to-configure-ufw-firewall-on-ubuntu","status":"publish","type":"post","link":"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/","title":{"rendered":"How to Configure UFW Firewall on Ubuntu: A Powerful 9-Rule Blueprint"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Learning how to configure UFW firewall on Ubuntu is the single highest-return hour you will ever spend on a new server. A fresh cloud instance is reachable from every IP address on the planet within seconds of booting, and automated scanners find it long before you finish your first coffee. The UFW firewall is the tool Ubuntu ships specifically to close that window \u2014 and it is genuinely uncomplicated once you understand the handful of rules that actually matter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide walks through nine rules that take a bare Ubuntu server from wide open to properly locked down. Follow them in order and you will end up with a UFW firewall that denies everything by default, permits exactly the traffic your applications need, survives reboots, and \u2014 critically \u2014 never locks you out of your own machine. <\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_86 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">In This Guide<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#What_Is_UFW_and_Why_It_Is_the_Default_Ubuntu_Firewall\" >What Is UFW and Why It Is the Default Ubuntu Firewall<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#UFW_iptables_and_nftables_how_they_relate\" >UFW, iptables and nftables: how they relate<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Before_You_Configure_the_UFW_Firewall_A_4-Point_Pre-Flight_Check\" >Before You Configure the UFW Firewall: A 4-Point Pre-Flight Check<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#How_to_Configure_UFW_Firewall_on_Ubuntu_The_9_Rules_at_a_Glance\" >How to Configure UFW Firewall on Ubuntu: The 9 Rules at a Glance<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_1_%E2%80%94_Install_and_Inspect_the_UFW_Firewall\" >Rule 1 \u2014 Install and Inspect the UFW Firewall<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_2_%E2%80%94_Set_Default_Policies_Before_You_Enable_Anything\" >Rule 2 \u2014 Set Default Policies Before You Enable Anything<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_3_%E2%80%94_Allow_SSH_First_Every_Single_Time\" >Rule 3 \u2014 Allow SSH First, Every Single Time<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_4_%E2%80%94_Open_Only_the_Ports_Your_Services_Actually_Need\" >Rule 4 \u2014 Open Only the Ports Your Services Actually Need<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_5_%E2%80%94_Write_Tighter_UFW_Rules_with_Sources_Subnets_and_Interfaces\" >Rule 5 \u2014 Write Tighter UFW Rules with Sources, Subnets and Interfaces<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_6_%E2%80%94_Rate-Limit_SSH_and_Other_Brute-Forced_Ports\" >Rule 6 \u2014 Rate-Limit SSH and Other Brute-Forced Ports<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_7_%E2%80%94_Read_UFW_Status_Like_an_Auditor\" >Rule 7 \u2014 Read UFW Status Like an Auditor<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_8_%E2%80%94_Handle_Docker_IPv6_and_Cloudflare_Before_They_Bite\" >Rule 8 \u2014 Handle Docker, IPv6 and Cloudflare Before They Bite<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Docker_bypasses_your_UFW_rules\" >Docker bypasses your UFW rules<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#IPv6_is_on_by_default_and_often_forgotten\" >IPv6 is on by default and often forgotten<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Cloudflare_and_other_proxies_change_what_you_are_filtering\" >Cloudflare and other proxies change what you are filtering<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Managing_UFW_Rules_After_the_Firewall_Is_Live\" >Managing UFW Rules After the Firewall Is Live<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Rule_9_%E2%80%94_Log_Monitor_and_Maintain_the_Ubuntu_Firewall\" >Rule 9 \u2014 Log, Monitor and Maintain the Ubuntu Firewall<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#5_Mistakes_That_Will_Lock_You_Out_of_Your_Server\" >5 Mistakes That Will Lock You Out of Your Server<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#UFW_Firewall_Command_Cheat_Sheet\" >UFW Firewall Command Cheat Sheet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Frequently_Asked_Questions_About_the_UFW_Firewall\" >Frequently Asked Questions About the UFW Firewall<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Is_UFW_enabled_by_default_on_Ubuntu\" >Is UFW enabled by default on Ubuntu?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Do_UFW_rules_survive_a_reboot\" >Do UFW rules survive a reboot?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Should_I_use_UFW_or_iptables_directly\" >Should I use UFW or iptables directly?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Does_the_UFW_firewall_slow_down_my_server\" >Does the UFW firewall slow down my server?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Why_does_ufw_status_show_every_rule_twice\" >Why does ufw status show every rule twice?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#I_locked_myself_out_What_now\" >I locked myself out. What now?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Does_UFW_protect_against_DDoS_attacks\" >Does UFW protect against DDoS attacks?<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/nodeguard.io\/blog\/how-to-configure-ufw-firewall-on-ubuntu\/#Final_Thoughts\" >Final Thoughts<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_Is_UFW_and_Why_It_Is_the_Default_Ubuntu_Firewall\"><\/span>What Is UFW and Why It Is the Default Ubuntu Firewall<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">UFW stands for Uncomplicated Firewall, and the name is an accurate description of its job. Every Linux firewall ultimately runs on Netfilter, the packet-filtering subsystem built into the kernel. Netfilter is powerful and completely unforgiving: writing raw rules by hand means memorising chains, tables, match extensions and jump targets, and a single typo can silently drop every packet on the box.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">UFW is a front end that translates human-readable commands into those low-level rules for you. When you type <code>sudo ufw allow 443\/tcp<\/code>, UFW writes the kernel entries, orders them correctly, applies them to both IPv4 and IPv6, and makes the change persistent across reboots. That is why Canonical made it the default Ubuntu firewall tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">UFW is not a <em>different<\/em> firewall \u2014 it is the same kernel engine with a sane interface on top. UFW rules are real kernel rules: no proxy, no userspace daemon inspecting packets, and no measurable throughput penalty.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"UFW_iptables_and_nftables_how_they_relate\"><\/span>UFW, iptables and nftables: how they relate<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Modern Ubuntu uses the nftables backend underneath the familiar <code>iptables<\/code> command, and UFW sits above that stack. In practice: don&#8217;t run UFW alongside another manager such as firewalld, because two tools fighting over one rule set produces results nobody can debug; and rules you add directly with <code>iptables<\/code> outside UFW are usually wiped the next time UFW reloads.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One caveat before we start: a UFW firewall is one layer, not a complete security posture. It controls which ports accept connections. It does not patch your software or stop an attack that arrives through a legitimately open port 443. Treat it as the floor you build on, not the ceiling.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Before_You_Configure_the_UFW_Firewall_A_4-Point_Pre-Flight_Check\"><\/span>Before You Configure the UFW Firewall: A 4-Point Pre-Flight Check<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Every lockout story starts with someone skipping this section. Four minutes here saves a support ticket and a console session later.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>1. Confirm how you connect.<\/strong> Know your SSH port before you touch anything. If you have moved SSH away from 22 \u2014 a sensible hardening step covered in our guide to <a href=\"https:\/\/nodeguard.io\/blog\/how-to-set-up-an-ubuntu-vps\">set up an Ubuntu VPS<\/a> \u2014 you must allow that custom port, not the default. Check with <code>sudo ss -tlnp | grep sshd<\/code> and write the number down.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>2. Know your out-of-band access.<\/strong> Every decent provider offers a web or serial console that works independently of SSH. Find yours and verify you can log in. If a UFW firewall rule goes wrong, the console is how you fix it without a reinstall.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>3. Inventory your listening services.<\/strong> Run <code>sudo ss -tulnp<\/code>. Anything bound to <code>0.0.0.0<\/code> or <code>[::]<\/code> is reachable from outside and needs an explicit allow rule or \u2014 better \u2014 rebinding to localhost. Services on <code>127.0.0.1<\/code> need no UFW rules at all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>4. Check for a competing firewall.<\/strong> Reused images sometimes ship firewalld or custom iptables scripts. Check with <code>systemctl status firewalld<\/code> and remove anything that conflicts before enabling the UFW firewall. A provider-level network firewall, on the other hand, complements the Ubuntu firewall rather than replacing it \u2014 run both.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_to_Configure_UFW_Firewall_on_Ubuntu_The_9_Rules_at_a_Glance\"><\/span>How to Configure UFW Firewall on Ubuntu: The 9 Rules at a Glance<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here is the full sequence before we go deep on each one. If you already know UFW and just want the order of operations, this list is your guide.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Install the UFW firewall and inspect its starting state<\/li>\n\n\n\n<li>Set default policies before enabling anything<\/li>\n\n\n\n<li>Allow SSH first, every single time<\/li>\n\n\n\n<li>Open only the ports your services actually need<\/li>\n\n\n\n<li>Write tighter UFW rules with sources, subnets and interfaces<\/li>\n\n\n\n<li>Rate-limit SSH and other brute-forced ports<\/li>\n\n\n\n<li>Read UFW status like an auditor<\/li>\n\n\n\n<li>Handle Docker, IPv6 and Cloudflare before they bite<\/li>\n\n\n\n<li>Log, monitor and mantain the Ubuntu firewall<\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works-1024x576.webp\" alt=\"How the UFW firewall filters inbound traffic on an Ubuntu server\" class=\"wp-image-165\" srcset=\"https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works-1024x576.webp 1024w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works-300x169.webp 300w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works-768x432.webp 768w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works-900x506.webp 900w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-how-it-works.webp 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Inbound packets are tested against your UFW rules in order; anything that matches no rule hits the default deny policy<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_1_%E2%80%94_Install_and_Inspect_the_UFW_Firewall\"><\/span>Rule 1 \u2014 Install and Inspect the UFW Firewall<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">UFW ships with Ubuntu Server and Ubuntu Desktop, so installation is usually a formality. Confirm it anyway, because minimal and container-derived images sometimes strip it out.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update\nsudo apt install ufw -y\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now look at what you are starting from:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status verbose\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">On a fresh system the UFW status reads <code>Status: inactive<\/code>. Inactive does not mean &#8220;safe with no rules&#8221; \u2014 it means the UFW firewall is not filtering anything, and every listening service is exposed to the internet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do not enable it yet. Enabling with no rules is exactly how people lock themselves out, because the default incoming policy is deny and SSH is not yet permitted. Rules first, enable last \u2014 that ordering is the backbone of this blueprint.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">While you are here, list the application profiles UFW knows about with <code>sudo ufw app list<\/code>. Packages like OpenSSH and Nginx register named profiles, and <code>sudo ufw app info \"Nginx Full\"<\/code> shows exactly which ports a profile opens. Check before you trust one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_2_%E2%80%94_Set_Default_Policies_Before_You_Enable_Anything\"><\/span>Rule 2 \u2014 Set Default Policies Before You Enable Anything<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Default policies are the rules that apply when no specific rule matches. They are the foundation of the whole UFW firewall, and there is one correct starting configuration for a server:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw default deny incoming\nsudo ufw default allow outgoing\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Deny incoming means nothing reaches your server unless you explicitly permit it. This default-deny posture is the only sane choice for an internet-facing machine; the alternative \u2014 allow everything, then block known-bad things \u2014 requires predicting every threat in advance.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Allow outgoing means your server can still run <code>apt<\/code> updates, DNS lookups and API calls. Locking down outbound traffic is a legitimate advanced technique, but it breaks things constantly and belongs in a hardened environment with a documented dependency list.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A third policy, <code>sudo ufw default deny routed<\/code>, blocks traffic forwarded between interfaces. On a normal web server nothing should be routed, so it&#8217;s a free improvement \u2014 VPN gateways and Docker hosts are the exception (see Rule 8).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Setting default policies does not activate the UFW firewall; it only records what happens once it is active, so you can set them safely before enabling.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_3_%E2%80%94_Allow_SSH_First_Every_Single_Time\"><\/span>Rule 3 \u2014 Allow SSH First, Every Single Time<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the rule that saves your weekend. Before you enable the firewall, allow the port you are currently connected on.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If SSH runs on the default port:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow OpenSSH\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Or, equivalently and more explicitly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 22\/tcp\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you moved SSH to a custom port, allow that instead and give it a label so future-you understands the rule:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 2222\/tcp comment 'SSH custom port'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Comments matter: six months from now, <code>2222\/tcp ALLOW IN Anywhere # SSH custom port<\/code> tells you everything, while uncommented UFW rules never get cleaned up.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now \u2014 and only now \u2014 switch the UFW firewall on:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw enable\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">UFW warns that this may disrupt existing SSH connections. Because you allowed SSH first, it will not. Then <strong>open a second terminal and start a new SSH session.<\/strong> Your existing session survives through connection tracking even if the rules are wrong, so it proves nothing. Only a brand-new connection is a real test. If it fails, your first session is still open: run <code>sudo ufw disable<\/code>, fix the rule, try again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once SSH works, harden it with key-based authentication \u2014 our guide on how to <a href=\"https:\/\/nodeguard.io\/blog\/how-to-set-up-ssh-keys-on-ubuntu\">set up SSH keys on Ubuntu<\/a> pairs naturally with this, because a UFW firewall that permits port 22 is only as strong as what listens on it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_4_%E2%80%94_Open_Only_the_Ports_Your_Services_Actually_Need\"><\/span>Rule 4 \u2014 Open Only the Ports Your Services Actually Need<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With SSH secured, open what your workload genuinely requires \u2014 and nothing else. Every open port is a surface an attacker can probe.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A standard web server needs HTTP and HTTPS:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 80\/tcp comment 'HTTP'\nsudo ufw allow 443\/tcp comment 'HTTPS'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Port 80 is still worth opening even on an HTTPS-only site, because Let&#8217;s Encrypt HTTP-01 validation uses it and most sites redirect 80 to 443 anyway.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Other common patterns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow 25\/tcp comment 'SMTP'\nsudo ufw allow 587\/tcp comment 'Submission'\nsudo ufw allow 993\/tcp comment 'IMAPS'\nsudo ufw allow 53 comment 'DNS'\nsudo ufw allow 51820\/udp comment 'WireGuard VPN'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>sudo ufw allow 53<\/code> without a protocol opens both TCP and UDP, which DNS needs. For almost everything else, name the protocol. Port ranges use a colon and require one: <code>sudo ufw allow 60000:60010\/udp<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ports that should almost never face the world: 3306 (MySQL), 5432 (PostgreSQL), 6379 (Redis), 27017 (MongoDB) and 9200 (Elasticsearch). If the database lives on the same server as the app, bind it to <code>127.0.0.1<\/code> and it needs no UFW rules at all. If it lives elsewhere, Rule 5 shows how to open it to one host only. Exposed databases remain one of the most common causes of real-world data loss.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_5_%E2%80%94_Write_Tighter_UFW_Rules_with_Sources_Subnets_and_Interfaces\"><\/span>Rule 5 \u2014 Write Tighter UFW Rules with Sources, Subnets and Interfaces<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Basic allow rules open a port to everyone. The real power of UFW rules is restricting <em>who<\/em> can reach them, using the <code>from<\/code> and <code>to<\/code> syntax.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Allow a single trusted IP address to reach your database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow from 203.0.113.45 to any port 5432 proto tcp comment 'App server to Postgres'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Allow an entire private subnet \u2014 typical for a provider&#8217;s internal network:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow from 10.0.0.0\/8 to any port 3306 proto tcp comment 'Private network to MySQL'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Restrict SSH to your office or home IP, which eliminates essentially all brute-force noise:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow from 198.51.100.22 to any port 22 proto tcp comment 'Office SSH'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Be careful with that last one on a dynamic home IP \u2014 if your address changes, you are off to the provider console. Keep a jump-host rule as backup, or rely on rate limiting (Rule 6) instead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also scope UFW rules to one network interface, useful on servers with public and private NICs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw allow in on ens4 to any port 6379 proto tcp comment 'Redis on private NIC only'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>deny<\/code> silently drops traffic and gives a scanner nothing. <code>reject<\/code> sends an explicit refusal, which is friendlier on internal networks:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw deny from 192.0.2.0\/24 comment 'Abusive range'\nsudo ufw reject from 10.0.5.0\/24 to any port 8080 comment 'Deprecated internal client'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Order matters: UFW rules are evaluated top to bottom and the first match wins, so a broad allow above a narrow deny makes the deny pointless. Insert by position to fix that:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw insert 1 deny from 192.0.2.66 comment 'Blocked scanner'\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_6_%E2%80%94_Rate-Limit_SSH_and_Other_Brute-Forced_Ports\"><\/span>Rule 6 \u2014 Rate-Limit SSH and Other Brute-Forced Ports<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">UFW has a built-in brute-force defence that almost nobody uses, and it is one line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw limit 22\/tcp comment 'SSH rate limited'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <code>limit<\/code> verb denies a source IP that has attempted six or more connections to that port within thirty seconds. Legitimate users never trip it. Automated password-guessing bots trip it constantly, and once tripped they are dropped rather than being allowed to keep trying.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you already created a plain allow rule for SSH, replace it rather than stacking a second rule on top:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw delete allow 22\/tcp\nsudo ufw limit 22\/tcp comment 'SSH rate limited'\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Rate limiting works on any TCP port, so it is equally useful in front of an admin panel. It is not a substitute for Fail2Ban, which bans on failed-login patterns from application logs \u2014 run both. One caveat: limits track source IPs, so many users behind one office NAT can collectively trip them. Allow that range explicitly above the limit rule.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_7_%E2%80%94_Read_UFW_Status_Like_an_Auditor\"><\/span>Rule 7 \u2014 Read UFW Status Like an Auditor<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Checking UFW status is not a one-time formality. It is how you verify the UFW firewall does what you think it does.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status verbose\nsudo ufw status numbered\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The verbose UFW status shows active state, logging level, default policies and every rule. Read the policy line first \u2014 <code>deny (incoming), allow (outgoing), deny (routed)<\/code> is the target \u2014 then ask whether you can still justify each rule. The numbered UFW status is what you use for editing and for auditing a server you inherited. Rules with <code>Anywhere<\/code> as the source are open to the whole internet: fine for 80 and 443, suspicious for anything else. A <code>(v6)<\/code> twin of every rule is normal \u2014 that is the IPv6 copy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, verify from the outside. An Ubuntu firewall that looks correct locally but behaves differently from the internet is one you don&#8217;t understand. From another machine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>nmap -Pn -p 22,80,443,3306 your-server-ip\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Opened ports should report <code>open<\/code>; everything else <code>filtered<\/code> \u2014 exactly what a default-deny UFW firewall should produce. If a port you never opened reports <code>open<\/code>, something is bypassing your UFW rules, which brings us to Rule 8. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules-1024x576.webp\" alt=\"how to configure ufw firewall on ubuntu\" class=\"wp-image-166\" srcset=\"https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules-1024x576.webp 1024w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules-300x169.webp 300w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules-768x432.webp 768w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules-900x506.webp 900w, https:\/\/nodeguard.io\/blog\/wp-content\/uploads\/2026\/10\/ufw-firewall-9-rules.webp 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">The nine-rule blueprint, from installation through long-term maintenance.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_8_%E2%80%94_Handle_Docker_IPv6_and_Cloudflare_Before_They_Bite\"><\/span>Rule 8 \u2014 Handle Docker, IPv6 and Cloudflare Before They Bite<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Three situations routinely break an otherwise correct UFW firewall. Knowing about them in advance is far cheaper than discovering them in production.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Docker_bypasses_your_UFW_rules\"><\/span>Docker bypasses your UFW rules<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This surprises almost everyone. When you publish a container port with <code>-p 8080:80<\/code>, Docker writes its own kernel rules that are evaluated <em>before<\/em> UFW&#8217;s. Your default-deny policy is never consulted, and the container is exposed even though the UFW status shows no rule permitting it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The clean fix is to bind published ports to localhost and put a reverse proxy in front:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>docker run -p 127.0.0.1:8080:80 my-image\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In a Compose file, the same thing looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ports:\n  - \"127.0.0.1:8080:80\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The container is now reachable only from the host, and the UFW firewall is back in control of what the outside world can touch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"IPv6_is_on_by_default_and_often_forgotten\"><\/span>IPv6 is on by default and often forgotten<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">UFW manages IPv6 automatically when <code>IPV6=yes<\/code> is set in <code>\/etc\/default\/ufw<\/code>, which is the default \u2014 confirm with <code>grep IPV6 \/etc\/default\/ufw<\/code>. The failure mode to avoid is disabling IPv6 in UFW while it stays enabled on the network interface: a server filtered on IPv4 and wide open on IPv6.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Cloudflare_and_other_proxies_change_what_you_are_filtering\"><\/span>Cloudflare and other proxies change what you are filtering<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Behind Cloudflare, all legitimate web traffic arrives from the proxy&#8217;s ranges, so you can allow 80 and 443 only from those ranges and stop attackers hitting your origin directly. Automate the range updates, and remember that blocking a proxied visitor in the Ubuntu firewall blocks the proxy, not them \u2014 those bans belong at the edge.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Managing_UFW_Rules_After_the_Firewall_Is_Live\"><\/span>Managing UFW Rules After the Firewall Is Live<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Services change and stale UFW rules quietly accumulate. Delete by number \u2014 the safest method, because you see what you are removing:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw status numbered\nsudo ufw delete 4\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Deleting renumbers everything below, so re-check the numbered UFW status between deletions. You can also delete by matching the rule, as in <code>sudo ufw delete allow 8080\/tcp<\/code>. There is no in-place edit: delete and re-add. Rules persist across <code>disable<\/code>\/<code>enable<\/code> and reboots, <code>sudo ufw reload<\/code> applies edits to config files, and <code>sudo ufw reset<\/code> wipes everything \u2014 never run it over SSH without console access ready.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Back up before significant changes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tar -czf ~\/ufw-backup-$(date +%F).tar.gz \/etc\/ufw \/etc\/default\/ufw\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Better still, keep your UFW rules in a provisioning script. A UFW firewall you can rebuild from version control is one you can reason about.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rule_9_%E2%80%94_Log_Monitor_and_Maintain_the_Ubuntu_Firewall\"><\/span>Rule 9 \u2014 Log, Monitor and Maintain the Ubuntu Firewall<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A UFW firewall nobody watches tells you nothing when something goes wrong. Enable logging:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo ufw logging on\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The default <code>low<\/code> level records blocked packets and suits most servers. <code>medium<\/code> helps while debugging. <code>high<\/code> and <code>full<\/code> will fill a small disk fast \u2014 short diagnostic windows only.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Entries land in the system log:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo grep UFW \/var\/log\/syslog | tail -50\nsudo journalctl -k | grep -i ufw | tail -50\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>[UFW BLOCK]<\/code> entry means the Ubuntu firewall dropped a packet. A steady stream against random ports is normal background scanning \u2014 proof the configuration works. Worry about sudden spikes from one source, or blocks against a port your own app needs, which usually means missing UFW rules rather than an attack.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Maintenance is the part everyone skips. Quarterly, review the numbered UFW status and delete anything you cannot justify in one sentence. Firewalls decay through accumulation, not attack: a twenty-rule UFW firewall you understand beats a sixty-rule one you inherited.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The UFW firewall only protects the host it runs on; patching, SSH keys and unprivileged service users matter just as much. If you are starting fresh, NodeGuard&#8217;s <a href=\"https:\/\/nodeguard.io\/cloud-vps\">Cloud VPS plans<\/a> ship Ubuntu images with UFW ready to configure from first boot.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"5_Mistakes_That_Will_Lock_You_Out_of_Your_Server\"><\/span>5 Mistakes That Will Lock You Out of Your Server<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Enabling before allowing SSH<\/strong> \u2014 the connection drops the moment the UFW firewall activates.<\/li>\n\n\n\n<li><strong>Trusting your open session as proof<\/strong> \u2014 only a freshly opened SSH session tests the rules.<\/li>\n\n\n\n<li><strong>Allowing 22 after moving SSH to 2222<\/strong> \u2014 confirm the real port with <code>ss -tlnp<\/code> first.<\/li>\n\n\n\n<li><strong>Restricting SSH to a dynamic IP<\/strong> \u2014 without a backup path, an ISP change locks you out.<\/li>\n\n\n\n<li><strong>Assuming Docker respects your UFW rules<\/strong> \u2014 published container ports bypass them entirely.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"UFW_Firewall_Command_Cheat_Sheet\"><\/span>UFW Firewall Command Cheat Sheet<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Task<\/th><th>Command<\/th><\/tr><\/thead><tbody><tr><td>Check state and rules<\/td><td><code>sudo ufw status verbose<\/code><\/td><\/tr><tr><td>Numbered rules for editing<\/td><td><code>sudo ufw status numbered<\/code><\/td><\/tr><tr><td>Default deny inbound<\/td><td><code>sudo ufw default deny incoming<\/code><\/td><\/tr><tr><td>Default allow outbound<\/td><td><code>sudo ufw default allow outgoing<\/code><\/td><\/tr><tr><td>Allow SSH by profile<\/td><td><code>sudo ufw allow OpenSSH<\/code><\/td><\/tr><tr><td>Allow a TCP port<\/td><td><code>sudo ufw allow 443\/tcp<\/code><\/td><\/tr><tr><td>Allow a port range<\/td><td><code>sudo ufw allow 60000:60010\/udp<\/code><\/td><\/tr><tr><td>Allow from one IP<\/td><td><code>sudo ufw allow from 203.0.113.45 to any port 5432 proto tcp<\/code><\/td><\/tr><tr><td>Allow from a subnet<\/td><td><code>sudo ufw allow from 10.0.0.0\/8 to any port 3306 proto tcp<\/code><\/td><\/tr><tr><td>Allow on one interface<\/td><td><code>sudo ufw allow in on ens4 to any port 6379 proto tcp<\/code><\/td><\/tr><tr><td>Rate-limit a port<\/td><td><code>sudo ufw limit 22\/tcp<\/code><\/td><\/tr><tr><td>Silently drop a source<\/td><td><code>sudo ufw deny from 192.0.2.0\/24<\/code><\/td><\/tr><tr><td>Insert at a position<\/td><td><code>sudo ufw insert 1 deny from 192.0.2.66<\/code><\/td><\/tr><tr><td>Delete by number<\/td><td><code>sudo ufw delete 4<\/code><\/td><\/tr><tr><td>List app profiles<\/td><td><code>sudo ufw app list<\/code><\/td><\/tr><tr><td>Enable \/ disable<\/td><td><code>sudo ufw enable<\/code> \/ <code>sudo ufw disable<\/code><\/td><\/tr><tr><td>Reload after file edits<\/td><td><code>sudo ufw reload<\/code><\/td><\/tr><tr><td>Wipe everything<\/td><td><code>sudo ufw reset<\/code><\/td><\/tr><tr><td>Turn on logging<\/td><td><code>sudo ufw logging on<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Frequently_Asked_Questions_About_the_UFW_Firewall\"><\/span>Frequently Asked Questions About the UFW Firewall<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Is_UFW_enabled_by_default_on_Ubuntu\"><\/span>Is UFW enabled by default on Ubuntu?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. UFW is installed but starts inactive, so nothing is filtered until you run <code>sudo ufw enable<\/code>. A UFW status of <code>Status: inactive<\/code> on a new server is the normal starting point.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Do_UFW_rules_survive_a_reboot\"><\/span>Do UFW rules survive a reboot?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. UFW rules are stored in <code>\/etc\/ufw\/<\/code> and reapplied at boot once the UFW firewall is enabled. No startup script needed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Should_I_use_UFW_or_iptables_directly\"><\/span>Should I use UFW or iptables directly?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Use UFW unless you have a specific reason not to. Both write kernel rules through the same subsystem, so performance is identical; the difference is readability and error rate. The Ubuntu firewall front end wins for everything except complex routing or programmatically generated rule sets.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Does_the_UFW_firewall_slow_down_my_server\"><\/span>Does the UFW firewall slow down my server?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Not measurably. A few dozen UFW rules add overhead too small to detect. Only <code>high<\/code> or <code>full<\/code> logging causes noticeable disk I\/O.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Why_does_ufw_status_show_every_rule_twice\"><\/span>Why does ufw status show every rule twice?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Those are the IPv4 and IPv6 copies. Entries marked <code>(v6)<\/code> are expected, not duplication to clean up.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"I_locked_myself_out_What_now\"><\/span>I locked myself out. What now?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Log in through your provider&#8217;s web or serial console, run <code>sudo ufw disable<\/code>, correct the rule and re-enable. That is why verifying console access is part of the pre-flight check.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Does_UFW_protect_against_DDoS_attacks\"><\/span>Does UFW protect against DDoS attacks?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Only marginally. A volumetric attack saturates your link before packets reach the Ubuntu firewall, so that protection has to happen upstream at your provider or CDN.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Final_Thoughts\"><\/span>Final Thoughts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Knowing how to configure UFW firewall on Ubuntu comes down to a short, repeatable discipline: deny by default, allow SSH before you enable, open only what you can justify, restrict by source, rate-limit what gets attacked, and review your UFW rules often enough to remember why they exist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The whole setup takes about ten minutes. Do it on your next server before you install anything else, verify it from the outside with a port scan, and schedule a quarterly audit. A UFW firewall you review regularly is worth more than a perfect one you configure once and forget.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Further reading:<\/strong> the <a href=\"https:\/\/documentation.ubuntu.com\/server\/how-to\/security\/firewalls\/\" target=\"_blank\" rel=\"noopener\">official Ubuntu Server firewall documentation<\/a>, the <a href=\"https:\/\/manpages.ubuntu.com\/manpages\/en\/man8\/ufw.8.html\" target=\"_blank\" rel=\"noopener\">ufw man page<\/a>, the <a href=\"https:\/\/help.ubuntu.com\/community\/UFW\" target=\"_blank\" rel=\"noopener\">Ubuntu community UFW guide<\/a>, Docker&#8217;s notes on <a href=\"https:\/\/docs.docker.com\/engine\/network\/packet-filtering-firewalls\/\" target=\"_blank\" rel=\"noopener\">packet filtering and firewalls<\/a>, and the <a href=\"https:\/\/www.cisecurity.org\/benchmark\/ubuntu_linux\" target=\"_blank\" rel=\"noopener\">CIS Benchmarks for Ubuntu Linux<\/a> for a formal hardening baseline.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n","protected":false},"excerpt":{"rendered":"<p>Learning how to configure UFW firewall on Ubuntu is the single highest-return hour you will ever spend on a new server. A\u2026<\/p>\n","protected":false},"author":2,"featured_media":167,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,25],"tags":[85,49,86,75,72,5,7,41,84,34],"class_list":["post-164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security","category-server-management","tag-firewall","tag-linux","tag-network-security","tag-server-security","tag-ssh","tag-sysadmin","tag-ubuntu","tag-ubuntu-server","tag-ufw","tag-vps-security"],"_links":{"self":[{"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/posts\/164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/comments?post=164"}],"version-history":[{"count":1,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/posts\/164\/revisions"}],"predecessor-version":[{"id":168,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/posts\/164\/revisions\/168"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/media\/167"}],"wp:attachment":[{"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/media?parent=164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/categories?post=164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nodeguard.io\/blog\/wp-json\/wp\/v2\/tags?post=164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}