Skip to content

Instantly share code, notes, and snippets.

@NiceRath
Last active March 19, 2024 02:55
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save NiceRath/900f115f216c942283584c41baeb209f to your computer and use it in GitHub Desktop.
Save NiceRath/900f115f216c942283584c41baeb209f to your computer and use it in GitHub Desktop.
NFTables TPROXY - proxy input and output
#!/usr/sbin/nft -f
# see also:
# https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks
# https://docs.kernel.org/networking/tproxy.html
# https://powerdns.org/tproxydoc/tproxy.md.html
# http://git.netfilter.org/nftables/commit/?id=2be1d52644cf77bb2634fb504a265da480c5e901
# http://wiki.squid-cache.org/Features/Tproxy4
# https://serverfault.com/questions/1052717/how-to-translate-ip-route-add-local-0-0-0-0-0-dev-lo-table-100-to-systemd-netw
# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/net/netfilter/nft_tproxy.c
# you might need to enable some nftables kernel modules:
# modprobe nft_tproxy
# modprobe nft_socket
# modprobe nf_tproxy_ipv4
# modprobe nf_tproxy_ipv6
# you will also have to configure a loopback route if you want to proxy 'output' traffic:
# echo "200 proxy_loopback" > /etc/iproute2/rt_tables.d/proxy.conf
# these need to be configured persistend (maybe use an interface up-hook)
# ip rule add fwmark 200 table proxy_loopback
# ip -6 rule add fwmark 200 table proxy_loopback
# ip route add local 0.0.0.0/0 dev lo table proxy_loopback
# ip -6 route add local ::/0 dev lo table proxy_loopback
# can be checked using:
# ip rule list
# ip -6 rule list
# ip -d route show table all
# you might need to set a sysctl:
# sysctl -w net.ipv4.conf.all.route_localnet=1
# you might want to block 127.0.0.1 on non loopback interfaces if you enable it:
# see below: 'prerouting_raw' & 'postrouting_mangle'
# modify variables as needed
define MARK_PROXY = 200;
define MARK_DONE = 201;
define EXCLUDES_PROXY_V4 = { 127.0.0.0/8, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12 };
define EXCLUDES_LOOP_V4 = { 255.255.255.255/32 };
define EXCLUDES_PROXY_V6 = { ::1 };
define EXCLUDES_LOOP_V6 = { :: };
define PROXY_PORT = 3129;
define PROXY_UID = 13;
delete table inet proxy
table inet proxy {
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
meta l4proto tcp socket transparent 1 meta mark set $MARK_PROXY comment "Redirect proxy sessions to proxy"
# meta mark $MARK_PROXY log prefix "PRE MARK PROXY"
# meta mark $MARK_DONE log prefix "PRE MARK DONE"
meta l4proto tcp jump proxy_redirect
meta mark $MARK_DONE ct mark set meta mark comment "Store mark in connection"
}
chain proxy_redirect {
ip daddr $EXCLUDES_PROXY_V4 return
ip6 daddr $EXCLUDES_PROXY_V6 return
ip protocol tcp meta mark $MARK_DONE return comment "Exclude proxied traffic - anti-loop"
meta protocol ip meta l4proto tcp tproxy ip to 127.0.0.1:$PROXY_PORT
meta protocol ip6 meta l4proto tcp tproxy ip6 to [::1]:$PROXY_PORT
}
chain output {
type route hook output priority mangle; policy accept;
ct mark $MARK_DONE meta mark set ct mark comment "Load mark from connection"
# meta mark $MARK_PROXY log prefix "OUT MARK PROXY"
# meta mark $MARK_DONE log prefix "OUT MARK DONE"
meta l4proto tcp jump output_loop
meta mark $MARK_DONE meta mark set 0 comment "Remove unnecessary mark"
}
chain output_loop {
ip daddr $EXCLUDES_PROXY_V4 return
ip6 daddr $EXCLUDES_PROXY_V6 return
ip daddr $EXCLUDES_LOOP_V4 return
ip6 daddr $EXCLUDES_LOOP_V6 return
meta skuid $PROXY_UID return comment "Exclude Traffic from proxy itself - anti-loop"
meta l4proto tcp meta mark $MARK_DONE return comment "Exclude proxied traffic - anti-loop"
meta l4proto tcp meta mark set $MARK_PROXY
}
chain prerouting_raw {
type filter hook prerouting priority raw; policy accept;
iifname != "lo" ip daddr 127.0.0.0/8 drop comment "Security fix for 'route_localnet'"
}
chain postrouting_mangle {
type filter hook postrouting priority mangle; policy accept;
oifname != "lo" ip saddr 127.0.0.0/8 drop comment "Security fix for 'route_localnet'"
}
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
}
@NiceRath
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment