tcp 握手失败。客户端发送 rst(syn-ack 之后)。有人能提供建议吗?

tcp 握手失败。客户端发送 rst(syn-ack 之后)。有人能提供建议吗?

拓扑:2 台 Linux 计算机直接连接。没有 iptables 规则(除 - iptables -A OUTPUT -p tcp -j NFQUEUE 外)没有防火墙。

路由定义为 - “route add default dev eth0”

在第二个(192.168.1.1)上运行 apache 服务器。

我有一个基于 libnetfilter_queue 的小程序,它监听 nfqueue 并在 dst ip 为 192.168.1.2 的情况下将 dst ip 更改为 192.168.1.1(我知道我可以使用 iptables 来做到这一点,但我的程序将来会做更多的事情),修复校验和并返回到队列。

如果我调用 telnet 192.168.1.1 ,则意味着我的程序不需要进行任何操作,握手正常。如果我调用远程登录 192.168.1.2,我的程序改变了目标。服务器获取 syn 并返回 syn-ack,但是在获取 syn-ack 之后客户端立即发送 rst。

有人能提供建议吗?

telnet 的 wireshark

上述 telenet 的 tcpdump

答案1

如果我呼叫 telnet 192.168.1.2,我的程序会更改目标。服务器获取 syn 并返回 syn-ack,但在获取 syn-ack 后,客户端立即发送 rst。

您遇到的问题是您正在打开一个到某个端点(192.168.1.1)的 TCP 套接字,将目标重写为 192.168.1.2,并以某种方式确保将数据包发送回您的 NIC。

当这些数据包到达您的 NIC 时,您在 Linux 内核中没有与 192.168.1.2 对应的打开的 TCP 套接字,因此内核会发送 RST。

仅有的要阻止 RST 造成的损害,您可以做的一件事是插入一条iptables规则,从源 TCP 端口丢弃发往 192.168.1.2 的 TCP RST 数据包。完成后,您需要删除此规则。

答案2

如果您在一个方向上损坏了数据包,则应该检查另一个方向的数据包是否属于这种损坏的连接并将其撤消。

在您的情况下,源为 192.168.1.1 的传入数据包可能属于您破坏的连接,您应该将源设置回 192.168.1.2。

内核发送 RST,因为源地址与它发送 SYN 的地址不匹配(内核对您的地址转换一无所知)。

答案3

客户端忽略 syn-ack 并发送 rst 的原因是因为端口表此端口是在 ip 192.168.1.2(原始 ip)下注册的,所以当 ip 192.168.1.1 使用相同端口发回 syn-ack 时,客户端发送了 RST。

更详细解释:

我在 IPTABLES OUTPUT 上有一条规则,将输出数据包放入 nfqueue 中。显然在这个阶段,客户端已经分配了一个端口并使用原始 ip 注册它,当你更改 ip 时,这个注册不会改变。

我更改了 IP 并使用新的目标 IP 将其返回到 NFQUEUE。

syn 被发送到固定 ip,但是当它返回 syn-ack 时,他的 ip 未在此端口上注册。

所以解决方案是也使用 INPUT 规则,当你从改变后的 IP 返回数据包时将 IP 改回原来的 IP。

感谢大家的帮助。

相关内容