3v-Hosting has earned recognition from Research.com as the best backup software for its proven reliability, robust security features, and customer-focused servi...
3v-Hosting Blog
13 min read
Unfortunately, configuring a firewall is one of those things that people either remember too late or put off indefinitely. Very often, businesses are focused solely on launching their product, service, or website as quickly as possible. That’s why the process of setting up a new server usually goes something like this: set up a VPS, deploy your service, check that the site loads, and move on. At this stage, many people think they can deal with security issues later, when they have time. What a mistake!
The problem is that every server with a public IP starts getting scanned almost immediately after going online. Thousands of bots try SSH usernames and passwords, look for open ports and accessible databases, and check for vulnerable services and modules. And this isn’t a targeted attack specifically against you or your business - it’s just "normal" background noise on the internet. And if your server is exposed to the public internet even slightly more than is necessary for its normal operation, sooner or later it will be compromised or hacked.
It would seem that, until quite recently, configuring a firewall in Linux was a task marked with an asterisk, since working directly with iptables required a solid and confident understanding of how rule chains, tables, and network connection states work. At the same time, a mistake in just a single rule could either completely expose the server to attackers or, conversely, cut off access to it for everyone, including yourself. That is precisely why many administrators either put off configuring the firewall until later, "so that later, when they have free time, they can sit down and figure it out properly", or simply copied other people’s config files without fully understanding what exactly they were doing or how they worked.
But with the advent of UFW, the situation began to change for the better. Essentially, the UFW utility is an extension of the iptables (or nftables) utility, which in turn is an extension for configuring the Netfilter kernel module, the built-in system firewall. It’s simply a simplification tool that allows you to enter just a few straightforward commands instead of dozens of rules and chains.
We’ve previously written a brief guide to UFW. In this article, we’d like to take a closer look at this tool, explain how to install UFW, and show you how to use it to configure a firewall to protect your server from malicious intrusions. However, it’s always worth remembering that configuring a firewall is just a small part of a whole set of measures that must be taken to ensure maximum security for your infrastructure.
Let’s go back to what setting up a new server usually looks like: you’ve spun up a VPS, installed the necessary packages, configured Nginx or the backend, opened SSH for server management, and it seems like the job is done. It seems like the server is fully ready to go - the service is responding, the site is accessible - so you can move on to the next tasks or go have some tea with your colleagues and discuss yesterday’s soccer game.
But there’s a nuance that isn’t obvious even to many experienced administrators. The thing is, by default, your server is much more "talkative" than you might think. And even if you didn’t intentionally open any additional ports, various entry points may still be accessible from the outside - ones you might not even be aware of.
The most common examples might look something like this:
Oh! This is simply a hacker’s paradise - a whole set of potential entry points that are automatically scanned by thousands of bots, followed by more sophisticated tools.
This is precisely where the firewall’s key role comes into play. It doesn’t enhance security in some abstract way; it’s not a magic "make everything secure" button. Instead, it does something very specific: it limits external access to the server to the absolute minimum, opening only those services that need to be visible - and only to those who are authorized to see them.
As we mentioned in the introduction, UFW is not a standalone packet filtering mechanism, but merely a wrapper around existing low-level tools. Under the hood, it uses iptables or nftables, and its main task is to simplify interaction with them, without forcing you to delve into rule chains, tables, and connection states every time.
To put it simply, UFW is a high-level interface to the firewall. You describe rules as simple, easy-to-understand commands, and the system automatically translates them into correct low-level rules that are applied at the Linux kernel level. In other words, all the actual filtering happens in the same place as with manual iptables configuration; the only difference is how you manage it.
And here it’s important to dispel a common misconception. Because of its simplicity, UFW is sometimes perceived as a stripped-down or even a training tool. But in practice, this isn’t the case. It doesn’t limit the firewall’s capabilities; it merely hides the excessive complexity. Of course, if you’re working on a complex infrastructure project that requires sophisticated filtering schemes, you can always write rules directly in iptables. But for the vast majority of tasks, UFW’s capabilities are more than sufficient.
Moreover, using UFW often makes the configuration more predictable and maintainable. When rules are written in a simple, human-readable format like "allow this" and "deny that", they are easier to review, document, and share with other administrators. This is in contrast to long chains of rules in iptables, where it can sometimes be difficult to understand exactly what is happening without context.
On Ubuntu, UFW is usually already installed on the system; on Debian, it may not be. In any case, installation takes a couple of seconds and is straightforward:
sudo apt update
sudo apt install ufw
IMPORTANT! The most common mistake made by inexperienced administrators is that if you are connected to the server via SSH and enable UFW without first allowing SSH, you will cut yourself off from the connection.
Therefore, immediately after installation, B BEFORE ENABLINGB , the first thing you need to do is open the SSH port:
sudo ufw allow OpenSSH
This command adds a rule allowing SSH access (usually port 22, if the standard configuration is used).
If you are using a non-standard port (which, by the way, is often done to reduce brute-force attack noise), you must specify it explicitly:
sudo ufw allow 5522/tcp
, where 5522 is your actual SSH port. Without this step, enabling UFW will simply cut you off from the server.
Only after this can you safely enable UFW:
sudo ufw enable
You can check its status with the command:
sudo ufw status verbose
If you did everything correctly, you’ve already secured basic protection for your server at this stage without losing access to it - and that’s already an achievement :)
When it comes to configuring a firewall, it’s not so much about memorizing commands as it is about understanding the approach to security itself. UFW is built on a very simple and straightforward model: by default, your server shouldn’t accept any incoming connections unless you’ve explicitly allowed them.
This is exactly the principle you should use in your infrastructure: not "blocking the unnecessary", but "allowing only what is necessary". And while the difference may seem small, from a practical standpoint, these are two completely different levels of control.
In UFW, this logic is set with just two commands:
sudo ufw default deny incoming
sudo ufw default allow outgoing
With these commands, we’ve blocked all incoming connections and allowed all outgoing ones, so any incoming connection will be rejected unless you’ve added an explicit rule for it. At the same time, outgoing connections remain open so the system can function normally, receive updates, access third-party APIs, download packages, etc.
From here on, you’ll start consciously opening only those services that truly need to be accessible from the outside.
For example, the basic set for a web server consists of the HTTP and HTTPS ports:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
In the examples above, we simply opened the ports we needed, but in real-world practice, simply opening a port is only half the battle. The correct approach is not just to open a port, but to restrict access to it.
For example, SSH rarely needs to be accessible to the entire internet, and access is usually only required from your IP. In this case, we should allow access only from your IP:
sudo ufw allow from 192.168.1.100 to any port 22
The same applies to databases, since PostgreSQL or MySQL should not listen to the outside world. Their clients are usually a backend or an API - and that is who the database should be accessible to.
sudo ufw allow from 10.0.0.5 to any port 5432
From the outside, the port appears to be visible, but access to it is strictly limited to one or a few IP addresses. Therefore, it is effectively closed to random scanners.
At the start, the firewall configuration often looks extremely neat - just a couple of rules, everything is clear and transparent. But as time goes on, new services are gradually added to the system, temporary access is set up, test configurations are added, and as a result, the list of rules starts to grow. At some point, the overall set of rules ceases to be obvious, and the need to make any new changes raises doubts about whether any of the old rules might break.
Therefore, to prevent the firewall from becoming a black box, you need to periodically monitor and maintain it :) UFW provides an excellent, simple tool for this - viewing rules with numbering:
sudo ufw status numbered
You’ll get a list that looks something like this:
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 80/tcp ALLOW IN Anywhere
And the numbering here isn’t just for convenience - it can be used directly to manage rules, such as deleting them. If you no longer need a rule, you can easily delete it by its number:
sudo ufw delete 1
This may seem trivial, but a simple discipline like "add a rule, check it, remove the unnecessary ones" helps keep the configuration under control. If you neglect this, within a few months the firewall will turn into a jumble of random permissions, making it difficult to understand what is open and why.
When working with a server in practice, you often get the feeling that if a service isn’t responding, the problem must be in the code, the web server configuration, or a specific container. You check Nginx, restart the backend, look at the application logs, and everything seems fine, but connections still aren’t going through.
And this is where a simple but not always obvious fact often comes to light: traffic can be blocked at the firewall level. And this can happen without any obvious errors in the application itself.
That’s why another great tool that makes life much easier for system administrators is built-in logging. It lets you see which connections were rejected and where they came from. You can enable it with a single command:
sudo ufw logging on
After that, all events are recorded in the standard log:
/var/log/ufw.log
Inside, you’ll see entries about blocked packets, including their IP addresses, port numbers, and traffic direction. This greatly simplifies the process of pinpointing issues in the system and allows you to quickly identify and resolve problems.
This is especially helpful when configuring interactions between multiple services or microservices, working with Docker or Kubernetes where some network logic is hidden, as well as when identifying and resolving "floating" network issues that are difficult to reproduce.
At first glance, UFW gives the impression of complete control, since you’ve set the rules and are confident that they alone determine what is accessible from the outside and what isn’t. But in real-world infrastructure, things are sometimes a bit more complicated.
There is a whole class of services that interact with the firewall directly, bypassing UFW. The most common examples are Docker or hypervisors like Proxmox. They manage iptables independently, adding their own rules for networking, NAT, and port forwarding.
As a result, a situation may arise that isn’t immediately obvious: you look at the UFW rules and see that a port is closed, but in reality, the service is still accessible from the outside. From UFW’s perspective, everything is blocked, but at the iptables level, there’s already a rule that allows this access.
This is neither an error nor a bug - it is simply an architectural feature. Therefore, to avoid such situations, when configuring a server, it is helpful, first, to understand which components of the future system can control the firewall directly, and second, ideally, to verify the active rules directly at lower levels, such as in iptables itself.
Can UFW be used in production? Yes, it is a standard tool for most VPS and small projects. If configured correctly, it provides a sufficient level of security.
Should outgoing connections be blocked? Usually not, but in highly secure environments, this is done to limit data leaks and unwanted outgoing connections, such as reverse shells.
Should I choose UFW or manage iptables directly? If you don’t need complex scenarios, working with UFW is faster and more convenient. However, iptables makes sense when fine-grained customization is required.
Why is the port closed, but the service is running? Most likely, there is some other tool on your system that bypasses UFW and manages firewall rules directly. Examples of such services include Docker, ProxMox, and others.
How can I tell what exactly is blocking the connection? If you can’t figure out what exactly is blocking the connection, we recommend enabling and reviewing the UFW logs, which will show which packets were rejected and all their parameters.
Should you open the database port to the outside? You should almost never do this. It’s better to restrict access to internal IPs or VPNs only, which should be considered as early as the system design phase.
So, we’ve established that UFW (Uncomplicated Firewall) isn’t literally a simplified firewall, but simply a convenient add-on to the built-in firewall that already runs at the kernel level in Linux.
We also discussed the core philosophy - though not unique to UFW - that you should first block all incoming connections and then allow only those that are necessary and only for trusted IP addresses.
It’s important to remember that UFW may not be the only system component with access to the built-in firewall; for example, Docker, Proxmox, and other tools can interact directly with iptables, adding their own rules and bypassing your configuration, which can introduce uncertainty into the server’s operation. However, if this happens, it means your system is already sufficiently complex, and in that case, you should verify the actual rules in effect within the system at a lower level, such as directly in iptables.
A key distinguishing feature of UFW is its ease of maintenance and transparency, thanks to its simple and intuitive syntax.
Ultimately, UFW fulfills a key objective: it gives you quick and clear control over which services are accessible from the outside, ensuring a decent level of security with minimal effort.
What does HTTP error 500 mean, why it occurs, and how to quickly diagnose it. Practical steps, examples, and tips for servers, CMS, and applications.
How can you tell if your website is slow because of CPU, RAM, or disk issues - rather than because of the code? We’ll break down the signs, diagnostic steps, an...
Proxies and VPNs are often confused, but they are different tools. Let’s take a look at how they work, what the differences are, when to use each one, and how t...