IPTABLES UDP 端口转发疑惑

2021-06-07 21:22:45 +08:00
 caobug

在 centos7 拉取 github 源码编译经常连不上,找了许多资料发现透明代理比较合适。

一番折腾 TCP 终于正常转发,UDP 如果配置 PREROUTING 就没任何转发效果,配置成 OUTPUT 可以转发不过报文不对:

;; reply from unexpected source: 192.168.0.101#1080, expected 119.29.29.29#53

求大佬帮忙

#!/usr/bin/env bash

start() {
    stop

    iptables -t nat -A OUTPUT -p tcp -m mark --mark 0x255 -j ACCEPT
    iptables -t nat -A OUTPUT -p udp -m mark --mark 0x255 -j ACCEPT

    # tcp
    iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 1080

    # udp
    # ip rule add fwmark 0x2333/0x2333 pref 100 table 100
    # ip route add local default dev lo table 100
    # iptables -t mangle -A PREROUTING -p udp --dport 53 -j TPROXY --tproxy-mark 0x2333/0x2333 --on-ip 127.0.0.1 --on-port 1080
    # --dport 53

    # iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to 192.168.6.10

    iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 1080
}

stop() {
    iptables -t nat -F
    iptables -t mangle -F
    iptables -F
    iptables -X
    ip rule delete fwmark 0x2333/0x2333 pref 100 table 100 &>/dev/null
    ip route delete local default dev lo table 100 &>/dev/null
}

if [[ $1 == "start" ]]; then
    start
elif [[ $1 == "stop" ]]; then
    stop
fi
3393 次点击
所在节点    Linux
5 条回复
mikeguan
2021-06-07 22:08:16 +08:00
iptables dnat 转发 udp 好像会丢失转发前的地址和端口

shadowsocks-libev 项目上有提供使用内核的 tproxy 来转发 udp 的方法
iBugOne
2021-06-07 22:49:06 +08:00
把 DNAT 都换成 REDIRECT 吧,至少 REDIRECT 到本机后接收到包的进程可以获取 SO_ORIGINAL_DST 来帮你转发
caobug
2021-06-07 23:23:25 +08:00
谢谢抽空解答 ^_^

@mikeguan ss 提供的 tproxy udp 解决方案似乎只能用于“路由器”或将 Linux 作为路由器使用,不适用于透明代理当前 Linux 对外发包,ss 代码倒没问题,就是防火墙没配对。

@iBugOne REDIRECT 可以成功重定向到本机端口,代理程序也可以收到数据包,但是回复后防火墙似乎没正确转换。
比如我查询:dig www.baidu.com ,会得到以下错误报告:预期收到来自 119.29.29.29:53 的 udp 答复,但收到了 192.168.0.101:1080 的
```
;; reply from unexpected source: 192.168.0.101#1080, expected 119.29.29.29#53
```

```
#!/bin/sh

start() {
stop

iptables -t nat -A OUTPUT -p tcp -m mark --mark 0x255 -j ACCEPT
iptables -t mangle -A OUTPUT -p udp -m mark --mark 0x255 -j ACCEPT

# tcp
iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 1080

# udp
ip rule add fwmark 1 lookup 100
ip route add local default dev lo table 100
iptables -t mangle -A OUTPUT -p udp --dport 53 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -p udp --dport 53 -j TPROXY --on-ip 127.0.0.1 --on-port 1080 --tproxy-mark 0x01/0x01

iptables -t nat -L -nvx
iptables -t mangle -L -nvx
}

stop() {
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X
ip rule delete fwmark 1 lookup 100 &>/dev/null
ip route delete local default dev lo table 100 &>/dev/null
}

if [[ $1 == "start" ]]; then
start
elif [[ $1 == "stop" ]]; then
stop
fi

```
caobug
2021-06-08 07:53:29 +08:00
有些眉目了:

当转发到本地代理程序之后,需要在程序中通过 recvmsg 接受 udp 数据,并传入结构体 msghdr 以填充具体信息。

然后再从 msghdr 中查找原始目的地信息,如 119.29.29.29 。

当要回复 udp 给客户端时,新建 socket 并 bind 到原始目的地( 119.29.29.29 ),然后再 send 给客户端。

据测试 macOS pf udp 转发不需要这样处理,直接 send 给 client 就好了。
zhangsanfeng2012
2021-06-08 08:53:29 +08:00
配置 http_proxy 和 https_proxy 就可以了吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/781982

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX