A practical reference for sysadmins configuring ufw on Linux — covering correct rule order, default deny policy, and the exact sequence that prevents SSH lockout.
What is ufw?
ufw (Uncomplicated Firewall) is a frontend for iptables designed to simplify firewall configuration on Linux, particularly on Debian and Ubuntu systems where it is installed by default. It abstracts iptables rule syntax into human-readable commands while maintaining the full power of netfilter packet filtering underneath. For production servers, ufw provides a reliable way to configure a default-deny firewall with specific allow rules for SSH, web traffic, and any other required services — without requiring knowledge of iptables chain and table syntax. The most critical aspect of ufw configuration is rule order: SSH must be explicitly allowed before ufw is enabled, because enabling ufw with a default deny policy immediately blocks all inbound connections including your active SSH session. This is the single most common mistake that causes administrators to lose access to their own servers.
Syntax
ufw status
ufw status verbose
ufw allow ssh
ufw allow 80/tcp
ufw allow from 203.0.113.0/24 to any port 22
ufw default deny incoming
ufw default allow outgoing
ufw enable
ufw disableAlways run ufw allow ssh before ufw enable — this is the rule that prevents lockout. The status verbose command shows the current rules, default policies, and logging status. Use ufw allow from <ip> to any port 22 to restrict SSH to a specific IP range rather than allowing it from anywhere.
Key Options and Commands
| Flag / Parameter | Description | Security Note |
|---|---|---|
ufw allow <service> | Allow traffic on the named service port (uses /etc/services for port lookup) | Use 'ufw allow ssh' not 'ufw allow 22' — named services are easier to audit in status output |
ufw allow <port>/<protocol> | Allow traffic on a specific port and protocol, e.g. 443/tcp | — |
ufw allow from <ip> to any port <port> | Allow a specific source IP or CIDR range to access a specific port | Use to restrict SSH access to known admin IPs only — reduces SSH attack surface to zero for non-listed IPs |
ufw default deny incoming | Set default policy to deny all inbound connections not matched by an allow rule | Must be set before enable — this is the policy that makes the firewall effective |
ufw default allow outgoing | Set default policy to allow all outbound connections | Consider restricting outgoing on high-security servers to prevent exfiltration from compromised processes |
ufw enable | Activate the firewall and persist rules across reboots | Only run after verifying that SSH allow rule is in place — enable with active SSH session at risk |
ufw delete <rule> | Remove a specific rule — use 'ufw status numbered' then 'ufw delete <number>' | — |
ufw logging on | Enable firewall logging to /var/log/ufw.log | Enable on production servers to maintain an audit trail of blocked connection attempts |
Common Use Cases
Enable ufw Without Locking Yourself Out of SSH
The correct order matters. Allow SSH first, set default policies second, then enable. Running ufw enable before adding the SSH allow rule with a default deny policy will immediately terminate your SSH session with no recovery path except an out-of-band console.
ufw allow ssh
ufw default deny incoming
ufw default allow outgoing
ufw allow 80/tcp
ufw allow 443/tcp
ufw enableRestrict SSH Access to a Specific Admin IP
Allowing SSH from anywhere exposes port 22 to continuous brute force attempts from the entire internet. Restricting SSH to a known admin IP or CIDR range reduces the SSH attack surface to near zero — only connections from the specified source are considered.
ufw allow from YOUR.ADMIN.IP/32 to any port 22
ufw delete allow sshView Current Rules and Verify Configuration
After making changes, always verify the active ruleset before relying on it. The status numbered output makes it easy to identify rules by number for deletion or modification.
ufw status numbered
ufw status verboseSecurity Relevance: Rule Ordering Errors and Default Policy Hardening
The most dangerous ufw mistake is enabling it before adding SSH allow rules — a default deny policy immediately blocks the active SSH connection, leaving the server accessible only via an out-of-band console. This is not theoretical: it is among the most common causes of self-inflicted server outages. Beyond the lockout risk, the security value of ufw comes entirely from the default deny incoming policy. Without it, ufw is effectively decorative — all traffic passes unless explicitly blocked. The default allow incoming policy that ships with most distributions must be explicitly changed to deny. Outbound traffic control is a secondary consideration that most guides omit: restricting outbound connections from a compromised server can limit an attacker’s ability to download tools, beacon to C2 infrastructure, or exfiltrate data. This is more complex to configure without disrupting legitimate application traffic, but worth implementing on servers handling sensitive data.
- Always run 'ufw allow ssh' before 'ufw enable' — there is no safe recovery from lockout without an out-of-band console
- The default incoming policy on most systems is ALLOW — explicitly set 'ufw default deny incoming' before enabling
- ufw disable flushes all rules and reverts to ACCEPT everything — do not run it on a production server without a replacement ruleset ready
- ufw rules persist across reboots by default when enabled — this is correct behaviour but means mistakes also persist
Practical Examples
Complete minimal web server firewall setup in correct order
# Step 1: Allow SSH before anything else
ufw allow ssh
# Step 2: Set default policies
ufw default deny incoming
ufw default allow outgoing
# Step 3: Allow web traffic
ufw allow 80/tcp
ufw allow 443/tcp
# Step 4: Enable the firewall
ufw enable
# Step 5: Verify
ufw status verboseThe only safe order for enabling ufw on a remote server. Deviation from this sequence risks a self-inflicted lockout. Run ufw status verbose after enabling to confirm the rules are active as expected.
Enable ufw logging for audit trail
ufw logging on
# Logs appear in /var/log/ufw.log
tail -f /var/log/ufw.logFirewall logging records all blocked connection attempts with source IP, destination port, and protocol. Useful for detecting port scans, brute force attempts, and unexpected connection patterns. Set logging level with ‘ufw logging medium’ for more detail.
Delete a rule by number
ufw status numbered
# Identify the rule number, then:
ufw delete 3The numbered status output assigns an index to each rule. Deletion by number is more reliable than deletion by rule string, especially for rules with complex source IP specifications.
Troubleshooting Common Issues
Problem: Lost SSH access after enabling ufw
Solution: Connect via your hosting provider’s out-of-band console. Run ufw disable to immediately restore full access, then rebuild your ruleset in the correct order: allow SSH first, set default deny, then enable.
Problem: ufw is enabled but traffic that should be blocked is still passing
Solution: Check the default incoming policy with ufw status verbose. If it shows ‘Default: allow (incoming)’, run ufw default deny incoming and re-enable. A default allow policy means ufw only blocks explicitly denied traffic — the inverse of what most people intend.
Problem: ufw rules are correct but an application cannot connect
Solution: Check whether the application is using IPv6. ufw manages both IPv4 and IPv6 rules, but if IPV6=yes is not set in /etc/default/ufw, IPv6 rules may not be applied. Also verify the application is connecting on the port and protocol you allowed — some applications use non-standard ports.
Summary
ufw provides a reliable, persistent firewall for Linux servers with straightforward syntax that abstracts iptables complexity. The critical discipline is rule order: SSH must be explicitly allowed before ufw is enabled, and the default incoming policy must be set to deny before the firewall is switched on. Reversing this order — enabling the firewall before allowing SSH — is the most common cause of self-inflicted production outages. Get these two ordering steps right and ufw provides robust, reboot-persistent network-layer protection with minimal ongoing management overhead and no iptables syntax required.
- Run
ufw allow sshbeforeufw enable— this single sequence prevents the most common cause of server lockout - Set
ufw default deny incomingexplicitly — the default on most systems is allow, which makes the firewall ineffective - Use
ufw allow from <YOUR.IP> to any port 22to restrict SSH to known admin IPs only
Related Commands
iptables for stateful firewall rules • fail2ban for SSH brute force prevention • nmap to scan your own server externally • ss for fast open port enumeration
Need a Hardened Linux Server, Configured from Day One?
INTRAM configures and manages Linux servers with security controls including SSH hardening, firewall rules, fail2ban, and continuous monitoring — deployed correctly the first time.
Request Server Hardening