There are some guides available online on how to do this, but they don’t really offer what I need.
Also, they seem very complicated and I wonder if there’s not an easier solution.
Basically, I want to block all incoming and all outgoing traffic except outgoing VPN traffic on the tun0 interface.
The only traffic allowed outside of tun0 should be the initial connection to the VPN server (to be more specific, the ip address of the VPN server should be whitelisted so I can establish the VPN connection).
I once used to do this via iptables / ufw using the following commands:
ufw default deny outgoing
ufw default deny incoming
ufw allow out on tun0 from any to any
ufw allow out from any to 22.214.171.124
(126.96.36.199 is just an example for the ip address of the VPN server).
Can someone please tell me how I can get the same effect with firewalld or firewall-config?
Unless something has changed recently, firewalld isn’t particularly good at managing outbound traffic. I set up a VPN machine as you are describing about a year ago and I had to add manual rules to block the outbound traffic using firewall-cmd --permanent --direct and then manually specifying them using syntax similar to iptables rules. I would share the rules with you but…
I lost that VM last week due to an unfortunate mistake and when I rebuilt it I just removed firewalld and installed ufw instead. It was much easier for that application.
Of course, if your machine is a general purpose desktop then the advantages of firewalld might outweigh the difficulties. In my case, it was dedicated machine I was using for when I wanted a VPN connection.
On general purpose workstations, I love firewalld. But for blocking outbound traffic, I usually switch to ufw because it is a handful of simple rules. That being said, it is possible to achieve your goal with either.
I believe the package iptables-nft provides a bridge between the iptables rules and nftables implementation.
In general case, some prerequisites must considered while implementing a kill switch:
DHCP/DHCPv6/ICMPv6 to configure and update IPv4/IPv6/SLAAC when necessary.
NTP to sync time to properly establish secure connections.
DNS to resolve NTP servers and VPN endpoints.
Otherwise the relevant system services may become deadlocked due to race conditions.
This can happen upon system reboot, temporary loss of connectivity, DHCP lease timeout, etc.
A firewall-based kill switch should work for OpenVPN.
But NetworkManager provides a built-in PBR-based kill switch for WireGuard.
It does not require any extra actions and is much easier to operate.
Besides better performance, this is another reason to use to WireGuard if possible.