为什么udp不能用Redirect
redirect的原理
在nat表修改数据包的目标地址,同时netfilter有 SO_ORIGINAL_DST 选项可以支持拿到原目的地址,netfilter 会将包的原目的地址放在 socket 的 SO_ORIGINAL_DST 属性里.代理客户端依次向原目标发起请求.
为什么udp不能拿到修改前的地址
udp是一种无连接协议,所以没有socket来拿到修改前的地址,改了就改了.
udp怎样实现代理
tproxy是在不修改数据包的前提上,将数据包转发到本地socket,但是这样不够,因为没有改数据包的目标地址,数据包就直接走forword了,所以需要增加一个路由表把所有数据转入本地:
ip route add local 0.0.0.0/0 dev lo table 100
然后增加一个rule,将特定的数据包转入这个路由表:
ip rule add fwmark 1 table 100
最后,该需要走代理的数据包加上这个标记,就可以:
iptables -t mangle -A CLASH_UDP -p udp -j TPROXY --on-port ${tproxy_port} --tproxy-mark 1
如果想代理本机udp,就给本地output增加mark 1:
iptables -t mangle -I OUTPUT -p udp --dport 53 -j MARK --set-mark 1
这样niptables会把本机数据重新路由到prerouting,可以代理本机.
配置规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| #!/bin/bash
set -e
set -x
lan_ipaddr="192.168.1.5" dns_port="5354" redir_port="7892" tproxy_port="7893"
clearAllRules() { iptables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | iptables-restore } setProxy() { iptables -t nat -N CLASH_DNS iptables -t nat -F CLASH_DNS iptables -t nat -A CLASH_DNS -p udp -j REDIRECT --to-ports ${dns_port} iptables -t nat -A PREROUTING -p udp --dport 53 -j CLASH_DNS
iptables -t nat -N CLASH_TCP iptables -t nat -F CLASH_TCP iptables -t nat -A CLASH_TCP -d 0.0.0.0/8 -j RETURN iptables -t nat -A CLASH_TCP -d 10.0.0.0/8 -j RETURN iptables -t nat -A CLASH_TCP -d 127.0.0.0/8 -j RETURN iptables -t nat -A CLASH_TCP -d 169.254.0.0/16 -j RETURN iptables -t nat -A CLASH_TCP -d 172.16.0.0/12 -j RETURN iptables -t nat -A CLASH_TCP -d 192.168.0.0/16 -j RETURN iptables -t nat -A CLASH_TCP -d 224.0.0.0/4 -j RETURN iptables -t nat -A CLASH_TCP -d 240.0.0.0/4 -j RETURN iptables -t nat -A CLASH_TCP -p tcp -j REDIRECT --to-ports ${redir_port} iptables -t nat -A PREROUTING -p tcp -j CLASH_TCP
iptables -t mangle -N CLASH_UDP iptables -t mangle -F CLASH_UDP iptables -t mangle -A CLASH_UDP -d 0.0.0.0/8 -j RETURN iptables -t mangle -A CLASH_UDP -d 10.0.0.0/8 -j RETURN iptables -t mangle -A CLASH_UDP -d 127.0.0.0/8 -j RETURN iptables -t mangle -A CLASH_UDP -d 169.254.0.0/16 -j RETURN iptables -t mangle -A CLASH_UDP -d 172.16.0.0/12 -j RETURN iptables -t mangle -A CLASH_UDP -d 192.168.0.0/16 -j RETURN iptables -t mangle -A CLASH_UDP -d 224.0.0.0/4 -j RETURN iptables -t mangle -A CLASH_UDP -d 240.0.0.0/4 -j RETURN iptables -t mangle -A CLASH_UDP -p udp --dport 53 -j RETURN iptables -t mangle -A CLASH_UDP -p udp -j TPROXY --on-port ${tproxy_port} --tproxy-mark 1 iptables -t mangle -A PREROUTING -p udp -j CLASH_UDP }
case "$1" in clear) clearAllRules echo "delete rules successfully" ;; set) clearAllRules setProxy echo "set rules successfully" ;; *) echo "usage: $0 clear|set" exit 0 ;; esac exit
|
参考
透明代理入门 | Project X
透明代理 UDP 为什么要用 TProxy?
Clash旁路网关设置
透明代理(TPROXY)