Skip to main content

Firewall basics: ufw and firewalld without the fear

Default-deny, allow only what you serve, and never lock yourself out.

A firewall is a list of who may talk to what. The whole game is: deny everything by default, then allow the handful of ports you actually serve.

The mental model

  • Inbound — someone connecting to your server. Default deny.

  • Outbound — your server connecting out. Usually allow all; you rarely want to restrict this.

  • Stateful — replies to connections you started are allowed automatically. You do not need a rule for them.

ufw (Debian, Ubuntu)

bash
apt install -y ufw

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp

# ALWAYS check the plan before enabling
ufw show added

ufw enable
ufw status verbose

Common extras:

bash
ufw allow from 203.0.113.5 to any port 22     # SSH from one IP only
ufw allow 25,465,587/tcp                      # mail submission
ufw allow 3478/udp                            # a TURN/STUN range for video calls
ufw delete allow 8080/tcp                     # remove a rule
ufw reset                                     # wipe all rules (dangerous)

firewalld (AlmaLinux, Rocky, Fedora)

bash
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all

Richer rules:

bash
# allow a specific port and make it permanent at once
firewall-cmd --permanent --add-port=3478/udp
firewall-cmd --reload

# allow an SSH connection from one subnet only (use a rich rule)
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.75.0.0/16" service name="ssh" accept'
firewall-cmd --reload

Never lock yourself out

The classic failure: you enable a firewall that drops your SSH port, and the session dies.

  1. Allow the SSH port before enabling.

  2. Enable while connected, and the moment it is on, open a second terminal and test a fresh login.

  3. Keep the first session open until the second succeeds.

  4. If you still lose access, use the rescue console in /panel/vps.

Our private mesh

Your VPS joins our WireGuard mesh on a private interface. If you filter aggressively, remember two things: allow the mesh interface (allowed on wg0 in ufw terms, or add the mesh subnet as a trusted source in firewalld), and allow established/related traffic. Locking the mesh out breaks monitoring, backups and our management plane.

Firewall vs fail2ban vs security groups

  • The firewall decides which ports exist at all.

  • fail2ban reacts to repeated failed attempts by banning the source IP. See Fail2ban basics.

  • A cloud security group, where present, filters even earlier. If a port is closed at the provider layer, your host firewall never sees the traffic.

Together they are layered defence: a smaller surface, then automatic blocking, then early filtering.

Related reading