MHOSTMHOST

The ufw firewall: managing ports

ufw (Uncomplicated Firewall) is a simplified front end for the Linux kernel's built-in firewall (netfilter/iptables): instead of writing out long iptables chains, you describe rules with simple commands like ufw allow 80/tcp. In this article you'll install and enable ufw on your mHost VPS, deny all incoming connections by default, open the ports you need — SSH, HTTP/HTTPS, and one of your own — and learn to list the rules and remove the ones you no longer need.

Diagram: incoming traffic hits the firewall — ports 22, 80 and 443 are allowed through to the server, everything else is blocked

What you'll need

  • An mHost VPS on Ubuntu 22.04/24.04 or Debian 11/12 — ufw is the default firewall on exactly these systems.
  • On AlmaLinux/Rocky Linux the default tool is firewalld instead, with different commands; this article doesn't cover it.
  • SSH access as root or a user with sudo rights.
  • Access to the VMmanager 6 panel — as a safety net in case you do lock yourself out over SSH: the panel has a browser-based server console that doesn't depend on SSH. If you haven't logged in yet, start with "How to log in to VMmanager 6".
Important: the most common mistake when setting up ufw is turning the firewall on without first allowing SSH. The result is a dropped SSH session and lost remote access to the server. Make sure to complete Step 3 (allow SSH) before Step 4 (enable ufw) — the order of steps in this article is deliberate.

Step 1. Install ufw

On Ubuntu, ufw is usually already installed out of the box (but disabled); on Debian you need to install it separately. The command below is safe in both cases — on Ubuntu it will simply confirm the package is already there:

bash
sudo apt update
sudo apt install -y ufw

Check that the command is available:

bash
sudo ufw version

The command should print the ufw version number. If you get command not found instead, check that the package installation above completed without errors.

Step 2. Set the default policy: deny incoming

The whole point of a default-deny firewall is that everything not explicitly allowed by a rule is blocked. Set that explicitly:

bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
  • deny incoming — any new incoming connection is blocked unless there's a specific allow rule for it.
  • allow outgoing — connections initiated by the server itself (package updates, requests to external APIs, and so on) are allowed.

This is actually ufw's factory-default policy already, but it's worth setting explicitly so the policy is a deliberate choice rather than whatever happened to be there. Neither command turns anything on or affects existing connections — the rules only take effect after Step 4.

Step 3. Allow SSH — before you turn the firewall on

Important: this is the single most important step in this article. As soon as you enable ufw with a deny-incoming policy (Step 4), any connection without an explicit allow rule is blocked immediately — including your own SSH connection. If you don't allow SSH beforehand, you will lose remote access to the server the moment you run ufw enable.

Allow the SSH port (22/tcp by default):

bash
sudo ufw allow 22/tcp
Tip: if you've already changed SSH to a non-standard port (see the article on hardening SSH), use that port number here instead of 22. For the standard port, sudo ufw allow ssh gives the same result (ufw looks up port 22 by service name in /etc/services), and on Ubuntu so does sudo ufw allow OpenSSH (an application profile registered by the openssh-server package; that profile may not exist on Debian).
If you do get locked out: you can disable or fix the rule from the VMmanager 6 server console — it opens right in the browser and doesn't depend on SSH. See "How to log in to VMmanager 6" for details.

Step 4. Enable ufw

bash
sudo ufw enable

ufw will warn you that the operation may disrupt existing SSH connections:

Command may disrupt existing ssh connections. Proceed with operation (y|n)?

Since you already allowed SSH in Step 3, confirm with y. The setting persists: after a server reboot, ufw comes back on automatically in the same state — there's no separate systemd autostart to configure.

Check the status, and — without closing your current SSH session — open a new connection in a separate terminal window. Only close the old session once you've confirmed the new SSH login still works:

bash
sudo ufw status
Done: the status is Status: active and the new SSH connection opens without trouble — the firewall is on and you haven't locked yourself out.

Step 5. Open HTTP, HTTPS, and your own port

Allow the standard web ports:

bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Tip: you can allow several ports in one command using a comma: sudo ufw allow 80,443/tcp.

To open an arbitrary port for your own application or service, specify its number and protocol:

bash
sudo ufw allow 8080/tcp
  • Always specify the protocol explicitly — /tcp or /udp. If you omit it, ufw opens the port for both at once, when usually you only need one.
  • Only open a port once something on the server is actually listening on it — otherwise it's just an unused hole in the firewall.
Tip: to allow a port only from a specific IP address rather than from the whole internet, add from: sudo ufw allow from 203.0.113.10 to any port 8080 proto tcp.
Important: if another mHost guide sent you to this section for a specific service (a web server or an application, for example), go back there and open exactly the port it specifies.

Step 6. Check the rules: status numbered

Plain ufw status lists rules without numbers. To get a number for every rule — for example, before deleting one — use:

bash
sudo ufw status numbered

Example output after the steps above (rules are automatically duplicated for IPv6 — that's the default behavior, unless IPV6=yes has been turned off in /etc/default/ufw):

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 8080/tcp                   ALLOW IN    Anywhere
[ 5] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 6] 80/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 7] 443/tcp (v6)               ALLOW IN    Anywhere (v6)
[ 8] 8080/tcp (v6)              ALLOW IN    Anywhere (v6)

The number in brackets is what you'll need in the next step.

Step 7. Delete a rule

Say you no longer need port 8080. Look up its rule number (Step 6) and delete it:

bash
sudo ufw status numbered
sudo ufw delete 4

ufw first shows exactly which rule it's about to delete (Deleting: allow 8080/tcp), then asks for confirmation:

Proceed with operation (y|n)?

Confirm with y.

Important: deleting a rule shifts the numbers of all the remaining ones. If you need to delete several rules in a row, delete from the highest number down to the lowest, and re-check ufw status numbered before every next deletion — otherwise it's easy to delete the wrong rule.
Tip: for a rule that has both an IPv4 and an IPv6 version (like 8080/tcp in the example above — numbers 4 and 8), it's simpler to remove both in one command by matching the rule's content instead of its number: sudo ufw delete allow 8080/tcp.

To confirm the rule is gone, run sudo ufw status numbered again.

Done: the rule is deleted and the rule list is updated — repeat for any other rule on the list if you need to.

What's next

For deeper SSH protection — changing the port, key-only login — see "Hardening SSH". Fail2ban adds automatic IP banning for repeated failed logins — see "Fail2ban: blocking brute-force attempts". And if you need netfilter capabilities that ufw's simplified syntax doesn't expose, the basic iptables commands are covered in "iptables basics".