TCP is the transmission control protocol, TCP protocol in IP protocol on the basis of the increase of packet integrity check to ensure the integrity of transmission mechanism, so that it has been widely used in the field of data
Follow these steps to quickly understand the information contained in TCP packets
Description of TCP RFC documents
Reference: RFC tools.ietf.org/html/rfc793
The core TCP packet structure is as follows
The common fields are as follows
field | role |
---|---|
Source Port | Port number of the packet sending machine |
Destination Port | Port number of the packet receiving machine |
Sequence Number | Package number, |
Acknowledgment Number | Confirm the package, |
urg/ack/psh/rst/syn/fin | Flag bit that sets the yes/no operation flag |
Window | Flow control window |
Checksum | Packet integrity check |
The client uses this value to determine whether TCP packets have been altered or tampered with in transit
Get case packets
To obtain a TCP packet using wireshark, right-click on the TCP layer, select Copy, and select as a Hex Stream
The TCP packet data obtained here is as follows
1f90f04f3747d146dcae23f3801831bf14ef00000101080a3176450b31764503
Copy the code
Now you can write a program to parse out the specific data of the message from this TCP hexadecimal
Parse TCP data packets
The conversion relationship between binary digits and hexadecimal digits: One hexadecimal number can represent four binary numbers. For example, binary: 00011111 10010000 can be expressed in hexadecimal: 1F90
You can convert hexadecimal to binary strings using the following code
func hex2bin(hex string) string {
var bin string
for i := 0; i < len(hex); i++ {
hex2int, _ := strconv.ParseInt(string(hex[i]), 16.64)
bin = bin + fmt.Sprintf("%04b", hex2int)
}
return bin
}
Copy the code
Then the TCP datagram information can be read by binary bits, the reference code is as follows
func main(a) {
atcp := "1f90f04f3747d146dcae23f3801831bf14ef00000101080a3176450b31764503"
bintcp := hex2bin(atcp)
sourcePort, _ := strconv.ParseInt(bintcp[0:16].2.64)
fmt.Printf("sourcePort is %d \n", sourcePort)
destinationPort, _ := strconv.ParseInt(bintcp[16:32].2.64)
fmt.Printf("destinationPort is %d \n", destinationPort)
sequenceNumber, _ := strconv.ParseInt(bintcp[32:64].2.64)
fmt.Printf("sequenceNumber is %d \n", sequenceNumber)
acknowledgmentNumber, _ := strconv.ParseInt(bintcp[64:96].2.64)
fmt.Printf("acknowledgmentNumber is %d \n", acknowledgmentNumber)
dataOffset, _ := strconv.ParseInt(bintcp[96:100].2.64)
fmt.Printf("dataOffset is %d \n", dataOffset)
reserved, _ := strconv.ParseInt(bintcp[100:106].2.64)
fmt.Printf("reserved is %d \n", reserved)
// Control Bits Control Bits. The value ranges from 106 to 1012. There are six Bits in total
urg, _ := strconv.ParseInt(bintcp[106:107].2.64)
ack, _ := strconv.ParseInt(bintcp[107:108].2.64)
psh, _ := strconv.ParseInt(bintcp[108:109].2.64)
rst, _ := strconv.ParseInt(bintcp[109:110].2.64)
syn, _ := strconv.ParseInt(bintcp[110:111].2.64)
fin, _ := strconv.ParseInt(bintcp[111:112].2.64)
fmt.Printf("Control bit identifier as follows :\n")
fmt.Printf(" urg: %d\n", urg)
fmt.Printf(" ack: %d\n", ack)
fmt.Printf(" psh: %d\n", psh)
fmt.Printf(" rst: %d\n", rst)
fmt.Printf(" syn: %d\n", syn)
fmt.Printf(" fin: %d\n", fin)
// Data window 16 bits
window, _ := strconv.ParseInt(bintcp[112:128].2.64)
fmt.Printf("window is %d \n", window)
/ / checksum 16
checksum, _ := strconv.ParseInt(bintcp[128:144].2.64)
fmt.Printf("checksum is %d \n", checksum)
// urgentPointer
urgentPointer, _ := strconv.ParseInt(bintcp[144:160].2.64)
fmt.Printf("urgentPointer is %d \n", urgentPointer)
// options and padding
optionsAndPaddings := bintcp[160:]
fmt.Printf("optionsAndPaddings is %s \n", optionsAndPaddings)
fmt.Printf("tcp raw data is %s \n", atcp)
fmt.Printf("tcp bin data is %s \n", bintcp)
fmt.Printf("tcp bin data length is %d\n".len(bintcp))
}
Copy the code
The execution effect is as follows
The wireshark results are as follows
You can see that parsing is OK
A couple of points to note
The TCP packet data copied in the Wireshark is in hexadecimal format. However, some TCP fields occupy only one bit, and the hexadecimal format is a multiple of 4 in hexadecimal format. Parsing the hexadecimal format directly results in some TCP fields cannot be obtained
TCP packet data is eventually aligned to 32 bits, and the entire TCP packet size is padded to a 32 bit multiple with 0 at the end if it is not exactly a 32 bit multiple
TCP protocol in rfc3168 CWR and ece mark has been added, you can refer to: tools.ietf.org/html/rfc316…
Tcpdump: tcpdump -n -xx -i lo0 -s0 ‘TCP port 8080’
The resources
- Github.com/google/pack…
- Klamath.stanford.edu/~nickm/pape…
- Pcapplusplus. Making. IO/docs/tutori…
- Tools.ietf.org/html/rfc793…
- Forums.ni.com/t5/LabVIEW/…