Introduction
UFW (Uncomplicated Firewall) is a user-friendly front-end for managing iptables firewall rules on Ubuntu. It simplifies the process of configuring which network traffic is allowed into and out of your server, making it an essential first step after deploying any cloud VM.
An unprotected server accepts connections on every port by default. This means any service you run — a database, a development server, a monitoring tool — is accessible to the entire internet unless you explicitly restrict access. A properly configured firewall ensures that only the ports you intentionally allow (such as SSH, HTTP, and HTTPS) accept incoming traffic. Everything else is silently dropped.
In this tutorial, you will install and enable UFW on your Raff Ubuntu 24.04 server, configure default policies for incoming and outgoing traffic, add rules for common services, set up rate limiting to protect SSH from brute-force attacks, manage and delete rules as your stack evolves, and enable logging to monitor blocked connection attempts.
Step 1 — Installing and Checking UFW Status
UFW comes pre-installed on Ubuntu 24.04 but is disabled by default. This means the software is present on your server, but no firewall rules are active. Verify UFW is installed and check its current status:
bashsudo ufw status verbose
You should see:
Status: inactive
If UFW is not installed for any reason (for example, on a minimal server image), install it:
bashsudo apt update && sudo apt install -y ufw
Warning
Do not enable UFW before adding an SSH allow rule. If you enable the firewall without allowing SSH (port 22), you will immediately lose remote access to your server and will need to use the Raff web console to regain access.
Step 2 — Configuring Default Policies
Before adding specific rules, set the default policies that determine how UFW handles traffic for which no explicit rule exists. The recommended approach is to deny all incoming traffic and allow all outgoing traffic:
bashsudo ufw default deny incoming
sudo ufw default allow outgoing
You should see:
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)
Default outgoing policy changed to 'allow'
(be sure to update your rules accordingly)
With these defaults in place, your server will reject every incoming connection attempt unless you create a rule to permit it. Outgoing connections — such as package updates via apt, DNS queries, API calls, and downloading files — will continue to work normally.
This deny-by-default approach follows the principle of least privilege: start with everything blocked, then open only what you need. It is significantly more secure than the alternative (allow-by-default and block specific ports), because you cannot accidentally expose a new service by forgetting to add a block rule.
Step 3 — Allowing SSH and Enabling the Firewall
SSH is how you manage your server remotely. You must allow it before enabling the firewall. UFW understands common service names, so you can use the service name directly:
bashsudo ufw allow ssh
This creates a rule allowing incoming TCP traffic on port 22. If you have changed your SSH port to a non-standard value (for example, 2222), specify the port number instead:
bashsudo ufw allow 2222/tcp
With SSH allowed, you can safely enable UFW:
bashsudo ufw enable
You will see a warning:
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
Type y and press Enter. Your current SSH session will remain connected because the SSH rule is already in place. UFW is now active and will start automatically on every subsequent boot.
Verify the firewall status:
bashsudo ufw status verbose
Expected output:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
22/tcp (v6) ALLOW IN Anywhere (v6)
Notice that UFW automatically creates rules for both IPv4 and IPv6, ensuring your server is protected regardless of which protocol a client uses.
Step 4 — Rate Limiting SSH to Block Brute-Force Attacks
SSH is the most commonly attacked service on any public server. Automated bots continuously scan the internet and attempt to log in using common usernames and passwords. UFW's limit rule provides basic brute-force protection by rejecting connections from any IP address that makes more than 6 connection attempts within 30 seconds.
If you already added a plain allow ssh rule in the previous step, replace it with a limit rule:
bashsudo ufw delete allow ssh
sudo ufw limit ssh
Verify the updated rules:
bashsudo ufw status
You should see:
To Action From
-- ------ ----
22/tcp LIMIT Anywhere
22/tcp (v6) LIMIT Anywhere (v6)
The LIMIT action means legitimate SSH connections are allowed, but rapid repeated attempts from the same IP are automatically blocked. This significantly reduces the noise from brute-force bots.
Tip
For even stronger SSH security, combine UFW rate limiting with key-based authentication and disable password login entirely. Edit /etc/ssh/sshd_config and set PasswordAuthentication no, then restart the SSH service with sudo systemctl restart ssh.
Step 5 — Adding Rules for Web Traffic and Other Services
As you install web servers, databases, and applications, you will need to open additional ports. Here are the most common scenarios.
Allow HTTP and HTTPS for web traffic:
bashsudo ufw allow http
sudo ufw allow https
These are shorthand for sudo ufw allow 80/tcp and sudo ufw allow 443/tcp respectively. You will need these open before setting up a web server like Nginx with Let's Encrypt TLS certificates.
UFW also supports application profiles that bundle related ports. List available profiles:
bashsudo ufw app list
If Nginx is installed, you may see profiles like Nginx Full (ports 80 and 443), Nginx HTTP (port 80 only), and Nginx HTTPS (port 443 only). Allow both HTTP and HTTPS in one command:
bashsudo ufw allow 'Nginx Full'
For a database that should only be accessible from your private network — not the public internet — restrict the rule to a specific IP range:
bashsudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcp
This allows PostgreSQL connections only from the 10.0.0.0/24 subnet. Connections from any other source are denied. This pattern is essential when your web server and database run on separate Raff VMs connected by a private network.
For a custom application on a specific port, such as a Node.js server on port 3000:
bashsudo ufw allow 3000/tcp
To allow a port from a single specific IP address only:
bashsudo ufw allow from 203.0.113.5 to any port 3306 proto tcp
Note
Only open ports that you actively need. Every open port is a potential attack surface. If a service only needs to be accessed locally (for example, a Redis cache or a database that your web app on the same server connects to via localhost), do not open its port in the firewall.
Step 6 — Viewing, Deleting, and Resetting Rules
As your server configuration evolves — adding new services, removing old ones, tightening security — you will need to inspect and modify your firewall rules.
View all rules with their numbers for easy reference:
bashsudo ufw status numbered
Example output:
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp LIMIT IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
[ 3] 443/tcp ALLOW IN Anywhere
[ 4] 22/tcp (v6) LIMIT IN Anywhere (v6)
[ 5] 80/tcp (v6) ALLOW IN Anywhere (v6)
[ 6] 443/tcp (v6) ALLOW IN Anywhere (v6)
Delete a rule by its number:
bashsudo ufw delete 3
UFW asks for confirmation before deleting. After deletion, the remaining rules are renumbered, so always run status numbered again before deleting another rule to avoid removing the wrong one.
You can also delete a rule by repeating the original command with delete:
bashsudo ufw delete allow 3000/tcp
To temporarily disable the firewall without removing your rules:
bashsudo ufw disable
To completely reset UFW to factory defaults, removing all rules:
bashsudo ufw reset
Warning
ufw reset removes every rule and disables the firewall. You will need to reconfigure everything from Step 2 onward. Only use this if you want a completely clean start.
Step 7 — Enabling Logging and Monitoring Blocked Traffic
UFW can log blocked and allowed connection attempts, which is valuable for security monitoring, debugging connectivity issues, and understanding what traffic your server receives.
Enable logging:
bashsudo ufw logging on
The default logging level is low, which logs blocked packets. For more detail, increase the level:
bashsudo ufw logging medium
Available levels are off, low, medium, high, and full. For most servers, low or medium is sufficient. Higher levels generate significantly more log data and can fill your disk on busy servers.
UFW logs are written to /var/log/ufw.log. View the most recent blocked connection attempts:
bashsudo tail -30 /var/log/ufw.log
Each log entry marked [UFW BLOCK] shows the source IP address, destination port, and protocol. This is useful for confirming your rules work as expected and for identifying IP addresses that are repeatedly scanning your server.
To check that UFW persists across reboots:
bashsudo systemctl is-enabled ufw
This should return enabled, confirming that your firewall rules are active every time your server starts.
Tip
For automated security monitoring, consider piping UFW logs into a tool like fail2ban, which can automatically ban IP addresses that exhibit suspicious behavior across multiple services.
Conclusion
You have installed and configured UFW on your Raff Ubuntu 24.04 VM. Your server now denies all unsolicited incoming traffic, allows only the services you explicitly permitted, rate-limits SSH to block brute-force attacks, and logs blocked connections for monitoring.
As a quick reference, here are the commands you will use most often:
sudo ufw status numbered— view all active rulessudo ufw allow <port>/tcp— open a portsudo ufw delete <rule-number>— remove a rulesudo ufw limit ssh— rate-limit SSHsudo ufw reload— reload rules after changes
From here, you can:
- Install Docker and open only the ports your containers need
- Set up Nginx and secure it with Let's Encrypt TLS certificates
- Configure private networking between your Raff VMs so database traffic never traverses the public internet
Combined with Raff's built-in DDoS protection, UFW provides a strong security foundation for any workload. Review your firewall rules after every new service deployment by running sudo ufw status numbered to confirm that only the ports you intend to expose are open.