Firewall Security with UFW: Deny All, Allow Some

By Raman Kumar

Updated on Sep 23, 2025

Learn how to secure servers with the “deny all, allow some” firewall strategy using UFW. Our step-by-step guide covers reducing the attack surface.

In this guide we explain the minimal-attack-surface mindset, then walk through a practical, repeatable UFW workflow: deny everything by default, then open only the ports our services actually need. Actionable commands included. Clear, practical, and focused — no fluff.

Why “minimal attack surface” matters

An attack surface is every network port, service, API, or UI that an attacker can touch. The smaller the exposed surface, the fewer ways an attacker can get in. Reducing the attack surface means removing unused services, limiting who can manage systems, and only exposing necessary network ports. This is fundamental defensive hygiene.

What UFW gives us (quick primer)

UFW (Uncomplicated Firewall) is a user-friendly frontend for iptables/netfilter that’s common on Ubuntu and many Debian-based systems. By default it is designed to deny incoming traffic and allow outgoing traffic — which is already a secure baseline for most servers. We’ll use UFW to implement “deny all, allow some” policies safely.

Before we start — short checklist

  • Confirm we have console access or out-of-band recovery (so we aren’t locked out if SSH rules are wrong).
  • Know the admin IP(s) or subnets that need SSH access.
  • Decide which services must be externally reachable (web, mail, API).
  • Have a plan to test and roll back (ufw disable).

Step-by-step: Harden a server with UFW

1) Install or confirm UFW

sudo apt update
sudo apt install ufw -y

2) Reset to a known state (optional but tidy)

sudo ufw reset # removes existing rules and sets defaults back

3) Set the secure defaults

We recommend the conservative baseline: deny incoming, allow outgoing.

sudo ufw default deny incoming
sudo ufw default allow outgoing

4) Add safe SSH access rules (do this before enabling!)

If we connect remotely we must allow SSH first, or we might lock ourselves out. Prefer restricting SSH to admin IP(s) or using rate limiting.

Allow SSH from a specific admin IP:

sudo ufw allow from 203.0.113.45 to any port 22 proto tcp

Or allow but rate-limit brute-force attempts:

sudo ufw limit OpenSSH    # adds a rate-limited rule for ssh (better than plain allow)

5) Open service ports we actually need

Common web server rules:

sudo ufw allow 80/tcp     # HTTP
sudo ufw allow 443/tcp    # HTTPS

Mail server examples (open only if we run a mail server and know what each port is for):

sudo ufw allow 25/tcp     # SMTP (server-to-server; often blocked by cloud providers)
sudo ufw allow 587/tcp    # Submission (MSA) — client mail submission (TLS recommended)
sudo ufw allow 465/tcp    # SMTPS (legacy implicit TLS)
sudo ufw allow 143/tcp    # IMAP (insecure)
sudo ufw allow 993/tcp    # IMAPS (secure)
sudo ufw allow 110/tcp    # POP3 (insecure)
sudo ufw allow 995/tcp    # POP3S (secure)

(Brief note: prefer 587 for client submission and 993/995 for secure retrieval. Ports summary matches standard port usage. )

6) (If we deny outgoing) Permit essential outbound traffic

Some environments require strict outbound controls (e.g., hardened servers). If we change to default deny outgoing, make sure to allow DNS, time, and package update traffic first:

sudo ufw default deny outgoing
sudo ufw allow out 53            # DNS
sudo ufw allow out 123/udp       # NTP (if needed)
sudo ufw allow out 80/tcp
sudo ufw allow out 443/tcp

7) Enable the firewall

Make sure SSH is allowed (see step 4), then:

sudo ufw enable
sudo ufw status verbose
  • If something goes wrong, we can disable it from console: sudo ufw disable.
  • Pair UFW with Fail2Ban to stop brute force

Fail2Ban monitors logs and temporarily bans hosts that repeatedly fail authentication. It can automatically add UFW bans. Install and enable a simple SSH jail:

sudo apt install fail2ban -y

Example /etc/fail2ban/jail.local snippet (minimal):

[sshd]
enabled = true
port    = ssh
filter  = sshd
logpath = /var/log/auth.log
maxretry = 5
banaction = ufw

Fail2Ban’s daemon updates the firewall to block offending IPs, which complements UFW’s static rules.

Advanced but practical tips (keep the attack surface small)

  • Limit management exposure. Allow administrative ports (SSH, RDP) only from known admin networks or via a VPN. Don’t expose direct admin access to the public Internet.
  • Run only required services. Stop or disable unused daemons (systemctl disable --now <service>). Each service we run is a potential attack vector.
  • Bind services to internal interfaces. If a service is for internal use, configure it to listen only on the LAN interface.
  • Keep software patched. Firewall rules help, but patched services we actually run are crucial.
  • Use logs for detection. Enable UFW logging and check /var/log/ufw.log or syslog to spot suspicious activity:
sudo ufw logging on
sudo tail -f /var/log/ufw.log

Audit and troubleshooting commands

Show UFW rules:

sudo ufw status numbered

Delete a rule by number:

sudo ufw delete <rule-number>

Insert a rule at the top:

sudo ufw insert 1 allow 443/tcp

List listening sockets (what’s exposed right now):

ss -tuln
# or
sudo ss -tulnp

Find which process is listening:

sudo lsof -i -P -n | grep LISTEN

Quick-reference example: Harden a simple web server

# baseline
sudo apt update && sudo apt install ufw fail2ban -y
sudo ufw reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

# allow admin SSH from admin-IP, rate-limit as fallback
sudo ufw allow from 203.0.113.45 to any port 22 proto tcp
sudo ufw limit 22/tcp

# allow web traffic
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# enable
sudo ufw enable
sudo ufw status verbose

Short justification for choices

  • Deny-by-default prevents accidental exposure caused by forgotten services. UFW’s defaults are a practical secure baseline.
  • Restricting management access and combining UFW with Fail2Ban reduces brute-force and targeted admin attacks.
  • Only opening required mail/web ports and preferring secured ports (TLS) keeps our external footprint minimal and interoperable.

Final notes (what we should remember)

  • Firewalls reduce risk but do not replace patching, good authentication, monitoring, and least-privilege operations.
  • Always test rules in a safe way; have console/recovery access available if we administer remote systems.
  • Periodically review what services are listening and close anything that’s not needed. This straight-forward discipline dramatically reduces our attack surface.

That’s the whole workflow: a minimal surface, explicit rules, and automated protection for the noisy stuff. If we apply these steps consistently across servers and combine them with patching and least-privilege operations, our network will stop being a buffet for scanners and start behaving like an actual fortress.

Check out robust instant dedicated serversInstant KVM VPS, premium shared hosting and data center services in New Zealand