Skip to content

Instantly share code, notes, and snippets.

@0xc0392b
Created March 20, 2023 08:32
Show Gist options
  • Select an option

  • Save 0xc0392b/27b39a319efc88e8caaa24c0afe3751d to your computer and use it in GitHub Desktop.

Select an option

Save 0xc0392b/27b39a319efc88e8caaa24c0afe3751d to your computer and use it in GitHub Desktop.
nftables ruleset for secure home router with VPN
#!/usr/sbin/nft -f
# based on
# https://wiki.nftables.org/wiki-nftables/index.php/Simple_ruleset_for_a_home_router
# https://www.ivpn.net/knowledgebase/linux/linux-how-do-i-prevent-vpn-leaks-using-nftables-and-openvpn/
# reset
flush ruleset
# devices
define DEV_WORLD = wlan0
define DEV_PRIVATE = eno1
define DEV_TUNNEL = tun0
# networks
define NET_PRIVATE = 192.168.100.0/24
# VPN servers
define VPN_SERVERS = { xxx.xxx.xxx.xxx }
table ip global {
chain inbound_world {
# accept traffic from local DHCP servers
ip saddr 255.255.255.255 counter accept
}
chain inbound_private {
# accept pings on private interface
icmp type echo-request limit rate 5/second accept
# accept dhcp, ssh, dns on private interface
ip protocol . th dport vmap {
tcp . 22 : accept,
udp . 53 : accept,
tcp . 53 : accept,
udp . 67 : accept
}
}
chain inbound {
# drop everything by default
type filter hook input priority 0; policy drop;
# accept established and related packets, drop invalid
ct state vmap {
established : accept,
related : accept,
invalid : drop
}
# accept loopback, anything else jump to chain for evaluation
iifname vmap {
lo : accept,
$DEV_WORLD : jump inbound_world,
$DEV_PRIVATE : jump inbound_private
}
}
chain outbound_world {
# accept traffic to local DHCP servers
ip daddr 255.255.255.255 counter accept
# accept traffic to VPN servers
ip daddr $VPN_SERVERS counter accept
}
chain outbound_private {
# accept pings on private interface
icmp type echo-request limit rate 5/second accept
}
chain outbound {
# drop everything by default
type filter hook output priority 0; policy drop;
# accept established and related packets, drop invalid
ct state vmap {
established : accept,
related : accept,
invalid : drop
}
# accept loopback and VPN traffic, anything else jump to chain for evaluation
oifname vmap {
lo : accept,
$DEV_TUNNEL : accept,
$DEV_WORLD : jump outbound_world,
$DEV_PRIVATE : jump outbound_private
}
}
chain forward {
# drop everything by default
type filter hook forward priority 0; policy drop;
# accept traffic from established and related packets, drop invalid
ct state vmap {
established : accept,
related : accept,
invalid : drop
}
# connections from internal to internal or internet are allowed
iifname $DEV_PRIVATE accept
}
chain postrouting {
# accept everything by default
type nat hook postrouting priority 100; policy accept;
# masquerade private network IP addresses (private <-nat-> world)
ip saddr $NET_PRIVATE oifname $DEV_TUNNEL masquerade
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment