为什么透明代理中的 REDIRECT 方式仅支持 TCP,不支持 UDP? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaohusky
V2EX    问与答

为什么透明代理中的 REDIRECT 方式仅支持 TCP,不支持 UDP?

  •  
  •   xiaohusky 2023-12-26 20:18:04 +08:00 4420 次点击
    这是一个创建于 659 天前的主题,其中的信息可能已经有所发展或是发生改变。

    REDIRECT 方式是通过 iptables 规则将流量重定向到代理服务器的本地端口。它是通过修改 IP 层的目标 IP 地址和端口号来实现的。当网络数据包经过 iptables 规则时,它们的目标 IP 地址和端口会被修改为代理服务器的 IP 地址和端口,从而将流量重定向到代理服务器。

    然而,这种修改目标 IP 地址和端口的方式只适用于 TCP 协议,因为 TCP 是面向连接的协议,可以通过修改目标 IP 地址和端口来建立连接。而对于 UDP 协议,它是无连接的,没有建立连接的过程,因此无法通过修改目标 IP 地址和端口来实现透明代理。

    我搜到的答案是这个,但是小弟理解能力比较差,有大佬解释一下吗?或者给一个例子

    6 条回复    2024-08-20 17:36:49 +08:00
    kyor0
        1
    kyor0  
       2023-12-26 20:40:50 +08:00
    tproxy 是支持 udp 的。

    我个人更想知道 tproxy 和 REDIRECT 有啥区别,之前倒腾 passwall 的时候查过,但没啥收获
    ysc3839
        2
    ysc3839  
       2023-12-26 20:47:17 +08:00 via Android
    印象中在哪看过分析,就是因为 Linux 没有实现。好像是因为 TCP 有连接状态,所以 Linux 记下了原始的目标,重定向到代理程序后,程序可以获取到目标。而 UDP 获取不到目标,就不支持。
    xiaohusky
        3
    xiaohusky  
    OP
       2023-12-26 20:58:51 +08:00
    @ysc3839 我又去搜索了一下,好像就是因为这个原因,UDP 没有记录原始的目标,所以修改后就改不回去了,TCP 记录过原始目标,修改后该可以改回去
    tool2d
        4
    tool2d  
       2023-12-26 21:18:53 +08:00
    我一般 UDP 都是写死地址的,linux 可以针对 uid 单独进程做 iptables 规则,只要能确保进程只请求一个 udp 服务器,并且是固定的,那么 REDIRECT 就可以修改 nat ip4 头部信息。

    TCP 转发是 iptables 记录下来源地址的。
    ciaoSora
        5
    ciaoSora  
       2024-05-20 21:03:53 +08:00
    楼上们说的应该是正解,内核不支持,按照我的理解,原因如下:

    TCP 是全双工保证按序交付的传输层协议,所以 Linux 内核支持获取 REDIRECT 之前的 destination 。一个 TCP 连接是以 (Src IP, Src Port, Dst IP, Dst Port) 四元组作为唯一标识的,当真实 destination 发送 TCP 数据包到透明代理时,透明代理知道要把数据返回给 source IP ,因为透明代理内部把 (Src IP, Src Port, Proxy IP, Proxy Port) 和 (Proxy IP, Proxy Client Port, Dst IP, Dst Port) 这两个四元组建立了联系,代理程序清楚地知道,当自己的 Proxy Port 收到来自 source 的数据时,要原封不动地通过第二个 TCP 连接发送给 destination ;当自己的 Proxy Client Port 收到来自 destination 的数据时,要原封不动地通过第一个 TCP 连接发送给 source 。

    UDP 几乎就只是在 IP 的基础上加了 Src Port 和 Dst Port ,什么其他功能都没有(不是双工、不保证交付、不一定按序)。假设采取了跟 TCP 一样的原理,当 Proxy Client Port 收到来自 destination 的数据时,能理所当然地直接用 Proxy Port 发回给 source 吗?举个例子,一个人通过 email 投递简历到某公司的 HR 邮箱里( source 是这个人,destination 是 HR ),HR 读了之后感觉很优秀,认为需要直接让 CEO 跟你对接,于是他把 email 转发给了 CEO ( destination 把数据发给了 thirdparty),CEO 看完了之后,回了你一封邮件( thirdparty 发数据给 source )。假设在 source 前面有一个透明代理,如果他收到的是 HR 的回信那还好,直接理所当然地转回给 source 。但如果是刚刚的情况呢? HR 没有直接回你,而是让 CEO 回复你,这时透明代理就不知道应该转回给谁了。正因如此,内核就直接不支持获取 REDIRECT 之前的 destination 是什么,因为 UDP 本来是一种不需要建立连接的协议,仅从 UDP 这一层的角度(而不从应用层协议的角度)出发,REDIRECT 之前的 IP 是没意义的。当然应用层的协议可能刚好规定,若 source 给 destination 发数据,那么 destination 必然要跟 source 回复,但是无论应用层怎么规定,UDP 这个传输层的协议是不知道的,也不能做任何乐观假设。

    感觉 tproxy 或者其他能代理 UDP 的解决方案,应该就是乐观假设了「 CEO 给你回信」这个场景不会发生?有了这个假设之后,透过其他技术手段(毕竟内核不直接支持)获取到 REDIRECT 之的 destination 之后,就可以用类似 TCP 的方式把来自 destination 的数据回复给 source 了。

    不知道说得对不对,希望大佬能纠正我 =_=
    c521wy
        6
    c521wy  
       2024-08-20 17:36:49 +08:00
    TCP 使用 REDIRECT
    1. 发起 TCP 连接时,透明代理知道这个报文是用来建立连接的,此时会记录 IP 和端口映射关系
    2. 当 TCP 连接关闭时,透明代理此时知道这个报文是用来关闭连接的,此时会将第一步的映射关系删除

    UDP 使用 REDIRECT
    1. 发送 UDP 报文,透明代理不确定是否应该记录 IP 和端口映射关系。因为 UDP 是无连接的,类似于发短信,短信发送过去,对方不一定会回复。因此即便透明代理记录了映射关系,由于没有 TCP 的挥手机制,透明代理也不知道什么时候应该删除该映射关系。

    TPROXY 的机制
    1. 通过策略路由的方式,将报文路由至 loopback ,从而被透明代理获取
    2. 透明代理转发该报文时,TCP 或 UDP 报文的 srcIp 、srcPort 仍然是原客户端的 IP 和端口
    3. 当服务器发回响应时,响应报文是不经过透明代理中转的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2948 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 00:22 PVG 08:22 LAX 17:22 JFK 20:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86