Vucense

UFW Firewall Tutorial 2026: Secure Your Ubuntu Server

🟢Beginner

Configure UFW firewall for sovereign Ubuntu server security. Covers allow/deny rules, application profiles, rate limiting, logging, IPv6 configuration, and essential firewall patterns.

UFW Firewall Tutorial 2026: Secure Your Ubuntu Server
Article Roadmap

Key Takeaways

  • SSH first, always: sudo ufw allow ssh before sudo ufw enable. Every time. Without exception. A locked-out server requires a rescue console to recover.
  • Default deny incoming: sudo ufw default deny incoming blocks everything not explicitly allowed. This is the correct baseline for any internet-facing server.
  • ufw limit for rate limiting: sudo ufw limit 22/tcp blocks IPs that try more than 6 connections in 30 seconds — essential brute-force protection without installing Fail2Ban.
  • Application profiles: sudo ufw app list shows named profiles (Nginx Full, OpenSSH, etc.) — sudo ufw allow 'Nginx Full' opens both 80 and 443 at once.

Introduction

Direct Answer: How do I configure the UFW firewall on Ubuntu 24.04 to secure my server?

UFW is pre-installed on Ubuntu 24.04 but disabled by default. The correct setup sequence: (1) sudo ufw allow ssh — add SSH rule before anything else; (2) sudo ufw default deny incoming — block all unsolicited inbound traffic; (3) sudo ufw default allow outgoing — allow all outbound; (4) add service rules: sudo ufw allow 80/tcp, sudo ufw allow 443/tcp; (5) sudo ufw enable — activate the firewall; (6) sudo ufw status verbose — confirm rules are applied. To rate-limit SSH against brute force: sudo ufw limit ssh. To allow a specific IP only: sudo ufw allow from 203.0.113.10 to any port 22. To delete a rule: sudo ufw delete allow 80/tcp. UFW translates these commands into iptables rules — the rules persist across reboots automatically once UFW is enabled.


Part 1: First-Time Setup

# Check current UFW status (likely inactive on a fresh server)
sudo ufw status

Expected output:

Status: inactive
# ⚠️  CRITICAL: Allow SSH BEFORE enabling UFW
# Losing SSH access requires a VPS rescue console to recover
sudo ufw allow ssh
# Equivalent: sudo ufw allow 22/tcp

# Set default policies
sudo ufw default deny incoming   # Block all unsolicited inbound traffic
sudo ufw default allow outgoing  # Allow all outbound connections

# Allow web traffic (add only what you actually use)
sudo ufw allow http    # Port 80
sudo ufw allow https   # Port 443

# Enable the firewall
sudo ufw enable

Expected output:

Rules updated
Rules updated (v6)
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
# Verify status
sudo ufw status verbose

Expected output:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
22/tcp (v6)                ALLOW IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)

Part 2: Essential Rule Patterns

# ── Allow rules ───────────────────────────────────────────────────────────

# Allow by service name
sudo ufw allow ssh         # Port 22 TCP
sudo ufw allow http        # Port 80 TCP
sudo ufw allow https       # Port 443 TCP
sudo ufw allow ftp         # Port 21 TCP

# Allow by port number
sudo ufw allow 8080/tcp
sudo ufw allow 51820/udp   # WireGuard VPN

# Allow a port range
sudo ufw allow 8000:8010/tcp

# Allow from a specific IP (restrict who can SSH in)
sudo ufw allow from 203.0.113.10 to any port 22

# Allow from an entire subnet (e.g., your office network)
sudo ufw allow from 10.0.0.0/8 to any port 5432  # PostgreSQL from private net only

# Allow from specific IP to any port (trusted monitoring server)
sudo ufw allow from 10.0.0.100

# ── Deny rules ────────────────────────────────────────────────────────────

# Explicitly deny a port (creates a DENY rule, logging the attempt)
sudo ufw deny 23/tcp   # Telnet — block and log

# Reject with an ICMP "port unreachable" response (faster than deny)
sudo ufw reject 25/tcp  # SMTP — reject with error

# ── Rate limiting ─────────────────────────────────────────────────────────

# Rate-limit SSH: block IPs with >6 connections in 30 seconds
sudo ufw limit ssh
sudo ufw limit 22/tcp   # Equivalent

# ── Delete rules ──────────────────────────────────────────────────────────

# Delete by rule specification
sudo ufw delete allow 8080/tcp

# Delete by line number (from 'ufw status numbered')
sudo ufw status numbered
sudo ufw delete 3   # Delete rule #3

Part 3: Application Profiles

UFW ships with named application profiles for common services:

