与 SOCK_RAW 套接字的 TCP 握手 [英] TCP handshake with SOCK_RAW socket

查看:13
本文介绍了与 SOCK_RAW 套接字的 TCP 握手的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Ok, I realize this situation is somewhat unusual, but I need to establish a TCP connection (the 3-way handshake) using only raw sockets (in C, in linux) -- i.e. I need to construct the IP headers and TCP headers myself. I'm writing a server (so I have to first respond to the incoming SYN packet), and for whatever reason I can't seem to get it right. Yes, I realize that a SOCK_STREAM will handle this for me, but for reasons I don't want to go into that isn't an option.

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

The tutorials I've found online on using raw sockets all describe how to build a SYN flooder, but this is somewhat easier than actually establishing a TCP connection, since you don't have to construct a response based on the original packet. I've gotten the SYN flooder examples working, and I can read the incoming SYN packet just fine from the raw socket, but I'm still having trouble creating a valid SYN/ACK response to an incoming SYN from the client.

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

So, does anyone know a good tutorial on using raw sockets that goes beyond creating a SYN flooder, or does anyone have some code that could do this (using SOCK_RAW, and not SOCK_STREAM)? I would be very grateful.

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

MarkR is absolutely right -- the problem is that the kernel is sending reset packets in response to the initial packet because it thinks the port is closed. The kernel is beating me to the response and the connection dies. I was using tcpdump to monitor the connection already -- I should have been more observant and noticed that there were TWO replies one of which was a reset that was screwing things up, as well as the response my program created. D'OH!

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

The solution that seems to work best is to use an iptables rule, as suggested by MarkR, to block the outbound packets. However, there's an easier way to do it than using the mark option, as suggested. I just match whether the reset TCP flag is set. During the course of a normal connection this is unlikely to be needed, and it doesn't really matter to my application if I block all outbound reset packets from the port being used. This effectively blocks the kernel's unwanted response, but not my own packets. If the port my program is listening on is 9999 then the iptables rule looks like this:

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

推荐答案

你想在用户空间实现 TCP 栈的一部分……这没关系,其他一些应用程序这样做.

You want to implement part of a TCP stack in userspace... this is ok, some other apps do this.

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

One problem you will come across is that the kernel will be sending out (generally negative, unhelpful) replies to incoming packets. This is going to screw up any communication you attempt to initiate.

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

One way to avoid this is to use an IP address and interface that the kernel does not have its own IP stack using- which is fine but you will need to deal with link-layer stuff (specifically, arp) yourself. That would require a socket lower than IPPROTO_IP, SOCK_RAW - you need a packet socket (I think).

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

It may also be possible to block the kernel's responses using an iptables rule- but I rather suspect that the rules will apply to your own packets as well somehow, unless you can manage to get them treated differently (perhaps applying a netfilter "mark" to your own packets?)

阅读手册页

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

socket(7) ip(7) packet(7)

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

Which explain about various options and ioctls which apply to types of sockets.

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

Of course you'll need a tool like Wireshark to inspect what's going on. You will need several machines to test this, I recommend using vmware (or similar) to reduce the amount of hardware required.

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

Sorry I can't recommend a specific tutorial.

祝你好运.

这篇关于与 SOCK_RAW 套接字的 TCP 握手的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