V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xiaohusky
V2EX  ›  问与答

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

  •  
  •   xiaohusky · 330 天前 · 2536 次点击
    这是一个创建于 330 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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  
       330 天前
    tproxy 是支持 udp 的。

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

    TCP 转发是 iptables 记录下来源地址的。
    ciaoSora
        5
    ciaoSora  
       184 天前
    楼上们说的应该是正解,内核不支持,按照我的理解,原因如下:

    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  
       92 天前
    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   ·   实用小工具   ·   1192 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 18:24 · PVG 02:24 · LAX 10:24 · JFK 13:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.