Firewall
As my homelab is behind a NAT, I do not really care that much about firewall. However, I do use it to for certain tasks that I think is not that normal. The default config for a firewall is to accept all outgoing connection and drop all incoming. This means that the internal services can connect to internet, but if any of them open up a port to internet, the firewall will drop it. It is essential a block list versus an accept list. But for VyOS the firewall is disabled per default. Why? Because they want a bare bone system which only has the most essential enabled for you as a sysadmin to configure as you would like.
I first thought of using the default firewall set up, with two lists, but felt that it was pretty difficult to configure. What made worse, it was designed to be easier, but not like iptable or nftable. I therefore opted to for an accepting config and blocking only what was necessary, more on that below. In VyOS 1.5 they changed the config further, to work in similar fashion to previous mentioned services. I therefore, due to a previous Ansible restructure, decided to make more use of the firewall, at least for a starter. First, I need to mention that a firewall is basically a state machine 1, where each client connected would have to go through a set of rules, and if any of them are triggered, would execute an action, being accepting, rejecting or outright dropping a connection. In addition, you can nest these actions by jumping to other actions. There are more around how this works but I will not go through it yet as I am not entirely sure myself.
The configuration I first used was rather trivial. I allow all connections from outside. The reason for this was that while it could pose a threat, I saw it more of another point of failure and therefore relied on the NAT port-forwarding to act as my first point of defense. Do note that for a router this could be fine to some extent, but for a service which could be easily compromised it could mean it taking out the rest of the infrastructure, so it is good to be cautious in those instances and block in either direction. What I configured was that I added two sets of lists, the first being a known public DNS servers, being IPv4 or IPV6, which was used to block any outgoing DNS requests, mostly from IoT devices. This forced all my devices to use the internal DNS. Do note that my DNS services use unbound, meaning it talks directly to name servers for the DNS data. The list also stopped DoH 2 requests, so that was the main reason for going this route. The second list was basically banned IPs being dropped from accessing any of my services. I currently only have one, because I have only seen one trying to DDoS 3 my router, and that was years ago. Though, this list can be expanded further for years to come, just need some malicious clients first.
I did try once to apply a big filter for known bad IP ranges, but that ended up most universities, VPS hosts and companies being unable to access my services. I could limit this further, but I currently do not think this is necessary, so I left it out. Also, applying that list took minutes, and due to how Ansible for VyOS 4 works, that time was applied each time I tried to update anything. My optimized Ansible action could have solved that, but as I previously mentioned it was not desirable.
The previous config I kept for two years, but when I just recently upgraded to VyOS 1.5, I found their change in the firewall config, so I chose to add more states to it. The specifically one was to reject all outgoing connections on port 53, but those DNS services I run myself. I have been wanting to do this for a while, but did not know exactly how. This also gave me a reason to dive deeper into firewalls, VyOS firewall specifically. In short, I first added a state which returned if it the client was in the DNS list, otherwise reject. I then added an action that checked for port 53 and jump into previous mentioned state. Not fancy, but it works.
This is of course not perfect, as it wont stop malicious clients to access private DNS servers through DoH, but it will works for more than 99% of the time, and I find that rather acceptable considering my own situation.