以前常用 iptables 的 redirect 动作做端口转发,那个时候我的理解就是对 IP 包的目标端口做了修改然后转发;最近看了一些透明代理的实现,发现规则里也用到了 iptables 的 redirect 动作来转到某些代理协议的服务端口(比如:dokodemo door )。
如果按照以前的理解 redirect 动作修改了目标端口,那么代理程序的出口如何知道这个 IP 包要转发到的原始端口?如果 redirect 动作仅仅是把匹配的数据包转发 到指定端口什么都不修改,那么 IP 报文的目标端口都和实际服务的端口不一样,这个数据包怎么被服务收到? 官方文档我看过,没有看到详细过程的说明。
1
billlee 2023-07-03 12:35:52 +08:00 via Android
内核会记住原来的目标地址,getsockopt 有个参数可以获取。
|
2
bao3 2023-07-03 13:22:01 +08:00
内核帮你划分了一个用来做 mapping 的区域,所以叫透明代理,对你的应用是透明的。
|
3
RobberPhex 2023-07-03 13:30:47 +08:00
tproxy 部分:
1. 先用 setsockopt 函数为套接字设置 IP_TRANSPARENT 标识 2. accept 后,对 socket 进行 getsockopt(SO_ORIGINAL_DST)操作,获取原始的 ip 端口 3. 但 udp 没有 socket 对象,所以如下: 4. 通过 setsockopt(fd, SOL_IP, IP_RECVORIGDSTADDR, ...)给 socket 设置 IP_RECVORIGDST 5. 用 recvmsg 函数替代 recvfrom/recv 来接收数据包,返回的结果里有 msghdr 结构体,并遍历(cmsghdr*)msg_control ,找到 level 为 SOL_IP 的结构体,它就包含了 sockaddr_in 原始 IP 和端口。 其中 1 、2 是 redirect ,其他事 tproxy 扩展的。 另外,配置的时候要额外注意下 iptables 的配置,防止出现网络问题。比如我有一次就是 drop 了 tcp 握手中的 ack+syn 包,google 封禁了 IP (直接无法搜索)。https://github.com/robberphex/luci-app-v2ray/blob/v2.2.4/root/etc/init.d/luci_v2ray#L583 |
4
ac169 OP |
5
hankai17 2023-07-03 19:07:10 +08:00
透明代理
一般情况下本机监听的就是 realServer 的 ip 跟端口 不存在修改 |
6
hankai17 2023-07-03 19:13:58 +08:00
@RobberPhex 咨询一下 1 、2 对应的代码在哪个文件里?
|
7
mikewang 2023-07-03 20:57:58 +08:00 via iPhone 1
参考 https://www.netfilter.org/documentation/HOWTO/NAT-HOWTO-6.html#ss6.2
There is a specialized case of Destination NAT called redirection: it is a simple convenience which is exactly equivalent to doing DNAT to the address of the incoming interface. |
8
alexapollo 2023-07-04 00:27:39 +08:00
我印象里十年前这个模块叫做 conntrack ?
|
9
julyclyde 2023-07-04 11:33:50 +08:00
@alexapollo 和 conntrack 根本两码事
|
10
alexapollo 2023-07-04 11:35:08 +08:00
@julyclyde 楼上的 DNAT 让我触发了回忆,那时候 DNAT 不是默认 conntrack 吗
|
11
julyclyde 2023-07-04 11:36:29 +08:00
@alexapollo “带有”conntrack ,和“是”conntrack 两码事
|
12
alexapollo 2023-07-04 11:41:51 +08:00
@julyclyde Sounds reasonable
|