【问题标题】:TCP handshake with SOCK_RAW socket与 SOCK_RAW 套接字的 TCP 握手
【发布时间】:2017-11-23 19:54:43
【问题描述】:

好的,我意识到这种情况有点不寻常,但我需要仅使用原始套接字(在 C 中,在 linux 中)建立 TCP 连接(3 次握手)——即我需要构建 IP 标头和TCP标头自己。我正在编写一个服务器(所以我必须首先响应传入的 SYN 数据包),无论出于何种原因,我似乎都无法正确处理。是的,我知道 SOCK_STREAM 会为我处理这个问题,但由于我不想进入的原因,这不是一个选项。

我在网上找到的关于使用原始套接字的教程都描述了如何构建 SYN 泛洪器,但这比实际建立 TCP 连接要容易一些,因为您不必根据原始数据包构建响应.我已经让 SYN 泛洪器示例正常工作,并且可以很好地从原始套接字读取传入的 SYN 数据包,但我仍然无法为来自客户端的传入 SYN 创建有效的 SYN/ACK 响应。

那么,有没有人知道一个关于使用原始套接字的好教程,它超越了创建 SYN 泛洪器,或者有没有人有一些代码可以做到这一点(使用 SOCK_RAW,而不是 SOCK_STREAM)?我将不胜感激。


MarkR 是绝对正确的——问题在于内核发送重置数据包以响应初始数据包,因为它认为端口已关闭。内核正在击败我的响应并且连接消失了。我已经在使用 tcpdump 来监视连接了——我应该更加细心,并注意到有两个回复,其中一个是搞砸了的重置,以及我的程序创建的响应。哦!

似乎效果最好的解决方案是使用 MarkR 建议的 iptables 规则来阻止出站数据包。但是,正如建议的那样,有一种比使用标记选项更简单的方法。我只是匹配是否设置了重置 TCP 标志。在正常连接过程中,这不太可能需要,如果我阻止来自正在使用的端口的所有出站重置数据包,这对我的应用程序并不重要。这有效地阻止了内核不需要的响应,但不是我自己的数据包。如果我的程序正在监听的端口是 9999,那么 iptables 规则如下所示:

iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP

【问题讨论】:

    标签: linux network-programming


    【解决方案1】:

    您想在用户空间中实现部分 TCP 堆栈...这没关系,其他一些应用程序会这样做。

    您会遇到的一个问题是内核将向传入的数据包发送(通常是否定的、无用的)回复。这会破坏您尝试发起的任何通信。

    避免这种情况的一种方法是使用内核没有自己的 IP 堆栈使用的 IP 地址和接口——这很好,但您需要自己处理链路层的东西(特别是 arp)。那将需要一个低于 IPPROTO_IP、SOCK_RAW 的套接字——你需要一个数据包套接字(我认为)。

    也可以使用 iptables 规则来阻止内核的响应——但我怀疑这些规则也会以某种方式应用于你自己的数据包,除非你可以设法让它们得到不同的处理(也许应用一个 netfilter “标记”到您自己的数据包?)

    阅读手册页

    插座(7) ip(7) 数据包(7)

    其中解释了适用于套接字类型的各种选项和 ioctl。

    当然,您需要像 Wireshark 这样的工具来检查正在发生的事情。你需要几台机器来测试这个,我建议使用 vmware(或类似的)来减少所需的硬件数量。

    抱歉,我不能推荐具体的教程。

    祝你好运。

    【讨论】:

      【解决方案2】:

      我意识到这是一个旧线程,但这里有一个超越普通 SYN 泛洪器的教程:http://www.enderunix.org/docs/en/rawipspoof/

      希望对某人有所帮助。

      【讨论】:

        【解决方案3】:

        我无法帮助您完成任何教程。

        但我可以就可以用来协助调试的工具给你一些建议。

        首先,正如bmdhacks 所建议的,为自己准备一份wireshark 的副本(或tcpdump - 但wireshark 更易于使用)。捕捉良好的握手。请务必保存。

        捕捉一次失败的握手。 Wireshark 有很好的数据包解析和错误检查,所以如果有一个简单的错误它可能会告诉你。

        接下来,为自己获取一份tcpreplay 的副本。这还应该包括一个名为“tcprewrite”的工具。 tcprewrite 将允许您将之前保存的捕获文件分成两个 - 握手的每一侧一个。 然后,您可以使用 tcpreplay 回放握手的一侧,这样您就可以使用一组一致的数据包。

        然后您(再次)使用 wireshark 来检查您的回复。

        【讨论】:

          【解决方案4】:

          我没有教程,但我最近使用Wireshark 很好地调试了我正在做的一些原始套接字编程。如果您捕获了您发送的数据包,wireshark 会很好地向您显示它们是否格式错误。这对于与普通连接进行比较也很有用。

          【讨论】:

            【解决方案5】:

            在 netinet/ip.h 和 netinet/tcp.h 中分别声明了 IP 和 TCP 头的结构。您可能想查看此目录中的其他标头以获取可能有用的额外宏和内容。

            您发送一个设置了 SYN 标志和一个随机序列号 (x) 的数据包。您应该从另一端收到一个 SYN+ACK。该数据包将具有一个确认号 (y),它指示另一方期望接收的下一个序列号以及另一个序列号 (z)。您发回具有序列号 x+1 和确认号 z+1 的 ACK 数据包以完成连接。

            您还需要确保计算适当的 TCP/IP 校验和并为您发送的数据包填写标头的其余部分。另外,不要忘记主机和网络字节顺序之类的东西。

            TCP 在 RFC 793 中定义,可在此处获取:http://www.faqs.org/rfcs/rfc793.html

            【讨论】:

              【解决方案6】:

              根据您要执行的操作,让现有软件为您处理 TCP 握手可能会更容易。

              一个开源 IP 堆栈是 lwIP (http://savannah.nongnu.org/projects/lwip/),它提供了一个完整的 tcp/ip 堆栈。很可能使用 SOCK_RAW 或 pcap 使其在用户模式下运行。

              【讨论】:

                【解决方案7】:

                如果你使用原始套接字,如果你使用与实际不同的源mac地址发送,linux将忽略响应包而不发送rst。

                【讨论】:

                • 我知道这是 4 年前的问题,但你的建议看起来很有趣,所以我决定请你澄清一下。问题是:在将响应数据包路由到设备 MAC 地址错误的某些机器时,路由器是否有任何问题?现在的防火墙或防病毒软件会过滤数据包吗?
                • 如果交换机配置了端口安全性,则欺骗性 MAC 可能会被交换机过滤。 MAC 层上可能有 ACL,但通常没有什么可以阻止您欺骗 MAC。您只需要确保您的网卡将接受这个欺骗的 mac 的答案(通过将 mac 添加到接受的数据包表中或将其置于 promisc 模式)。如果您没有得到授权,这样做是个坏主意。
                猜你喜欢
                • 2015-02-22
                • 1970-01-01
                • 1970-01-01
                • 2020-09-18
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-11-08
                相关资源
                最近更新 更多