V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
caobug
V2EX  ›  Linux

IPTABLES UDP 端口转发疑惑

  •  
  •   caobug · 2021-06-07 21:22:45 +08:00 · 3554 次点击
    这是一个创建于 1257 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 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
    
    5 条回复    2021-06-08 08:53:29 +08:00
    mikeguan
        1
    mikeguan  
       2021-06-07 22:08:16 +08:00 via Android
    iptables dnat 转发 udp 好像会丢失转发前的地址和端口

    shadowsocks-libev 项目上有提供使用内核的 tproxy 来转发 udp 的方法
    iBugOne
        2
    iBugOne  
       2021-06-07 22:49:06 +08:00
    把 DNAT 都换成 REDIRECT 吧,至少 REDIRECT 到本机后接收到包的进程可以获取 SO_ORIGINAL_DST 来帮你转发
    caobug
        3
    caobug  
    OP
       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
        4
    caobug  
    OP
       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
        5
    zhangsanfeng2012  
       2021-06-08 08:53:29 +08:00
    配置 http_proxy 和 https_proxy 就可以了吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2687 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 11:39 · PVG 19:39 · LAX 03:39 · JFK 06:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.