# List all available application profiles
sudo ufw app list

Expected output:

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
# Allow Nginx (both HTTP and HTTPS at once)
sudo ufw allow 'Nginx Full'

# View what a profile contains
sudo ufw app info 'Nginx Full'

Expected output:

Profile: Nginx Full
Title: Web Server (Nginx, HTTP + HTTPS)
Description: Small, but very powerful and efficient web server

Ports:
  80,443/tcp
# Create a custom application profile
sudo tee /etc/ufw/applications.d/myapp << 'EOF'
[MyApp API]
title=My Application API
description=Custom API server
ports=3000/tcp
EOF

sudo ufw app update MyApp
sudo ufw allow 'MyApp API'
sudo ufw app info 'MyApp API'

Expected output:

Profile: MyApp API
Title=My Application API
Ports:
  3000/tcp

Part 4: Common Server Configurations

# ── Web server (Nginx + SSH) ──────────────────────────────────────────────
sudo ufw --force reset     # Start clean
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw limit ssh         # Rate limit against brute force
sudo ufw allow 'Nginx Full'
sudo ufw enable

# ── Database server (internal access only) ────────────────────────────────
sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 10.0.0.0/24 to any port 22    # SSH from private network
sudo ufw allow from 10.0.0.10 to any port 5432     # PostgreSQL from app server only
sudo ufw allow from 10.0.0.10 to any port 6379     # Redis from app server only
sudo ufw enable

# ── WireGuard VPN server ──────────────────────────────────────────────────
sudo ufw allow 51820/udp            # WireGuard
sudo ufw allow in on wg0 to any     # Allow all traffic from VPN interface
sudo ufw allow out on wg0 from any  # Allow VPN clients to reach internet
sudo ufw enable

Part 5: Logging and Monitoring

# Enable logging (off by default on many installs)
sudo ufw logging on       # Log blocked connections
sudo ufw logging full     # Log both allowed and blocked

# View UFW logs
sudo journalctl -k | grep UFW | tail -20
# Or:
sudo tail -f /var/log/ufw.log

# Count connection attempts by source IP (detect scanning)
sudo journalctl -k --since "1 hour ago" | grep "UFW BLOCK" | \
  grep -oP 'SRC=\K[\d.]+' | sort | uniq -c | sort -rn | head -10

Expected output (if being scanned):

     47 185.220.101.45
     23 194.165.16.78
      8 45.33.32.156
# Status of specific ports — verify what's actually open
sudo ufw status verbose | grep -E "ALLOW|LIMIT"

Part 6: IPv6 Configuration

UFW manages IPv4 and IPv6 rules simultaneously. Rules without a source address apply to both automatically:

# Verify IPv6 is enabled in UFW config
grep "IPV6=yes" /etc/default/ufw

Expected output:

IPV6=yes
# Rules apply to both IPv4 and IPv6 by default:
sudo ufw allow 443/tcp
# Creates:
#   443/tcp ALLOW IN Anywhere       (IPv4)
#   443/tcp (v6) ALLOW IN Anywhere  (IPv6)

# IPv6-specific rule
sudo ufw allow from 2001:db8::/32 to any port 22

# Verify IPv6 rules
sudo ufw status | grep v6

Quick Reference

# ── Status ────────────────────────────────────────────────────────────────
sudo ufw status                    # Quick status
sudo ufw status verbose            # Full rules
sudo ufw status numbered           # Rules with line numbers

# ── Enable/Disable ────────────────────────────────────────────────────────
sudo ufw enable                    # Activate (persists across reboots)
sudo ufw disable                   # Deactivate (keeps rules for next enable)
sudo ufw --force reset             # Remove ALL rules and disable

# ── Allow ─────────────────────────────────────────────────────────────────
sudo ufw allow ssh                 # By service name
sudo ufw allow 443/tcp             # By port
sudo ufw allow from IP to any port 22   # From specific IP
sudo ufw limit ssh                 # Rate-limited allow

# ── Deny/Delete ───────────────────────────────────────────────────────────
sudo ufw deny 23/tcp               # Block + log
sudo ufw delete allow 8080/tcp     # Remove rule by spec
sudo ufw delete N                  # Remove rule by number

# ── Logging ───────────────────────────────────────────────────────────────
sudo ufw logging on                # Enable
sudo ufw logging off               # Disable

Troubleshooting

Server became inaccessible after ufw enable

Cause: SSH was not allowed before enabling. You are locked out. Fix: Use your VPS provider’s console (Hetzner Console, DigitalOcean Console) to access the server without SSH. Run sudo ufw allow ssh && sudo ufw reload.

