ufw — Firewall Basics
Every program that listens on a port — ssh on 22, nginx on 80, a database on 3306 — can be reached by anyone who can reach your server. A firewall decides who may connect to which port. On Debian the easy way to drive the kernel's firewall is ufw, the uncomplicated firewall:
sudo apt install ufw
sudo ufw status # Status: inactive
Rule number one: SSH first
You are logged in over SSH. Turn on a firewall that doesn't allow SSH, and your next login fails — on a server in a data centre, that means a support ticket to the hosting company. So allow it before you enable anything:
sudo ufw app list # profiles of what's installed: Nginx Full, OpenSSH, …
sudo ufw allow OpenSSH # the same as: sudo ufw allow 22/tcp
Turn it on
sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup
From now on, everything that comes in is refused — unless a rule allows it. Everything that goes out is allowed.
sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
OpenSSH ALLOW IN Anywhere
OpenSSH (v6) ALLOW IN Anywhere (v6)
Every rule is there twice: once for IPv4, once for IPv6 (v6).
Open what you serve
sudo ufw allow http # a name from /etc/services: port 80/tcp
sudo ufw allow 443/tcp # a port and its protocol
sudo ufw allow 'Nginx Full' # an app profile: 80 and 443
Look, and remove
sudo ufw status numbered
sudo ufw delete allow http # repeat the rule after "delete"
sudo ufw delete 3 # or give its number
Watch it work
A server on the internet is knocked on all day: scanners trying every port, bots guessing ssh passwords. What the firewall stops, it writes down:
sudo tail /var/log/ufw.log
Oct 30 21:10:45 linux kernel: [UFW BLOCK] IN=eth0 OUT= … SRC=45.155.205.233 DST=172.17.0.2 … PROTO=TCP SPT=37125 DPT=3389 …
SRC is who knocked, DPT which of your ports they wanted.
⚠️ A firewall only filters connections from other machines.
curl localhostkeeps working whatever the rules say — to be sure a port is open, test from outside (your laptop).
| Command | Does |
|---|---|
ufw status [verbose|numbered] | is it on, and its rules |
ufw allow PORT[/tcp] / ufw allow NAME | open a port |
ufw deny PORT | close it explicitly |
ufw delete RULE / ufw delete NUM | remove a rule |
ufw enable / ufw disable | on / off |