This was copied from my own blog where I explain a bit more about zones, policies and rich rules.
Firewalld works with zones and policies. To accomplish what you want we have to assign all internet facing cards to a VPN-Only zone and create a policy that filters all traffic going into it.
Here I’m going to assume you only want to filter traffic coming from your own machine, therefore the policy will have the ingress zone HOST and the egress zone VPN-Only.
Create the VPN-Only zone:
firewall-cmd --permanent --new-zone VPN-Only
Create the VPN-Killswtich policy:
firewall-cmd --permanent --new-policy VPN-Killswitch
Default target for the policy (this means DROP everything we don’t explicitly allow):
firewall-cmd --permanent --policy VPN-Killswitch --set-target DROP
Reload to apply the changes:
firewall-cmd --reload
Now let’s add the policy rules that allow outbound traffic to the VPN IPs. Repeat this rule for every region replacing 1.2.3.4 with your VPN’s IP. Change openvpn to wireguard if that’s what you are using.
firewall-cmd --policy VPN-Killswitch --add-rich-rule='rule family="ipv4" destination address="1.2.3.4" service name="openvpn" accept'
Allow outgoing traffic to the local network:
firewall-cmd --policy VPN-Killswitch --add-rich-rule='rule family="ipv4" destination address="192.168.1.0/24" accept'
Set the ingress zone:
firewall-cmd --policy VPN-Killswitch --add-ingress-zone HOST
And the egress zone:
firewall-cmd --policy VPN-Killswitch --add-egress-zone VPN-Only
Now we only need to add our networks cards to the VPN-Only zone. This can be done through the NetworkManager GUI (or CLI) or through firewalld.
With NetworkManager open the properties window for the connection you want to filter and on the tab “General configuration” set “Firewall zone” to “VPN-Only”.
Or with firewalld:
firewall-cmd --permanent --zone VPN-Only --add-interface=enp0s8
Test the setup and make it permanent:
firewall-cmd --runtime-to-permanent