Port is allowed in UFW but connection still refused

Cause: The service isn’t running, or it’s bound to 127.0.0.1 (localhost only) instead of 0.0.0.0. Fix: sudo ss -tlnp | grep PORT to see if the service is listening. 0.0.0.0:PORT = accessible; 127.0.0.1:PORT = localhost only — change the service’s bind address.

UFW rules reset after reboot

Cause: UFW disabled — ufw enable was never run, or UFW service is disabled. Fix: sudo ufw enable and verify: sudo systemctl is-enabled ufw should return enabled.


Conclusion

UFW is now configured with the correct defaults — deny all incoming, allow outgoing — and explicit rules for your services. The rate-limit on SSH reduces brute-force exposure without requiring Fail2Ban. UFW rules persist across reboots and apply to both IPv4 and IPv6.

See SSH Hardening Guide 2026 for key-based authentication and sshd_config hardening alongside UFW, and Linux Networking Basics 2026 for the ss and ip commands used to verify what’s actually listening on each port.


People Also Ask

Should I use UFW or iptables directly on Ubuntu 24.04?

Use UFW. It translates readable commands into iptables rules without requiring you to understand iptables syntax. For 95% of server firewall needs — opening ports, restricting source IPs, rate limiting — UFW is simpler, less error-prone, and easier to audit. Use iptables directly only if you need advanced features UFW doesn’t expose: stateful connection tracking for specific protocols, custom NAT rules, or complex packet marking. Even then, nftables is the modern replacement for iptables and worth learning before going lower level.

Does UFW work with Docker on Ubuntu 24.04?

Docker bypasses UFW by modifying iptables directly. If you docker run -p 80:80 nginx, port 80 is exposed to the internet even if UFW says DENY 80/tcp. The fix: in /etc/docker/daemon.json, add "iptables": false to disable Docker’s iptables management, then use UFW exclusively. Alternatively, bind Docker to localhost only (-p 127.0.0.1:80:80) and use Nginx as a reverse proxy in front. See Docker Security Best Practices 2026 for the complete Docker + UFW interaction guide.

What is the difference between ufw deny and ufw reject?

ufw deny PORT drops packets silently — the sender gets no response and times out. ufw reject PORT sends back an ICMP “port unreachable” error — the sender knows immediately that the connection was refused. deny is better for blocking port scanners (no response = harder to fingerprint your server). reject is better for internal network services (fast failure, better UX for legitimate users who accidentally connect to the wrong port). Use deny as the default; use reject sparingly for specific services where fast failure is preferable.


Part 12: Hardened UFW Architecture

Ubuntu firewall hardening is an ongoing process. Build policies that reflect the actual service topology and change them carefully.

12.1 Policy-first design

Define which services need network access first, then open only those ports. A deny-by-default posture is the safest baseline.

12.2 IPv6 support

If your Ubuntu host uses IPv6, configure ufw to manage it too.

sudo ufw allow proto tcp from any to any port 22 comment 'SSH'
sudo ufw enable

Check ufw status verbose to ensure both IPv4 and IPv6 rules are active.

12.3 Interface-specific rules

Restrict rules to specific network interfaces for multi-homed hosts.

sudo ufw allow in on eth0 to any port 443 proto tcp

This prevents services exposed to a private network from being accessible on the public interface.

12.4 Logging and diagnostics

Enable logging to inspect dropped packets and suspicious connection attempts.

sudo ufw logging high

Use logs to tune rules and detect scanning or brute-force activity.

Part 13: Integrated Threat Mitigation

Combine UFW with additional Ubuntu security tools.

13.1 Fail2Ban integration

Use Fail2Ban to block repeated SSH or application-level failures.

sudo apt install fail2ban

Configure jail patterns and ban times, then let UFW enforce the temporary blocks.

13.2 AppArmor and UFW

Use AppArmor to confine service behavior while UFW controls network exposure. For example, restrict nginx or sshd to a minimal file and network access set.

13.3 Secure administrative access

Limit SSH access to trusted hosts and use key-based authentication only.

sudo ufw allow from 203.0.113.4 to any port 22 proto tcp

Disable SSH password login in /etc/ssh/sshd_config.

Part 14: Operational Management

UFW must be manageable and auditable in production.

14.1 Rule groups and comments

Use comments when adding rules so the purpose is clear.

sudo ufw allow proto tcp from 10.0.0.0/8 to any port 5232 comment 'internal app access'

Comments help reviewers understand legacy rules and avoid accidental deletions.

14.2 Rule ordering and impact

Although UFW abstracts ordering, understand the implication of broad allow rules such as sudo ufw allow from 10.0.0.0/8 and avoid them unless necessary.

