> For the complete documentation index, see [llms.txt](https://docs.glesys.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.glesys.com/products/compute/guides-for-server-management/set-up-a-firewall-on-ubuntu-22.04-or-newer-using-ufw.md).

# Set up a firewall on Ubuntu 22.04 or newer using UFW

***

Having a functional firewall on the server is an important step in securing the server. In this guide, we will create a basic firewall that you can later extend with your own rules. The guide assumes a newly installed Cloud VM running Ubuntu 22.04 or later. If you want to set up a firewall on Debian 11 or later, we have a guide for that here: "[Set up a firewall on Debian 11 using nftables](/products/compute/guides-for-server-management/set-up-a-firewall-on-debian-11-or-newer-using-nftables.md)".

UFW stands for *Uncomplicated Firewall* and is a tool that simplifies the administration of the built‑in Linux firewall. It comes pre‑installed on Ubuntu by default, but it is disabled.

## Set up some basic rules

Start by verifying that the firewall is disabled. Do this with the command:

{% code title="Command" %}

```
sudo ufw status
```

{% endcode %}

UFW should now respond with `Status: inactive`.

Now you can start adding the rules you need. To avoid risking locking yourself out, begin by allowing SSH:

{% code title="Command" %}

```
sudo ufw allow ssh
```

{% endcode %}

That should give the following output:

{% code title="Output" %}

```
Rules updated
Rules updated (v6)
```

{% endcode %}

Now, let's add the other ports you want to open, such as HTTP and HTTPS. Do this with:

{% code title="Multiple commands" %}

```
sudo ufw allow http
sudo ufw allow https
```

{% endcode %}

Instead of specifying a service name such as `http` or `https`, you can also specify a port number. The syntax would then be `ufw allow 80/tcp` to allow HTTP.

Let's also allow `traceroute`. To do that, you need to open the UDP ports 33434 through 33524. Do this with the following command:

{% code title="Command" %}

```
sudo ufw allow 33434:33524/udp
```

{% endcode %}

Now it’s time to set a default policy for outbound and inbound traffic. By default, the firewall should be configured to allow outbound traffic but deny inbound traffic. To make absolutely sure that this is the case, you can explicitly set these rules with the following command:

{% code title="Multiple commands" %}

```
sudo ufw default allow outgoing
sudo ufw default deny incoming
```

{% endcode %}

Now that you have the most important rules in place, you can enable the firewall. Do this with the command:

{% code title="Command" %}

```
sudo ufw enable
```

{% endcode %}

You will now receive a warning that the firewall might interrupt active SSH connections. Since you have already allowed SSH, answer `y` to the prompt. Afterwards, you get a confirmation that the firewall has been enabled:

<pre data-title="UFW prompt and output. Prompt and input is highlighted."><code><strong>Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
</strong>Firewall is active and enabled on system startup
</code></pre>

Now you have a fully functioning firewall that blocks all incoming traffic except for SSH, HTTP, HTTPS, and `traceroute`. ICMP (`ping`) is already allowed before UFW loads its rules. Check the firewall’s status again:

{% code title="Command" %}

```
sudo ufw status
```

{% endcode %}

This time, it will also display the allowed ports:

{% code title="Output" %}

```
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
33434:33524/udp            ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
33434:33524/udp (v6)       ALLOW       Anywhere (v6)
```

{% endcode %}

Note that UFW has added rules for both IPv4 and IPv6 by default.

## Edit the rules

Adding new rules is no more difficult than running the `ufw allow` command again with the service or port you want to allow. For example, to allow TCP port 8080, you would run:

{% code title="Command" %}

```
sudo ufw allow 8080/tcp
```

{% endcode %}

If we list the status again with `sudo ufw status`, the new port will be shown:

{% code title="Output" %}

```
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
8080/tcp                   ALLOW       Anywhere
33434:33524/udp            ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
8080/tcp (v6)              ALLOW       Anywhere (v6)
33434:33524/udp (v6)       ALLOW       Anywhere (v6)
```

{% endcode %}

If you now want to delete TCP port 8080 from the firewall, use the same syntax you used to add it, but prepend `delete` to the command:

{% code title="Command" %}

```
sudo ufw delete allow 8080/tcp
```

{% endcode %}

A new listing with `sudo ufw status` shows that the port has been removed from both IPv4 and IPv6:

{% code title="Output" %}

```
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
33434:33524/udp            ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
33434:33524/udp (v6)       ALLOW       Anywhere (v6)
```

{% endcode %}

To edit the list with greater precision, you can use a numbered list. This lets you delete a specific rule or insert new rules at a particular position in the list. Start by adding TCP port 8080 again so that you have something to experiment with:

{% code title="Command" %}

```
sudo ufw allow 8080/tcp
```

{% endcode %}

Now we list the status again, but this time using a numbered list. Run the following command:

{% code title="Command" %}

```
sudo ufw status numbered
```

{% endcode %}

This will output the following list:

{% code title="Output" %}

```
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443                        ALLOW IN    Anywhere
[ 4] 33434:33524/udp            ALLOW IN    Anywhere
[ 5] 8080/tcp                   ALLOW IN    Anywhere
[ 6] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 7] 80/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 8] 443 (v6)                   ALLOW IN    Anywhere (v6)
[ 9] 33434:33524/udp (v6)       ALLOW IN    Anywhere (v6)
[10] 8080/tcp (v6)              ALLOW IN    Anywhere (v6)
```

{% endcode %}

Now, for example, you can delete TCP port 8080 for IPv4 but not for IPv6. To do that, delete only rule number 5:

{% code title="Command" %}

```
sudo ufw delete 5
```

{% endcode %}

Here, you also get a prompt asking whether this is the correct rule you want to delete. If it is, answer `y` to the question:

<pre data-title="UFW output, prompt, and anwser. Prompt and answer is highlighted."><code>Deleting:
 allow 8080/tcp
<strong>Proceed with operation (y|n)? y
</strong>Rule deleted
</code></pre>

Similarly, you can insert new rules into the list. Suppose you want to insert TCP port 8080 again, but this time at the third position in the list. You can do that with the following command:

{% code title="Command" %}

```
sudo ufw insert 3 allow 8080/tcp
```

{% endcode %}

A new listing with `sudo ufw status numbered` shows that it succeeded:

{% code title="Command" %}

```
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 8080/tcp                   ALLOW IN    Anywhere
[ 4] 443                        ALLOW IN    Anywhere
[ 5] 33434:33524/udp            ALLOW IN    Anywhere
[ 6] 22/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 7] 80/tcp (v6)                ALLOW IN    Anywhere (v6)
[ 8] 443 (v6)                   ALLOW IN    Anywhere (v6)
[ 9] 33434:33524/udp (v6)       ALLOW IN    Anywhere (v6)
[10] 8080/tcp (v6)              ALLOW IN    Anywhere (v6)
```

{% endcode %}

Delete both rules for TCP port 8080 since this was only used for experimentation:

{% code title="Command" %}

```
sudo ufw delete allow 8080/tcp
```

{% endcode %}

## Block outgoing traffic

To make the server even more secure, you can block all outbound traffic by default and allow only the necessary ports.

First, allow traffic on the necessary ports before changing the policy to block all outbound traffic. The ports you need to allow are HTTP and HTTPS, DNS lookups, NTP requests (for time synchronization), and `traceroute`. You also need to allow DHCPv6 so the server can obtain an IPv6 address. Do this with the following commands:

{% code title="Multiple commands" %}

```
sudo ufw allow out http
sudo ufw allow out https
sudo ufw allow out domain
sudo ufw allow out ntp
sudo ufw allow out 33434:33524/udp
sudo ufw allow out proto udp to ::/0 port 546:547
```

{% endcode %}

The last command above allows outbound IPv6 connections to UDP ports 546 and 547, which are used for DHCPv6. To restrict the rule to IPv6 only, you had to specify the full command with `proto udp to ::/0 port 546:547`. The special address `::/0` represents all IPv6 addresses. For DHCP over IPv4, Ubuntu already includes a working rule that is loaded before the UFW rules.

Before proceeding to change the policy, verify that the changes look correct by listing the rules again with `sudo ufw status`:

{% code title="Output" %}

```
Status: active

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
33434:33524/udp            ALLOW       Anywhere
22/tcp (v6)                ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
33434:33524/udp (v6)       ALLOW       Anywhere (v6)

80/tcp                     ALLOW OUT   Anywhere
443                        ALLOW OUT   Anywhere
53                         ALLOW OUT   Anywhere
123/udp                    ALLOW OUT   Anywhere
33434:33524/udp            ALLOW OUT   Anywhere
80/tcp (v6)                ALLOW OUT   Anywhere (v6)
443 (v6)                   ALLOW OUT   Anywhere (v6)
53 (v6)                    ALLOW OUT   Anywhere (v6)
123/udp (v6)               ALLOW OUT   Anywhere (v6)
33434:33524/udp (v6)       ALLOW OUT   Anywhere (v6)
546:547/udp (v6)           ALLOW OUT   Anywhere (v6)
```

{% endcode %}

Everything looks good. The ports we allow outbound traffic on are marked with `ALLOW OUT` in the list above. Now you can change the firewall policy to deny all outbound traffic that isn’t explicitly allowed in the rules. Run the command:

{% code title="Command" %}

```
sudo ufw default deny outgoing
```

{% endcode %}

The firewall will now output:

{% code title="Output" %}

```
Default outgoing policy changed to 'deny'
(be sure to update your rules accordingly)
```

{% endcode %}

You now have a solid basic firewall that only permits the traffic you explicitly allow. Keep in mind, however, that you may need to adjust the rules to suit the specific services and applications you run on your server.

## If you lock yourself out by accident

Be careful when loading new firewall rules so you don’t lock yourself out of the SSH service (TCP port 22). If you do accidentally lock yourself out, you can log in through the console in Glesys Cloud. You’ll find it under **Compute** → **Virtual machines**. Click **Actions** next to your server’s name and select **Console**. Once you’re logged in, you can either completely disable the firewall with `sudo ufw disable` or fix the rule that is blocking you.

For more information on accessing the console and logging in using single-user mode, see [Connect to the VM console](/products/compute/kvm-virtual-machines/how-tos/connect-to-the-vm-console.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.glesys.com/products/compute/guides-for-server-management/set-up-a-firewall-on-ubuntu-22.04-or-newer-using-ufw.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
