UFW, or Uncomplicated Firewall, makes it easy to manage firewall rules on Linux and is available on several distributions.
I’m using this on web and email servers. It’s desirable to, by default, block inbound connections and only ports for the services they provide are allowed. This seems to be the only scenario covered in most examples.
But what about outbound connections? This is often set to allow by default. This seems reasonable, but what if the server is compromised in some way and used by an attacker to attack other systems. Now you’re server is the source of an attack. Since the server likely needs to access little, if any, other services on remote systems, blocking all outbound access by default will limit what an attacker or other misbehaving software can access.
Info on how to do this seems a bit hard to find, so here’s how to do it.
Configure your inbound policy to block by default and allow needed services you wish to provide as covered in numerous examples. This tutorial actually suggests blocking outbound connections default, but doesn’t explain how to allow connections.
Determine what services you’re server actually needs to access. For example, a web server may need to access your MySQL database and mail servers, and possibly other remote web servers to fetch data for display in the pages it serves. It’ll also need access to DNS.
First, allow access to any DNS server:
ufw allow out 53/udp ufw allow out 53/tcp
Allow access to your mail server at 1.2.3.4 so the web server can send mail:
ufw allow out from any to 1.2.3.5 port 25 proto tcp
Allow access to your MySQL at 1.2.3.5:
ufw allow out from any to 1.2.3.5 port 3306 proto tcp
Allow access to any remote web server:
ufw allow out 80/tcp ufw allow out 443/tcp
It may be desirable to limit access to DNS servers by specifying IP addresses as in the mail and MySQL examples above.
Finally, set the default behavior for the firewall to deny outgoing connections:
ufw default deny outgoing
View the configuration, verbose is needed t see the default policy.
ufw status verbose
Output will look something like this. The ALLOW OUT lines are the outbound connections we’ve allowed. Note that the default action for outgoing is now deny.
Status: active Logging: on (low) Default: deny (incoming), deny (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere 80/tcp (v6) ALLOW IN Anywhere (v6) 443/tcp (v6) ALLOW IN Anywhere (v6) 80/tcp ALLOW OUT Anywhere 443/tcp ALLOW OUT Anywhere 53/tcp ALLOW OUT Anywhere 53/udp ALLOW OUT Anywhere 1.2.3.4 25/tcp ALLOW OUT Anywhere 1.2.3.5 3306/tcp ALLOW OUT Anywhere 80/tcp (v6) ALLOW OUT Anywhere (v6) 443/tcp (v6) ALLOW OUT Anywhere (v6) 53/tcp (v6) ALLOW OUT Anywhere (v6) 53/udp (v6) ALLOW OUT Anywhere (v6)