14.3 Change control

Treat UFW rule changes like code changes. Store the intended changes in version control and apply them through a controlled deployment process.

Part 15: Firewall Testing and Validation

Validate UFW rules before and after deployment.

15.1 Access verification

Use local and remote tests to verify the expected ports are reachable and unexpected ports are blocked. Tools like nmap and curl are useful.

15.2 Regression tests

Create a small test script that validates the host’s expected open ports and services. Run it after each rule update.

15.3 Drift detection

Periodically compare the active UFW rules to your source-of-truth configuration. Alert if they diverge unexpectedly.

Part 16: Firewall Policies for Hybrid Environments

Ubuntu hosts often live in hybrid or cloud-connected systems.

16.1 Cloud provider security groups

Use UFW in combination with cloud provider security groups. The provider controls the outer boundary, while UFW enforces host-level policies.

16.2 VPN and bastion host patterns

Keep public access minimal and rely on VPN or bastion hosts for administrative access. UFW should permit only the necessary traffic from those trusted entry points.

16.3 Internal segmentation

Use UFW to enforce segmentation between application tiers on the same host or within the same subnet. For example, allow database traffic only from the application host.

Part 17: High-Availability and Failover

Firewall rules should support planned failover and high-availability patterns.

17.1 Floating IP handling

If the host uses floating IPs or failover addresses, write rules that stay valid when the address moves between nodes.

17.2 Stateful failover

Preserve connection state where needed during failover. Test how UFW behaves during failover scenarios and adjust your connection tracking settings accordingly.

17.3 Backup and restore

Export UFW rules and keep backup copies. On a restore, verify the rule set before enabling the firewall.

Part 18: Final Hardening Checklist

  • UFW is enabled with deny-by-default policy
  • only required ports and interfaces are allowed
  • IPv6 rules are configured if enabled
  • SSH access is restricted and key-based
  • ports are documented and reviewed regularly
  • UFW is integrated with Fail2Ban and AppArmor where appropriate
  • rule sets are version controlled and validated
  • drift detection and logging are in place

A hardened Ubuntu firewall is a foundational security control. When it is managed with discipline, it dramatically reduces the attack surface of your system and makes the host far more resilient under real-world conditions.

Part 19: Advanced Network Architecture

UFW can be part of a larger Ubuntu network architecture that includes VPNs, NAT, and segmented services.

19.1 VPN and private network rules

Allow only VPN-assigned subnets to access internal services. Do not expose internal management interfaces on the public network.

sudo ufw allow in on tun0 to any port 22 proto tcp

19.2 NAT and port forwarding

If the host provides NAT or port forwarding, keep the forwarded port open only if absolutely necessary. Use UFW to restrict the source of forwarded traffic.

19.3 Service segmentation

Segment services by role. For example, keep web traffic separate from database replication and internal APIs. Use host-based ACLs and UFW comments to document the intent of each rule.

Part 20: Auditing and Policy Enforcement

A firewall is only effective when it is audited and enforced consistently.

20.1 Regular reviews

Schedule periodic rule reviews. Remove stale ports and validate every open rule against current service architecture.

20.2 Compliance reporting

Generate reports that show allowed ports, source CIDRs, and rule comments. Use these reports for security reviews and audits.

20.3 Automated policy enforcement

Use configuration management to enforce UFW state. Tools like Ansible or Terraform can deploy rules from a source-of-truth definition so manual drift is minimized.

Part 21: Resilience and Recovery

Plan for firewall issues before they occur.

21.1 Rescue mode access

Have a separate recovery path that bypasses UFW if the firewall locks you out. This may be a serial console, cloud provider SSH key, or out-of-band access.

21.2 Rule rollback

Keep a backup of the previous UFW ruleset so you can restore it quickly if a new rule set breaks connectivity.

sudo ufw status numbered > /tmp/ufw-backup.txt

21.3 High-availability considerations

In clustered or highly available Ubuntu setups, coordinate firewall changes across nodes. Avoid partial updates that can create asymmetric routing or firewall gaps.

Part 22: Final Firewall Hardening Checklist

  • all rules are documented with comments
  • public-facing ports are minimized and justified
  • IPv6 configuration is validated if enabled
  • UFW is integrated with AppArmor and Fail2Ban as appropriate
  • rule drift is detected and corrected automatically
  • rescue access is documented and tested
  • firewall rules are deployed from an auditable source-of-truth
  • periodic reviews and audits are scheduled

UFW is a powerful tool when it is managed deliberately. Keep the host firewall aligned with your service architecture, and it becomes one of the strongest defenses in your Ubuntu security posture.

