NFTABLES KILLSWITCH
Configuring nftables
as a kill switch
to block any external connection without an active VPN connection.
Requirements#
- Blocking all connections that are not explicitly allowed
- Allow some connections to external/internal networks:
- External VPN server IP’s
- External NTP server IP’s
- Local network connection
Install#
Disable iptables#
sudo systemctl stop --now iptables
sudo systemctl disable --now iptables
Install nftables config file#
# Backup original nftables config file
sudo cp /etc/nftables.conf /etc/nftables.conf.ORIGINAL
# Use your killswitch file as nftable config file
sudo cp /tmp/killswitch.nft /etc/nftables.conf
# Enable nftable systemd service and apply rules
sudo systemctl enable --now nftables
# For disable killswith:
sudo systemctl stop --now nftables
sudo systemctl disable --now nftables
sudo nft flush ruleset
Disable IPv6#
Disable IPv6 on the local system. Unless you make use of local network IPv6 resources, it may be simplest to disable IPv6 entirely.
Run these commands:
echo 'net.ipv6.conf.all.disable_ipv6=1' | sudo tee -a /etc/sysctl.d/disable-ipv6.conf
echo 'net.ipv6.conf.default.disable_ipv6=1' | sudo tee -a /etc/sysctl.d/disable-ipv6.conf
echo 'net.ipv6.conf.lo.disable_ipv6=1' | sudo tee -a /etc/sysctl.d/disable-ipv6.conf
sudo sysctl --system
# To undo the change and restore IPv6 on your system,
# change the disable_ipv6=1 bits to disable_ipv6=0 or manually edit the /etc/sysctl.d/disable-ipv6.conf
# file and remove the three disable_ipv6=1 lines, then run sudo sysctl --system.
# Don't forget to remove /etc/sysctl.d/disable-ipv6.conf file because after rebbot
# this rules apply again.
Nftable config file#
#!/usr/sbin/nft -f
## /tmp/killswitch.nft
## FLUSH existing rules and create a table called "killswitch".
flush ruleset
add table inet killswitch
## NETWORK interfaces: Run "ip a" to confirm local interface device names.
### Outbound network interface
define INET_DEV = eth0
### VPN client interface
### tun*, ppp*, etc.
define VPN_DEV = tun0
## VPN servers IP list
### Can use
### dig +short {0..1}.myvpn.net | sort -h
### for get list of ip if you vpn provider provide static list of domains
# define VPN_SERVERS = 10.10.10.10
# define VPN_SERVERS = { 10.10.10.10, 11.11.11.1-11.11.11.254, 12.12.12.0/24 }
define VPN_SERVERS = { 10.10.10.10, 11.11.11.11 }
## NTP servers
## Ideally to use local NTP servers but if not exist ...
## dig +short {0..1}.pool.ntp.org | sort -h
define NTP_SERVERS = { 62.205.159.153, 91.198.10.4, 91.231.182.17, 91.236.251.14, 91.236.251.234, 91.236.251.29, 91.236.251.34, 95.67.102.33 }
## LAN
## CIDR of Local network or list of individual addresses that you need to access without an active vpn connection
## You need to uncomment the rule below as it is disabled by default.
# define LAN_CLIENTS = { 192.168.0.2, 192.168.0.4-192.168.0.6 }
define LAN_CLIENTS = 192.168.0.0/24
## DROP everything by default for all chains ("INPUT", "FORWARD", "OUTPUT").
add chain inet killswitch INPUT { type filter hook input priority 0 ; policy drop ; }
add chain inet killswitch FORWARD { type filter hook forward priority 0 ; policy drop ; }
add chain inet killswitch OUTPUT { type filter hook output priority 0 ; policy drop ; }
## LOOPBACK: Some local processes need to hear from other ones.
add rule inet killswitch INPUT iifname "lo" counter accept
## LAN BROADCAST: You may need to allow traffic from local DHCP servers.
add rule inet killswitch INPUT iifname $INET_DEV ip saddr 255.255.255.255 counter accept
## OPTIONAL: Allow incoming SSH (22/TCP), etc. from LAN.
## Uncomment if required or add additional rules for another services.
# add rule inet killswitch INPUT iifname $INET_DEV tcp dport 22 counter accept
## ALLOW related/established traffic and drop everything else without acknowledgement to peers.
add rule inet killswitch INPUT ct state related,established accept
add rule inet killswitch INPUT counter drop
## FORWARDING: Your device is not a router, so do not allow forwarding.
## Just dropping any forwarded packats
add rule inet killswitch FORWARD counter drop
## if you want to logging these packages, that use this variant
# add rule inet killswitch FORWARD counter log prefix "NFT drop fwd: " drop
## LOOPBACK: Some local processes need to talk to other ones.
add rule inet killswitch OUTPUT oifname "lo" counter accept
## NTP: Allow outbound NTP requests because OpenVPN’s certificate system is sensitive to time discrepancies.
add rule inet killswitch OUTPUT oifname $INET_DEV ip daddr $NTP_SERVERS udp dport 123 counter accept
## VPN: Allow outbound traffic to VPN servers defined above.
add rule inet killswitch OUTPUT oifname $INET_DEV ip daddr $VPN_SERVERS counter accept
## VPN: Allow outbound traffic through the VPN tunnel.
add rule inet killswitch OUTPUT oifname $VPN_DEV counter accept
## LAN BROADCAST: You may need to allow traffic to local DHCP servers.
add rule inet killswitch OUTPUT oifname $INET_DEV ip daddr 255.255.255.255 counter accept
## OPTIONAL: Allow outbound traffic to local network.
#add rule inet killswitch OUTPUT oifname $INET_DEV ip daddr $LAN_CLIENTS counter accept
## ALLOW related/established traffic.
add rule inet killswitch OUTPUT ct state related,established accept
## DROP everything else, without acknowledgement to peers.
## LOGGING is useful for testing, though may consume log files over time.
## Choose one rule or the other from below.
add rule inet killswitch OUTPUT counter drop
# add rule inet killswitch OUTPUT counter log prefix "NFT drop out: " drop
Read other posts