chevron_left chevron_right
Login Register invert_colors photo_library


Stay updated and chat with others! - Join the Discord!
Thread Rating:
  • 1 Vote(s) - 5 Average


TCP Packet header basics filter_list
Author
Message
TCP Packet header basics #1
In this thread I will go into exactly what a TCP packet header is, how it works, what is stored in it, and maybe a little goodie at the end on how to use it to your advantage.

This is designed for members who have no prior knowledge of the TCP protocol, but by no means am I discouraging more experienced members from reading or improving this.

What is a header?
A header is a segment of data that describes exactly what the data to follow is. We use headers for nearly everything. Take for example the following:
Code:
char *arrayChar = new char[30];
new won't just allocate 30 bytes and call it good. No, there is actually a header being placed somewhere in the malloc zone. This header enables our compiler to know how long the data is, what type of data it is, etc.
A TCP header does pretty much the same thing.

What is in a TCP header?
Alright, there are a lot of optional fields here, so I am just going to say that we are using them and write a C struct TCP header.
Code:
struct TCPHeader
{
     uint16_t source_port;
     uint16_t destination_port;
     uint32_t sequence_number;
     uint32_t acknowledgement_number;
     uint8_t data_offset; //only the first 4 bits
     uint8_t flags; //will explain later
     uint16_t window_size;
     uint16_t checksum;
     uint16_t urgent_pointer;
} __packed;
Following the header is the data of the packet (unless the data offset is greater than 5. In that case, options may follow, we will ignore all that for now. Alright, so what do all of these mean?

Source Port
Spoiler:
The port on the sender's machine that the packet is being sent through.
Destination Port
Spoiler:
The port on the receiver's machine that the packet is being sent to.
Sequence Number
Spoiler:
This one actually does two different things.
  1. If SYN is set (in flags), then this is the initial sequence number. Packets following this as well as acknowledgement numbers will be this number + 1 (incrementally)
  2. If SYN is clear, this is the accumulated sequence number
Acknowledgment Number
Spoiler:
If ACK is set, then this is the next sequence number expected to be recieved.
Data Offset
Spoiler:
This only uses the first 4 bits of the byte, and allows for up to 15 bytes of offset past the end of the header before the data actually starts. It is filled with 0s unless it is greater than 5 (5-15) in which case it may be used for optional fields. The 3 bits following the offset are reserved at 000
Flags:
Spoiler:
This is where it actually gets flawed. I wanted to keep the structure simple, so I didn't account for the fact that there are 9 flag bits. Therefore the first flag is actually the last bit of data offset.
  1. NS
  2. CWR
  3. ECE
  4. URG
  5. ACK
  6. PSH
  7. RST
  8. SYN
  9. FIN
NS - Nonce concealment protection RFC.3540
CWR - Congestion Window Reduced RFC.3168
ECE - Echo (dual purpose):
Spoiler:
SYN Set - Compatible with RFC.3168
SYN Clear - Packet with ECE was recieved
URG - Urgent pointer field is being used
ACK - Acknowledgment number being used (stating that a packet has been received and requesting the next)
PSH - PUSH data to application (Apple made this pretty famous)
RST - Reset connection
SYN - Synchronize packet numbers (only the very first packet should use this flag)
FIN - End of transmission (last packet)
Window Size
Spoiler:
Specifies the maximum number of bytes that the sender is willing to receive (basically it just sends the size of the recv buffer)
Checksum
Spoiler:
VERY IMPORTANT!!!!
The checksum is a hash of the pseudo-header (later), the TCP header, AND the data section. The TCP header and data together are called a TCP segment BTW.
Code:
struct PseudoTCPHeader
{
     uint32_t source_addr;
     uint32_t dest_addr;
     uint8_t resv;
     uint8_t protocol;
     uint16_t TCP_segment_length;
} __packed;
Now, source and dest addresses are taken from the IP header, resv is always 0b00000000, the protocol is taken from the TCP header process, it will normally be 0b00000110. The segment length is the length of the entire TCP segment to follow, which is calculated.
The checksum is calculated with the 16-bit sum field set to 0x0000, and then placed into that field. Afterwards, the pseudo header is discarded (will not be sent over wire).
Urgent Pointer
Spoiler:
"if the URG flag is set, then this 16-bit field is an offset from the sequence number indicating the last urgent data byte" I have NEVER actually seen this used before.

And there you have it.

Code:
struct PseudoTCPSegment
{
     struct PseudoTCPHeader pseudo_header;
     struct TCPHeader header;
     uint32_t data_size;
     unsigned char *wire_data;
} __packed;
struct TCPSegment
{
     struct TCPHeader header;
     uint32_t data_size;
     unsigned char *wire_data;
} __packed;
void *TCP_wiresegment(struct TCPSegment *seg)
{
     void *wire = malloc(seg->data_size + sizeof(struct TCPHeader));
     memcpy(wire, &seg->header, sizeof(struct TCPHeader));
     memcpy((wire + sizeof(struct TCPHeader)), seg->wire_data, seg->data_size);
     return wire;
}



There it all is. Comments, questions, concerns welcomed.

[+] 2 users Like phyrrus9's post
Reply






Users browsing this thread: 1 Guest(s)