Part 23: Cloud and Hybrid Connectivity

Ubuntu hosts often need to connect to cloud services or hybrid networks safely.

23.1 Connecting to cloud provider services

Allow only necessary cloud service endpoints through UFW. Use provider-specific CIDRs and avoid broad outbound permissions when possible.

23.2 Secure bastion patterns

Limit direct access by routing administrative connections through a bastion host. UFW should allow management traffic only from that bastion’s IP range.

23.3 VPN failover and redundancy

If your host relies on a VPN for secure connectivity, account for VPN failover. Keep firewall rules tolerant of the VPN interface switching, but strict about the source CIDRs.

Part 24: Container and Kubernetes Host Hardening

Ubuntu hosts running containers need firewall rules that reflect the container network model.

24.1 Container bridge protection

Restrict traffic to container bridge interfaces. Do not expose container IP ranges to the public internet unless necessary.

24.2 Kubernetes node firewalls

On Kubernetes worker nodes, allow only kubelet, kube-proxy, and node agent ports from the cluster control plane. Block other inbound traffic unless it is explicitly required.

24.3 Overlay network considerations

If using overlay networking, keep firewall rules compatible with the overlay CIDR and the encapsulation protocol. Avoid blocking internal traffic that is needed for service mesh or pod communication.

Part 25: Logging, Alerting, and Incident Response

Firewall hardening includes knowing when and why traffic is blocked.

25.1 Alerting on policy violations

Alert when critical ports are unexpectedly opened or when large volumes of denied traffic are observed.

25.2 Investigating blocked connections

Use UFW logs to trace blocked connection attempts. Correlate these with system logs and application logs for a full incident picture.

25.3 Incident documentation

Document firewall-related incidents and rule changes. This helps identify whether a policy change resolved the issue or introduced a gap.

Part 26: Compliance and Policy Automation

Firewall policy is part of a broader compliance posture.

26.1 Policy-as-code

Express UFW rules in code and deploy them through automation. Use CI/CD pipelines to validate the rules and deploy them consistently across hosts.

26.2 Approval workflows

Require a documented approval for firewall changes that open new services or change critical access paths. Link the change request to the deployed rule set.

26.3 Audit trail

Maintain an audit trail that includes the author, rationale, and timestamp for each rule change. This is useful for incident response and compliance reviews.

Part 27: Advanced Connection Tracking

Connection tracking determines how UFW handles stateful flows.

27.1 Netfilter connection tracking

Understand netfilter stateful tracking for TCP, UDP, and ICMP. UFW uses stateful rules for simplicity, but long-lived or high-frequency connections can affect kernel state tables.

27.2 SYN flood mitigation

Protect against SYN floods with kernel tuning and rate limits. Use net.ipv4.tcp_syncookies = 1 and monitor connection backlog stats.

27.3 Connection limits per host

For services exposed to the internet, cap the number of simultaneous connections from a single source. This helps prevent exhaustion attacks.

Part 28: Network Namespace and Container Isolation

Ubuntu hosts often host containers and network namespaces.

28.1 Namespace-specific UFW rules

Apply firewall rules per network namespace when services are isolated in containers. This provides a stronger security boundary than host-wide rules.

28.2 Docker and UFW interaction

If using Docker, be aware that Docker can modify iptables rules directly. Keep Docker’s bridge network and UFW rules aligned to avoid accidental exposure.

28.3 Podman and rootless containers

For rootless container workloads, manage firewall rules in the user namespace carefully. Ensure the host firewall still controls external access.

Further Reading

Tested on: Ubuntu 24.04 LTS (Hetzner CX22). UFW 0.36.2. Last verified: April 28, 2026.

Divya Prakash

About the Author

AI Systems Architect & Founder

Graduate in Computer Science | 12+ Years in Software Architecture | Full-Stack Development Lead | AI Infrastructure Specialist

Divya Prakash is the founder and principal architect at Vucense, leading the vision for sovereign, local-first AI infrastructure. With 12+ years designing complex distributed systems, full-stack development, and AI/ML architecture, Divya specializes in building agentic AI systems that maintain user control and privacy. Her expertise spans language model deployment, multi-agent orchestration, inference optimization, and designing AI systems that operate without cloud dependencies. Divya has architected systems serving millions of requests and leads technical strategy around building sustainable, sovereign AI infrastructure. At Vucense, Divya writes in-depth technical analysis of AI trends, agentic systems, and infrastructure patterns that enable developers to build smarter, more independent AI applications.

View Profile

Further Reading

All Dev Corner

Comments