1. Introduction §
This blog post is about designing firewall rules, not focusing on a specific operating system.
The idea came after I made a mistake on my test network where I exposed LAN services to the Internet after setting up a VPN with a static IPv4 on it due to too simplistic firewall rules. While discussing this topic on Mastodon, some mentioned they never know where to start when writing firewall rules.
2. Firewall rules ordering §
Firewall rules are evaluated one by one, and the evaluation order matters.
Some firewall use a "first match" type, where the first rule matching a packet is the rule that is applied. Other firewalls are of type "last match", where the last matching rule is the one applied.
3. Block everything §
The first step when writing firewall rules is to block all incoming and outgoing traffic.
There is no other way to correctly configure a firewall, if you plan to block all services you want to restrict and let the default allow rule do its job, you are doing it wrong.
4. Identify flows to open §
As all flows should be blocked by default, you have to list what should go through the firewall, inbound and outbound.
In most cases, you will want to allow outbound traffic, except if you have a specific environment on which you want to only allow outgoing traffic to a certain IP / port.
For inbound traffic, if you do not host any services, there are nothing to open. Otherwise, make a list of TCP, UDP, or any other ports that should be reachable, and who should be allowed to reach it.
5. Write the rules §
When writing your rules, whether they are inbound or outbound, be explicit whenever possible about this:
- restrict to a network interface
- restrict the source addresses (maybe a peer, a LAN, or anyone?)
- restrict to required ports only
Eventually, in some situations you may want to filter by source and destination port at the same time. This is usually useful when you have two servers communicating over a protocol enforcing both ports.
This is actually where I failed and exposed my LAN minecraft server to the wild. After setting up a VPN with a static IPv4 address, I only had a "allow tcp/25565" rule on my firewall as I was relying on my ISP router to not forward traffic. This rule was not effective once the traffic was received from the VPN, although it would have been filtrated when using a given network interface or a source network.
If you want to restrict the access of a critical service to a some user (1 or more), but that they do not have a static IP address, you should consider using a VPN for this service and restrict the access to the VPN interface only.
Firewall rules will evolve over time, you may want to write for your future you why you added this or that rule. Ideally, use a version control system on the firewall rules file, so you can easily revert changes or track history to understand a change.
7. Do not lock yourself out §
When applying the firewall rules the first time, you may have made a mistake and if it is on remote equipment with no (or complicated) physical access, it is important to prepare an escape.
There are different methods, the most simple is to run a command in a second terminal that sleeps for 30 seconds before resetting the firewall to a known state, you have to run this command just before loading the new rules. So if you are locked out after applying, just wait 30 seconds to fix the rules.
8. Add statistics and logging §
If you want to monitor your firewall, consider adding counters to rules, it will tell you how many times it was evaluated/matched and how many packets and traffic went through. With nftables on Linux they are named "counters", whereas OpenBSD packet filter names this "label".
It is also possible to log packets matching a rule, this can be useful to debug an issue on the firewall, or if you want to receive alerts in your logs when a rule is triggered.
9. Conclusion §
Writing firewall rules is not a hard task once you identified all flows.
While companies have to maintain flow tables, I do not think it can be useful for a personal network (your mileage may vary).