ufw Basics on Ubuntu
I like iptables, but I've mistyped one rule on a remote server and spent the next half hour on the provider's web console. That's why I use ufw on most Ubuntu boxes. It turns everyday firewall work into one-liners and still writes real iptables rules underneath. On 16.04 it's installed but disabled.
These are the handful of commands I use on nearly every server. Ubuntu 14.04 or 16.04, sudo access, and mind the order below so you don't lock yourself out.
1. Check the state and set defaults
Before enabling anything, look at the status and set the default policies. Denying incoming and allowing outgoing is the right starting point for almost every server.
sudo ufw status verbose
sudo ufw default deny incoming
sudo ufw default allow outgoing
These defaults are recorded in /etc/default/ufw and /etc/ufw/user.rules; you rarely need to touch those files directly.
2. Allow SSH before enabling the firewall
Everybody skips this once and regrets it. Add a rule for SSH first. ufw understands service names from /etc/services, so ssh and 22/tcp are equivalent:
sudo ufw allow ssh
If sshd listens on a non-standard port, name the port explicitly:
sudo ufw allow 2222/tcp
I use limit instead of allow for SSH on anything public. instead of allow for SSH. It permits connections but blocks a source IP that opens more than six connections in thirty seconds, which takes the edge off brute-force attempts:
sudo ufw limit ssh
3. Enable it
sudo ufw enable
You will be warned that the command may disrupt existing SSH connections. Because the SSH rule is already in place, it will not. ufw is now active and will start at boot via its systemd unit.
4. Open what your services need
For a web server:
sudo ufw allow http
sudo ufw allow https
ufw also ships application profiles in /etc/ufw/applications.d/. Packages such as nginx and Apache register their own, so you can write:
sudo ufw app list
sudo ufw allow 'Nginx Full'
To restrict a service to a single source, for example MySQL from an application server only:
sudo ufw allow from 10.0.0.5 to any port 3306 proto tcp
Whole subnets work too:
sudo ufw allow from 10.0.0.0/24 to any port 5432 proto tcp
5. Deleting and reordering rules
List rules with numbers so you can refer to them precisely:
sudo ufw status numbered
sudo ufw delete 3
You can also delete by repeating the original rule with delete in front:
sudo ufw delete allow http
Rules are evaluated in order, and deny rules for specific hosts should come before broad allow rules. Use insert to place a rule at a given position:
sudo ufw insert 1 deny from 198.51.100.7
6. Logging
ufw logs to /var/log/ufw.log (and to the kernel log) once you enable it:
sudo ufw logging low
low logs blocked packets only, which is what I want most of the time. medium and high add allowed packets and rate-limit information and get noisy quickly.
Check what's really in effect
sudo ufw status verbose
You should see Status: active, the default policies, and each rule with its action and source. To see the underlying iptables rules ufw generated:
sudo iptables -L ufw-user-input -n
From another machine, nc -zv 203.0.113.30 3306 should time out or be refused unless that machine is in an allowed source range.
Gotchas
ERROR: Could not find a profile matching 'Nginx Full'. The application profile only exists after the nginx package is installed. Usesudo ufw allow 80,443/tcpinstead.- Enabled ufw and lost the SSH session. You skipped the SSH rule. From the provider console run
sudo ufw allow ssh, orsudo ufw disableto start over. - Docker containers reachable despite ufw rules. Docker inserts its own iptables rules that bypass the ufw chains. Either bind published ports to
127.0.0.1in the container's port mapping, or set"iptables": falsein/etc/docker/daemon.jsonand manage the rules yourself. - IPv6 rules missing. Check that
IPV6=yesis set in/etc/default/ufw, then runsudo ufw disable && sudo ufw enableso the v6 rules are generated.
ufw won't replace iptables for complicated setups, but for a single server it's plenty. For anything fancier you can still drop raw rules into /etc/ufw/before.rules.