[关闭]
@Otokaze 2018-10-06T09:43:48.000000Z 字数 1250 阅读 399

编程语言学习计划

笔记

深入学习的几个语言

关于透明代理

Linux 中有两种透明代理方式(只讨论 TCP 和 UDP):REDIRECTTPROXY

REDIRECT 方式注定只能透明代理 TCP,因为 UDP 在经过 DNAT 之后,无法使用 SO_ORIGINAL_DST 套接字选项来获取原始的目的地址和目的端口。目前的解决办法是,通过 TPROXY 来代理 UDP,使用此方法代理 UDP 时,需要先为监听套接字设置 IP_RECVORIGDSTADDR 选项,然后在收到 UDP 包之后(使用 recvmsg() 而不是 recvfrom()),获取原始目的地址信息,进行透明代理。

解释一下 IP_TRANSPARENT 选项的作用,它的作用有两个:

  1. 可以让套接字进行透明代理
  2. 可以让套接字绑定非本地地址

所以要使用 TPROXY 进行透明代理,IP_TRANSPARENT 套接字选项是必不可少的。

REDIRECT TCP 透明代理思路

  1. 首先,像往常一样,监听一个 TCP 端口(如 60080),然后等待新连接的到来。
  2. 设置 iptables REDIRECT 规则,将需要代理的 TCP 流量重定向至该监听端口。
  3. 新连接到来之后,使用 SO_ORIGINAL_DST socket 选项获取原始目的地址信息。
  4. 新建 TCP 套接字,地址为刚才的真实目的地址,发起 TCP 连接,然后转发数据。

TPROXY TCP 透明代理思路

  1. 首先,创建监听套接字,设置 IP_TRANSPARENT 选项,然后再绑定要监听地址。
  2. 设置 iptables TPROXY 规则,将需要代理的 TCP 流量路由到本地的监听端口。
  3. 新连接到来之后,通过 getsockname() 获取目的地址(即 self-side 地址)。
  4. 新建 TCP 套接字,目的地址为刚才获取的目的地址,发起 TCP 连接,转发数据。

TPROXY UDP 透明代理思路

  1. 创建套接字,设置 IP_TRANSPARENTIP_RECVORIGDSTADDR 选项,绑定要监听地址。
  2. 设置 iptables TPROXY 规则,将需要代理的 UDP 流量重定向或路由到本地监听端口。
  3. 使用 recvmsg() 接收 UDP 包,获取原始地址信息,然后发送该 UDP 数据给目的主机。
  4. 收到响应包后创建新套接字并设置 IP_TRANSPARENT 选项,bind 原始地址再发给客户端。

但是,如果按照上面的 TPROXY UDP 实现思路,那么它将只能用于透明代理 request-response 类型的 UDP 上层协议,如 DNS,但是类似 QUIC 这样的非 request-response 类型的 UDP 上层协议会出现问题,因为端口号变了,导致它们依靠端口号来识别用户的策略失效,即 QUIC 协议无法正常工作。

解决方法:在代理程序内部维护一个 hash table,手动维护一个状态信息,防止端口变化。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注