发送带有负载的 TCP SYN 数据包

Send TCP SYN packet with payload

是否可以在发起TCP连接时发送一个带有自定义payload的SYN包?我的直觉是理论上是可行的。我正在寻找一种在 Linux 中实现此目标的简单方法(使用 C 或 Go 语言),但因为它不是标准行为,所以我还没有找到有用的信息。 (This post 非常相似,但不是很有帮助。)

请帮帮我,谢谢!

编辑:很抱歉含糊不清。不仅是这样的任务的可能性,我也在寻找一种方法,甚至是示例代码来实现它。

显然,如果您在两边都编写自己的软件,则可以让它按您想要的方式工作。但是如果你在任何一端都依赖标准软件(例如,标准 linux 或 Windows 内核),那么不,这是不可能的,因为根据 TCP,你不能在建立会话之前发送数据,并且在您从其他对等方收到 确认 到您的 SYN 之前不会建立会话。

因此,例如,如果您向 linux 内核发送一个还包含额外负载的 SYN 数据包(警告:这在某种程度上是推测,因为我还没有实际尝试过),它将简单地忽略有效负载并继续确认 (SYN/ACK) 或拒绝 (使用 RST) SYN,具体取决于是否有侦听器。

在任何情况下,您都可以尝试这个,但是既然您要去 "off the reservation" 可以这么说,您将需要制作自己的原始数据包;您将无法说服当地 OS 为您创建它们。

pythonscapy包可以构造它:

#!/usr/bin/env python2
from scapy.all import *
sport = 3377
dport = 2222
src = "192.168.40.2"
dst = "192.168.40.135"
ether = Ether(type=0x800, dst="00:0c:29:60:57:04", src="00:0c:29:78:b0:ff")
ip = IP(src=src, dst=dst)
SYN = TCP(sport=sport, dport=dport, flags='S', seq=1000)
xsyn = ether / ip / SYN / "Some Data"
packet = xsyn.build()
print(repr(packet))

我之前说过这是不可能的。总的来说,我支持这个评价。

但是对于客户端来说,使用connect()API其实是不行的。使用 TCP Fast Open 时有一个替代连接 API。 Example:

    sfd = socket(AF_INET, SOCK_STREAM, 0);
    
    sendto(sfd, data, data_len, MSG_FASTOPEN, 
                (struct sockaddr *) &server_addr, addr_len);
        // Replaces connect() + send()/write()
    
    // read and write further data on connected socket sfd

    close(sfd);

没有API允许服务器将数据附加到发送给客户端的SYN-ACK。

即便如此,在客户端和服务器上启用 TCP Fast Open 可能会让您获得想要的结果,如果您只是指来自客户端的数据,但它有自己的 issues.

如果您想要与 TCP 相同的可靠性和数据流语义,您将需要一个新的可靠协议,除了 TCP 提供的其余部分(例如拥塞控制和 window缩放。

幸运的是,您不必从头开始实施它。 UDP 协议是一个很好的起点,可以作为新 L4 的 L3。

其他项目也做了类似的事情,所以可以使用它们而不是实现你自己的。考虑 QUIC or UDT。这些协议是在现有的 UDP 协议上实现的,因此避免了部署 TCP Fast Open 所面临的问题。

据我了解(以及 Jeff Bencteux 在另一个答案中的评论中所写),TCP Fast Open 针对 TCP 解决了这个问题。

this LWN article:

Eliminating a round trip

Theoretically, the initial SYN segment could contain data sent by the initiator of the connection: RFC 793, the specification for TCP, does permit data to be included in a SYN segment. However, TCP is prohibited from delivering that data to the application until the three-way handshake completes.

...

The aim of TFO is to eliminate one round trip time from a TCP conversation by allowing data to be included as part of the SYN segment that initiates the connection.

TCP 快速开放做到这一点。但是两端都要讲TCP快开。 QUIC 一个基于 AKA 0-RTT 的新协议来解决这个问题。