#!/usr/sbin/nft -f flush ruleset define vpn_port=6174 define vpn_if=tun0 define outside_if=enp0s17 define vpn_subnet=10.10.10.0/24 define vpn_port_tor=6175 define vpn_if_tor=tun1 define vpn_subnet_tor=10.10.20.0/24 table inet filter { chain input { # allow OpenVPN connections to the Server udp dport $vpn_port accept # allow OpenVPN TOR connections to the Server udp dport $vpn_port_tor accept } chain forward { #Drop forwarded packets if they are not matched type filter hook forward priority 0; policy drop; # allow existing connections ct state related,established accept # allow packets from vpn interface iifname $vpn_if oifname $outside_if accept # allow packets from vpn interface iifname $vpn_if_tor oifname $outside_if accept } chain output { ## Transproxy leak blocked: # https://trac.torproject.org/projects/tor/wiki/doc/TransparentProxy#WARNING ct state invalid counter drop oifname != "lo" ip saddr != 127.0.0.1 ip daddr != 127.0.0.1 tcp flags & (fin|ack) == fin|ack counter drop oifname != "lo" ip saddr != 127.0.0.1 ip daddr != 127.0.0.1 tcp flags & (rst|ack) == rst|ack counter drop } } # create a ipv4 table only for NAT entries (you need both chains even if they're empty) table ip nat { chain postrouting { type nat hook postrouting priority 100; # enable NAT for VPN iifname $vpn_if oifname $outside_if ip saddr $vpn_subnet masquerade # enable NAT for TOR VPN iifname $vpn_if_tor oifname $outside_if ip saddr $vpn_subnet_tor masquerade } chain prerouting { # Transparent proxy to TOR type nat hook prerouting priority 0; iifname $vpn_if_tor ip saddr $vpn_subnet_tor udp dport 53 counter dnat to 10.10.20.1:53530 iifname $vpn_if_tor ip protocol tcp ip saddr $vpn_subnet_tor counter dnat to 10.10.20.1:9040 iifname $vpn_if_tor ip protocol udp ip saddr $vpn_subnet_tor counter dnat to 10.10.20.1:9040 } }