gsnova icon indicating copy to clipboard operation
gsnova copied to clipboard

关于透明代理的UDP部分

Open kuyagic opened this issue 7 years ago • 16 comments

我在 配置文件的 Proxy 节点里 设置了 Transparent 为true 端口假设为 6060 然后启动后 通过 netstat -ntplu 查看 并没有看到 程序在UDP 监听6060 端口

请问 iptables 这个转发要怎么写 理解中 是用 TPROXY 来实现的udp转发 但是需要程序监听对应的UDP端口

谢谢.

kuyagic avatar Oct 10 '17 09:10 kuyagic

需要用最新的代码编译,预编译的包目前不包含这个

yinqiwen avatar Oct 10 '17 09:10 yinqiwen

使用最新代码编译了客户端和服务器端 监听有UDP的端口了 但是 NAT测试工具测试下来是 UDPBlocked 下面是 客户端启动后部分日志

2017/10/10 19:55:55 proxy.go:394: Started GSnova r12.
2017/10/10 19:55:55 local_server.go:257: Listen on address :6060
2017/10/10 19:55:55 local_server.go:257: Listen on address :1889
2017/10/10 19:55:55 transparent_unix.go:126: Listen transparent UDP proxy on 0.0.0.0:6060
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:api.twitter.com:443 for IP:104.244.42.130:443
2017/10/10 19:55:55 dns.go:143: DNS query api.twitter.com to 208.67.222.222:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:api.twitter.com:443 for IP:104.244.42.130:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:api.twitter.com:443 for IP:104.244.42.130:443
2017/10/10 19:55:55 dns.go:143: DNS query api.twitter.com to 208.67.220.220:443
2017/10/10 19:55:55 dns.go:143: DNS query api.twitter.com to 208.67.220.220:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:api.twitter.com:443 for IP:104.244.42.194:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:api.twitter.com:443 for IP:104.244.42.130:443
2017/10/10 19:55:55 dns.go:143: DNS query api.twitter.com to 208.67.220.220:443
2017/10/10 19:55:55 dns.go:143: DNS query api.twitter.com to 208.67.222.222:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:twitter.com:443 for IP:104.244.42.1:443
2017/10/10 19:55:55 dns.go:143: DNS query twitter.com to 208.67.220.220:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:tweetdeck.twitter.com:443 for IP:104.244.42.196:443
2017/10/10 19:55:55 dns.go:143: DNS query tweetdeck.twitter.com to 208.67.222.222:443
2017/10/10 19:55:55 local_server.go:95: Sniffed SNI:hlslive-l3c.med1.m.lv.twimg.com:443 for IP:8.253.44.249:443
2017/10/10 19:55:55 config.go:235: ip:104.244.42.66 is CNIP:false
2017/10/10 19:55:55 config.go:235: ip:104.244.42.2 is CNIP:false
2017/10/10 19:55:55 local_server.go:190: Proxy stream[3] select vps-us for proxy to api.twitter.com:443
2017/10/10 19:55:55 dns.go:143: DNS query hlslive-l3c.med1.m.lv.twimg.com to 208.67.220.220:443
2017/10/10 19:55:55 local_server.go:190: Proxy stream[5] select vps-us for proxy to api.twitter.com:443
2017/10/10 19:55:55 config.go:235: ip:104.244.42.1 is CNIP:false
2017/10/10 19:55:55 config.go:235: ip:104.244.42.2 is CNIP:false
2017/10/10 19:55:55 local_server.go:190: Proxy stream[7] select vps-us for proxy to api.twitter.com:443
2017/10/10 19:55:55 config.go:235: ip:104.244.42.66 is CNIP:false

然后下面两行重复无数遍后 NAT测试工具报错

2017/10/10 19:56:01 transparent_unix.go:159: Select vps-us to proxy udp packet to 217.10.68.152:3478
2017/10/10 19:56:01 config.go:235: ip:217.10.68.152 is CNIP:false

相同防火墙TPROXY 环境下 使用 ssr-redir 下 NAT测试工具反馈正常

kuyagic avatar Oct 10 '17 11:10 kuyagic

iptables是怎么设置的?

yinqiwen avatar Oct 11 '17 07:10 yinqiwen

iptables 部分

