Firewall Rule Generator
Choose the ports your server needs and get the same policy twice: as ufw commands and as an nftables ruleset. Both block everything incoming except what you list. Use one of them, not both. Everything runs in your browser; nothing is sent anywhere.
WARNING: read this before you apply anything.
- Docker-published ports bypass ufw. A port published with
-p 8080:8080orports:in a compose file is reachable from the internet even if ufw says "deny". Docker adds its own rules for that traffic, and it takes a different path through the kernel than ufw's input rules (and the nftables input chain below) look at. This firewall protects services running directly on the host, not published container ports. - Fix for Docker: bind the port to localhost (
127.0.0.1:8080:8080) and put a reverse proxy in front, or don't publish it at all. Only the proxy publishes 80 and 443. If you must filter published ports, Docker'sDOCKER-USERchain is the supported place; see the Docker docs on packet filtering or how to check and fix Docker bypassing ufw. The Compose generator builds stacks this way. - Allow SSH before you enable the firewall. The commands below are in that order and SSH is always included. Keep your current session open, then open a second terminal and log in before you close the first one. If you use a non-standard SSH port, enter it below, and make sure it matches
Portin/etc/ssh/sshd_config. - If you do lock yourself out, use the provider's web console (VNC/rescue) to fix it.
Option A: ufw
Option B: nftables /etc/nftables.conf
Load the nftables ruleset
Reminder: neither option filters ports that Docker publishes. Bind those to 127.0.0.1.
What the defaults do
- Deny incoming, allow outgoing. The server can reach out (updates, backups, DNS); nothing can reach it unless you open a port.
- Replies are allowed. The nftables version accepts established and related traffic and drops invalid packets, and always allows the loopback interface.
- ICMP. IPv6 needs ICMPv6 for neighbour discovery, so it is never blocked. Ping is optional. ufw already answers ping through its default
/etc/ufw/before.rules; this tool doesn't change that. - Rate limit. ufw's
limitrule blocks an address that opens six or more connections within 30 seconds. The nftables rule accepts about six new SSH connections per minute (with a short burst) and drops the excess. Neither replaces key-only SSH login. - IPv6. The nftables table is
inet, so it covers IPv4 and IPv6. ufw covers IPv6 whenIPV6=yesin/etc/default/ufw(the default on Debian and Ubuntu).
ufw or nftables?
ufw is simpler and fine for most single servers. nftables is what ufw and iptables sit on top of in current Debian and Ubuntu releases; pick it if you want one readable file you can version-control. Don't run both: they would both manage the same kernel tables. The nftables file here uses its own table (selfhost_fw) and doesn't flush the whole ruleset, which would wipe Docker's rules and break container networking until Docker is restarted.
Check the result
sudo ufw status verbose # ufw sudo nft list ruleset # nftables sudo ss -tulpn # what is actually listening, and on which address # from another machine: nmap -Pn YOUR.SERVER.IP
In ss output, 127.0.0.1:PORT is local only; 0.0.0.0:PORT or *:PORT is reachable from outside, unless a firewall stops it. For Docker, the scan from another machine is the real test.
Related
The firewall is step two in the first 15 minutes on a fresh VPS. The Docker and Caddy post shows the "only the proxy is published" pattern. Services that should start on boot can use the systemd generator.