【TCP】图解,一步一步拆解TCP包结构,各个字段分析

 

原始pcap包内容

TCP包结构定义

 

分析

源端口目的端口

序列号

确认号

序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。e.g.一个报文段的序号为300,此报文段数据部分共有100字节,则下一个报文段的序号为400。所以序号确保了TCP传输的有序性。确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。比如建立连接时,SYN报文的ACK标志位为0。

4位首部长度

4bits。由于首部可能含有可选项内容,因此TCP报头的长度是不确定的,报头不包含任何任选字段则长度为20字节,4位首部长度字段所能表示的最大值为1111,转化为10进制为15,15*32/8 = 60,故报头最大长度为60字节。首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。

所以图上是32bytes,32个字节长度头部

 

保留6位

为将来定义新的用途保留,现在一般置0。

URG

紧急指针标志,为1时表示紧急指针有效,为0则忽略紧急指针。

ACK

确认序号标志,为1时表示确认号有效,为0表示报文中不含确认信息,忽略确认号字段。

PSH

push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。

RST

重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求。

SYN

同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。

FIN

finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。

16位窗口大小

滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。窗口大小是一个16bit字段,因而窗口大小最大为65535。

零窗口(ZeroWindow)

当发送方的发送速度大于接收方的处理速度,接收方的缓冲塞满后,就会告诉发送方当前窗口size=0,请停止发送,发送方此时停止发送数据。

16位TCP校验和

奇偶校验,此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。

16位紧急指针

只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。

选项(若有)

最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是32位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证TCP头是32的整数倍。

数据(若有)

 TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。在处理超时的许多情况中,也会发送不带任何数据的报文段。

 

 

可以使用golang中的net库和raw socket来构造一个TCP SYN并添加TCP选项字段。以下是一个示例代码: ```go package main import ( "net" "syscall" ) func main() { // 构造TCP SYN srcIP := net.ParseIP("192.168.1.100") dstIP := net.ParseIP("192.168.1.1") srcPort := 12345 dstPort := 80 seqNum := uint32(123456789) tcpHeaderLen := 20 tcpFlags := syscall.TCP_SYN // 构造TCP选项字段 tcpOptions := []byte{0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x0f, 0x48, 0x61, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x57, 0x65, 0x62, 0x21} // 构造TCP头部 tcpHeader := make([]byte, tcpHeaderLen) tcpHeader[0] = byte(srcPort >> 8) tcpHeader[1] = byte(srcPort) tcpHeader[2] = byte(dstPort >> 8) tcpHeader[3] = byte(dstPort) tcpHeader[4] = byte(seqNum >> 24) tcpHeader[5] = byte(seqNum >> 16) tcpHeader[6] = byte(seqNum >> 8) tcpHeader[7] = byte(seqNum) tcpHeader[8] = byte(0) tcpHeader[9] = byte(0) tcpHeader[10] = byte(tcpHeaderLen >> 8) tcpHeader[11] = byte(tcpHeaderLen) tcpHeader[13] = byte(tcpFlags) tcpHeader[14] = byte(0x10) tcpHeader[15] = byte(0xff) // 添加TCP选项字段 copy(tcpHeader[tcpHeaderLen:], tcpOptions) // 构造IP头部 ipHeaderLen := 20 ipVersion := 4 ipHeader := make([]byte, ipHeaderLen) ipHeader[0] = byte(ipVersion<<4 | ipHeaderLen>>2) ipHeader[1] = byte(0) ipHeader[2] = byte(0) ipHeader[3] = byte(0) ipHeader[4] = byte(0) ipHeader[5] = byte(0) ipHeader[6] = byte(0) ipHeader[7] = byte(0) ipHeader[8] = byte(0) ipHeader[9] = byte(0) ipHeader[10] = byte(0xff) ipHeader[11] = byte(0xff) copy(ipHeader[12:16], srcIP.To4()) copy(ipHeader[16:20], dstIP.To4()) // 计算IP头部校验和 checksum := checksum(ipHeader) // 添加IP头部校验和 ipHeader[10] = byte(checksum >> 8) ipHeader[11] = byte(checksum) // 合并IP和TCP头部 packet := make([]byte, len(ipHeader)+len(tcpHeader)) copy(packet, ipHeader) copy(packet[len(ipHeader):], tcpHeader) // 发送TCP SYN conn, err := net.Dial("ip4:tcp", dstIP.String()) if err != nil { panic(err) } defer conn.Close() _, err = conn.Write(packet) if err != nil { panic(err) } } // 计算校验和 func checksum(data []byte) uint16 { var sum uint32 for i := 0; i < len(data)-1; i += 2 { sum += uint32(data[i])<<8 | uint32(data[i+1]) } if len(data)%2 != 0 { sum += uint32(data[len(data)-1]) << 8 } for (sum >> 16) > 0 { sum = (sum & 0xffff) + (sum >> 16) } return ^uint16(sum) } ``` 这段代码构造了一个源IP为192.168.1.100,目标IP为192.168.1.1,源端口为12345,目标端口为80的TCP SYN,并添加了TCP选项字段。在发送之前,需要使用`net.Dial("ip4:tcp", dstIP.String())`连接到目标IP地址,然后将构造好的TCP SYN写入连接中即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值