:ssr-libev - [0:0]
-A PREROUTING -p udp -j ssr-libev
-A ssr-libev -s 192.168.11.10/32 -j RETURN
-A ssr-libev -m set --match-set local dst -j RETURN
-A ssr-libev -m set --match-set vps dst -j RETURN
-A ssr-libev -m set --match-set exclude dst -j RETURN
-A ssr-libev -m set --match-set chinaip dst -j RETURN
-A ssr-libev -p udp -m udp -j TPROXY --on-port 6060 --on-ip 0.0.0.0 --tproxy-mark 0x1/0x1
COMMIT

:ssr-libev - [0:0]
-A PREROUTING -p tcp -j ssr-libev
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 10.18.0.0/24 -o eth0 -j MASQUERADE
-A POSTROUTING -s 192.168.11.0/24 -o eth0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8082 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8000 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -d 127.0.0.1/32 ! -i docker0 -p tcp -m tcp --dport 8082 -j DNAT --to-destination 172.17.0.2:8082
-A DOCKER -d 127.0.0.1/32 ! -i docker0 -p tcp -m tcp --dport 8000 -j DNAT --to-destination 172.17.0.2:8000
-A ssr-libev -s 192.168.11.10/32 -j RETURN
-A ssr-libev -m set --match-set telegram dst -j RETURN
-A ssr-libev -m set --match-set local dst -j RETURN
-A ssr-libev -m set --match-set vps dst -j RETURN
-A ssr-libev -m set --match-set chinaip dst -j RETURN
-A ssr-libev -p tcp -j REDIRECT --to-ports 6060
-A ssr-libev -p icmp -j REDIRECT --to-ports 6060
COMMIT

ip route 部分(启动透明代理脚本添加iptables和ip route部分)

ip rule add fwmark 0x01/0x01 table 100
        ip route add local 0.0.0.0/0 dev lo table 100
        iptables -t mangle -I PREROUTING -p udp -j ssr-libev
        iptables -t nat -I PREROUTING -p tcp -j ssr-libev

上面 iptables 部分是 预先配置好的 设置. 然后 执行 下面部分的命令后 相当于 在 nat 和 mangle 表Insert了 走 ssr-libev 链的规则 启用了透明代理. 默认透明代理监听6060端口

另外我发现 gsnova 服务器端 最新编译版本 并没有对 udp端口进行监听 但是 ssr 的 server是有监听的.是不是和这个有关 导致 udp 不能被发送?

kuyagic avatar Oct 11 '17 07:10 kuyagic

目前的udp transparent实现可能有些问题,只适用于Request-Response类型的协议,例如dns,其它模式应该不适用 有无测试过dns是否可行?

yinqiwen avatar Oct 11 '17 07:10 yinqiwen

测试过 在如上我发的 iptables 规则下 nslookup www.twitter.com 8.8.8.8 结果显示服务器超时. gsnova服务器端显示和我issue 里的日志相同.

我使用的测试 udp的工具是一个叫 NAT类型测试的 windows 工具

kuyagic avatar Oct 11 '17 07:10 kuyagic

如果是PC上记得好像是要在output上而不是mangle里。路由器需要在mangle上设置

yinqiwen avatar Oct 11 '17 07:10 yinqiwen

我这台 192.168.11.10 是做nat 设备存在的.所以配置上 是正确的. 只要目标IP不是国内都会经过这台机器的 转发 也就会走NAT和mangle表了.

kuyagic avatar Oct 11 '17 08:10 kuyagic

稍微修改了下代码,目前可以支持类似stream传输方式的 udp协议了。

在我的路由器上udp规则只有:

ip route add local default dev lo table 100
ip rule add fwmark 1 lookup 100
iptables -t mangle -F GSNOVA
iptables -t mangle -A GSNOVA -p udp --dport 53 -s 192.168.1.75 -j TPROXY --on-port 48101 --tproxy-mark 0x01/0x01
iptables -t mangle -A PREROUTING -j GSNOVA

PC上执行:

dig www.youtube.com @8.8.4.4

最新的代码编译后路由器上日志:

2017/10/11 09:06:50 transparent_unix.go:101: Select qcloud-tcp to proxy udp packet to 8.8.4.4:53
2017/10/11 09:06:50 transparent_unix.go:84: Close transparent udp session:192.168.1.75:54663-8.8.4.4:53

