9

Is it possible to send a SYN packet with self-defined payload when initiating TCP connections? My gut feeling is that it is doable theoretically. I'm looking for a easy way to achieve this goal in Linux (with C or perhaps Go language) but because it is not a standard behavior, I didn't find helpful information yet. (This post is quite similar while it is not very helpful.)

Please help me, thanks!

EDIT: Sorry for the ambiguity. Not only the possibility for such task, I'm also looking for a way, or even sample codes to achieve it.

4
  • 1
    The duplicate you mention says it isn't possible. You may not consider that 'very helpful', but it is. Commented Jun 23, 2016 at 23:24
  • @EJP I'm confused for that post because the another answer says "sending data in SYN packet is possible". I guess the problem is that scaling window is not established yet. So do you know whether TCP sliding window takes care of the handshake packets (SYN, SYNACK and ACK) as well? Or does it only care about the actual data packets? Commented Jun 24, 2016 at 19:53
  • 1
    It is possible if you write your own TCP protocol: not otherwise. You can send such a packet in isolation, via a raw socket, but you can't conduct an entire TCP session that way, because the kernel will stop you. The TCP sliding window is concerned with data, and SYN and ACK are not data by themselves (although ACK can be piggybacked on data). Commented Jun 25, 2016 at 1:37
  • @EJP OK I got it. Thank you so much! Commented Jun 25, 2016 at 13:00

4 Answers 4

7

As far as I understand (and as written in a comment by Jeff Bencteux in another answer), TCP Fast Open addresses this for TCP.

See 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.

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Note that your example is only valid if TCP cookies are used. Without any TCP cookies, the server is not allowed to send packets until it received an ACK from the client, as it would mean it a spoofed initial TCP packet could use the server as an amplifying attack
6

Obviously if you write your own software on both sides, it is possible to make it work however you want. But if you are relying on standard software on either end (such as, for example, a standard linux or Windows kernel), then no, it isn't possible, because according to TCP, you cannot send data until the session is established, and the session isn't established until you get an acknowledgment to your SYN from the other peer.

So, for example, if you send a SYN packet that also includes additional payload to a linux kernel (caveat: this is speculation to some extent since I haven't actually tried it), it will simply ignore the payload and proceed to acknowledge (SYN/ACK) or reject (with RST) the SYN depending on whether there's a listener.

In any case, you could try this, but since you're going "off the reservation" so to speak, you would need to craft your own raw packets; you won't be able to convince your local OS to create them for you.

The python scapy package could construct it:

#!/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))

9 Comments

Thanks! I understand it's not a part of protocol and I cannot rely on the standard stuffs. I also think it is theoretically doable. But my question is actually "how?" (Sorry for the ambiguity here. I'll edit the question to make it more clear.) According to your suggestion, the question might be "how to craft a SYN packet with payload from a raw packet?" Any suggestions/sample codes for this?
If it were me, I would use the python scapy package. Sample added to my answer.
Just a guess without having read the specs on this: won't any decent router (and especially a NAT/PAT'ing one) simply drop the packet and reset the connection upon reading such a "malformed" packet?
"(such as, for example, a standard linux or Windows kernel), then no, it isn't possible" You could use TCP Fast Open option to achieve it, this is experimental but Linux does implement it (see proc/sys/net/ipv4/tcp_fastopen for configuration). It is not optimal though as you need a first connection before being able to use it.
@zzy You misunderstood TFO I think :). The cookie is 4 to 16 bytes long. But when you send the cookie via the option, you also send data in SYN's payload. That's the goal. However, you need to ask the other endpoint a cookie first, so you can only do it after a first connection has been made.
|
1

TCP Fast open do that. But both ends should speak TCP fast open. QUIC a new protocol is based to solve this problem AKA 0-RTT.

Comments

1

I had previously stated it was not possible. In the general sense, I stand by that assessment.

However, for the client, it is actually just not possible using the connect() API. There is an alternative connect API when using TCP Fast Open. 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);

There is no API to allow the server to attach data to the SYN-ACK sent to the client.

Even so, enabling TCP Fast Open on both the client and server may allow you to achieve your desired result, if you only mean data from the client, but it has its own issues.

If you want the same reliability and data stream semantics of TCP, you will need a new reliable protocol that has the initial data segment in addition to the rest of what TCP provides, such as congestion control and window scaling.

Luckily, you don't have to implement it from scratch. The UDP protocol is a good starting point, and can serve as your L3 for your new L4.

Other projects have done similar things, so it may be possible to use those instead of implementing your own. Consider QUIC or UDT. These protocols were implemented over the existing UDP protocol, and thus avoid the issues faced with deploying TCP Fast Open.

4 Comments

May I ask whether TCP sliding window takes care of the handshake packets (SYN, SYNACK and ACK) as well? I have thought it only handles the actual data packets.
@zzy I was speaking to useful TCP features that should be part of a protocol meant to replace it.
The question asked if it's possible to send data in a SYN packet - which is absolutely possible to do. It's non-standard, and so may get filtered by some firewalls, but if you want to do it you can. You don't need to use UDP or some other protocol.
@RalphBolton: I have clarified my answer, and addressed TCP Fast Open specifically. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.