Set up UFW without losing SSH
A firewall that blocks your own SSH session is worse than no firewall. The order of the commands is what keeps you connected. Allow SSH, set the defaults, check, then enable.
Published . Ubuntu Server 22.04 and 24.04, and Debian 11 to 13 with the ufw package installed.
- Why the order matters
- Find your SSH port
- Allow SSH first
- Set the default policy
- Enable it and test with a second session
- Read the status
- Keep IPv6 covered
- Rate-limit SSH
Why the order matters
UFW is off when you install it. The moment you turn it on with a default policy of deny, every incoming connection that no rule allows is dropped. That includes SSH. If you enable first and add rules later, you may never get to add them.
So the plan is always the same: add the SSH rule, set the defaults, look at what you are about to load, and only then enable. You can add rules while UFW is inactive. They are saved and take effect when you enable it.
Find your SSH port
Don't assume it's 22. If you or your provider changed it, a rule for 22 won't help you. Ask the server what sshd listens on:
sudo ss -tlpn | grep sshd
The number after the last colon in the local address is your port. Then install UFW if it isn't there yet and check its state:
sudo apt install ufw
sudo ufw status
On a fresh server this says Status: inactive.
Allow SSH first
On Ubuntu, the openssh-server package ships a UFW application profile. List the profiles to see its name, then allow it:
sudo ufw app list
sudo ufw allow OpenSSH
The profile covers the standard port only. If SSH runs on another port, allow the number instead:
sudo ufw allow 2222/tcp
If you only ever connect from one fixed address, you can narrow it to that address. Only do this if the address really never changes:
sudo ufw allow proto tcp from 203.0.113.7 to any port 22
Add the other services the server must answer, for example a web server:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Set the default policy
The defaults decide what happens to traffic that no rule matches. For a server, that is: drop what comes in, let out what the server starts itself.
sudo ufw default deny incoming
sudo ufw default allow outgoing
Set them explicitly, so you know what they are rather than trusting whatever an earlier admin or image left behind. Before you enable anything, list the rules you added:
sudo ufw show added
Your SSH rule must be in that list. If it isn't, stop and add it.
Enable it and test with a second session
Keep your current SSH session open until a new one works. Enabling UFW can drop existing connections. When you run it over SSH, UFW asks you to confirm for that reason. Answer y, then open a new terminal and connect again before you close anything. If the new connection fails, you still have the old one to fix the rule or run sudo ufw disable.
sudo ufw enable
Enabling also turns the firewall on at boot. If you want a timer that turns it off again unless you confirm, see locked out after ufw enable.
Read the status
sudo ufw status verbose
Check three things in the output:
Status: active.- The
Default:line reads deny for incoming and allow for outgoing. - Your SSH port is in the rule list.
Anywheremeans any address:0.0.0.0/0for IPv4 and::/0for IPv6. Rules marked(v6)are the IPv6 copies.
To remove a rule later, list them with numbers and delete by number:
sudo ufw status numbered
sudo ufw delete 3
The IPv4 and IPv6 versions of a rule have separate numbers, so deleting one number removes only one of them. Run status numbered again after each delete, since the numbers shift.
Keep IPv6 covered
Many VPS servers have a public IPv6 address as well as IPv4. A firewall that only covers IPv4 leaves the same services open on the other address. UFW handles IPv6 when IPV6=yes is set in /etc/default/ufw, which is the default. Check it:
grep IPV6 /etc/default/ufw
If it says no, UFW only accepts IPv6 on loopback, so SSH over IPv6 stops working too. To change it, edit the file and run sudo ufw reload.
Rate-limit SSH
Bots try passwords on port 22 all day. A limit rule still allows SSH, but blocks an address that opens 6 or more connections within 30 seconds. Use it in place of the plain allow rule:
sudo ufw limit OpenSSH
# or, on a custom port
sudo ufw limit 2222/tcp
Then run sudo ufw status numbered. If an old ALLOW rule for the same port is still listed next to the new LIMIT rule, delete the ALLOW one. Keep in mind that scripts which open many SSH connections in a row from one address can hit the limit too. Rate limiting slows guessing down. It doesn't replace key-only login: see SSH hardening without lockout.
One more thing to know: if you run Docker, ports it publishes skip these rules. Read Docker bypasses UFW, and confirm the result from outside with a real port check.
Stenvakt sets this up with a safety net. Its Review shows which ports are open and whether a firewall is on at all. You see a Preview of every rule before it runs, and the fix runs in safe mode: if the change cuts off SSH, the server rolls it back by itself. It's a Mac app and isn't out yet: get early access.
Sources
- ufw(8) manual page, Ubuntu 24.04 (manpages.ubuntu.com)
- ufw-framework(8) manual page, Ubuntu 24.04 (manpages.ubuntu.com)
- Ubuntu Server documentation: Firewall
- Launchpad bug 261884: Add UFW profile integration with OpenSSH