yinqiwen avatar Oct 11 '17 09:10 yinqiwen

是否需要更新 服务器端和客户端?还是只需要更新客户端? 我今晚测试, 然后会反馈

kuyagic avatar Oct 11 '17 09:10 kuyagic

只改了client的一个文件

yinqiwen avatar Oct 11 '17 09:10 yinqiwen

DNS 测试查询 成功 NAT测试失败了 pystun执行结果如下

root@bpi-iot-ros-ai:~# pystun
NAT Type: Blocked
External IP: None
External Port: None

客户端日志如下

2017/10/11 17:40:45 local_server.go:190: Proxy stream[5] select vps-us for proxy to pypi.python.org:443
2017/10/11 17:40:50 config.go:235: ip:217.10.68.152 is CNIP:false
2017/10/11 17:40:50 transparent_unix.go:101: Select vps-us to proxy udp packet to 217.10.68.152:3478
2017/10/11 17:41:05 config.go:235: ip:5.103.128.88 is CNIP:false
2017/10/11 17:41:05 transparent_unix.go:101: Select vps-us to proxy udp packet to 5.103.128.88:123
2017/10/11 17:41:06 config.go:235: ip:77.72.169.213 is CNIP:false
2017/10/11 17:41:06 transparent_unix.go:101: Select vps-us to proxy udp packet to 77.72.169.213:3478
2017/10/11 17:41:08 config.go:235: ip:77.72.169.212 is CNIP:false
2017/10/11 17:41:08 transparent_unix.go:101: Select vps-us to proxy udp packet to 77.72.169.212:3478
2017/10/11 17:41:12 config.go:235: ip:77.72.169.210 is CNIP:false
2017/10/11 17:41:12 transparent_unix.go:101: Select vps-us to proxy udp packet to 77.72.169.210:3478
2017/10/11 17:41:19 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-217.10.68.152:3478
2017/10/11 17:41:20 transparent_unix.go:84: Close transparent udp session:192.168.11.1:123-5.103.128.88:123
2017/10/11 17:41:29 config.go:235: ip:77.72.169.211 is CNIP:false
2017/10/11 17:41:29 transparent_unix.go:101: Select vps-us to proxy udp packet to 77.72.169.211:3478
2017/10/11 17:41:31 config.go:235: ip:216.93.246.18 is CNIP:false
2017/10/11 17:41:31 transparent_unix.go:101: Select vps-us to proxy udp packet to 216.93.246.18:3478
2017/10/11 17:41:36 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-77.72.169.213:3478
2017/10/11 17:41:38 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-77.72.169.212:3478
2017/10/11 17:41:40 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-77.72.169.210:3478
2017/10/11 17:41:44 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-77.72.169.211:3478
2017/10/11 17:41:52 transparent_unix.go:84: Close transparent udp session:192.168.11.1:54320-216.93.246.18:3478

你可以在PC上使用 pip install pystun 后 然后执行 pystun测试下.

另外 ssr-redir 使用下 结果

root@bpi-iot-ros-ai:~# pystun
NAT Type: Symmetric NAT
External IP: proxy ip
External Port: 37121

kuyagic avatar Oct 11 '17 09:10 kuyagic

结果

NAT Type: Symmetric NAT
External IP: 119.28.76.185
External Port: 56557

yinqiwen avatar Oct 11 '17 09:10 yinqiwen

这我就不理解了.... 服务器端不需要更新么?我没有更新服务器端 回头晚点我去windows上测试下...看看是不是我2层路由跳转的问题.. 感谢

kuyagic avatar Oct 11 '17 09:10 kuyagic

pystun指定了特殊服务器地址?

yinqiwen avatar Oct 11 '17 10:10 yinqiwen

不是 我家路由环境比较复杂. 出口路由这里做了判断 如果是国外IP 会回到局域网的 192.168.11.10 这个ip 也就是 gsnova客户端所在的Linux 下走一次 NAT ,不知道是不是这个原因但是 ssr-redir 是好的

pystun 我看了下 和我windows下的那个测试工具用的同一个 测试地址 stun.ekiga.net3478 端口

kuyagic avatar Oct 11 '17 14:10 kuyagic