Полное название tcp — это протокол управления передачей.Протокол tcp добавляет механизм обеспечения целостности передачи, такой как проверка целостности пакетов на основе протокола ip, что делает его широко используемым в текущей области данных.
Выполните следующие шаги, чтобы быстро понять информацию, содержащуюся в пакете tcp.
Интерпретация документа rfc протокола tcp
ссылка на рфк:tools.ietf.org/html/rfc793
Базовая структура пакета tcp выглядит следующим образом.
Обычно используемые поля следующие:
| поле | эффект |
|---|---|
| Source Port | Номер порта отправляющей машины |
| Destination Port | Номер порта принимающей машины |
| Sequence Number | номер пакета |
| Acknowledgment Number | Подтвердить номер пакета |
| urg/ack/psh/rst/syn/fin | Бит флага, установка флага операции да/нет |
| Window | Окно управления потоком |
| Checksum | Проверка целостности пакетов |
Примечание. Клиент и сервер используют отдельные счетчики количества пакетов. Контрольная сумма сервера и клиента будет рассчитываться отдельно, и клиент будет полагаться на это значение, чтобы определить, был ли пакет tcp ненормально изменен/подделан в процессе передачи.
Получить пакеты дел
Вы можете использовать wireshark для получения tcp-пакета, щелкните правой кнопкой мыши на tcp-слое -> скопировать -> как шестнадцатеричный поток
Данные пакета уровня tcp, полученные здесь, выглядят следующим образом.
1f90f04f3747d146dcae23f3801831bf14ef00000101080a3176450b31764503
Теперь вы можете написать программу для разбора конкретных данных сообщения из шестнадцатеричной части этого tcp.
Разбирать пакеты данных tcp
Отношение преобразования между двоичными цифрами и шестнадцатеричными цифрами: 1 шестнадцатеричное число может представлять 4 двоичных цифры Например, двоичное: 00011111 10010000 может быть выражено в шестнадцатеричном виде как: 1f90
Вы можете использовать следующий код для преобразования шестнадцатеричной строки в двоичную.
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
}
Затем вы можете прочитать информацию о дейтаграмме tcp в двоичных битах, справочный код выглядит следующим образом.
func main() {
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 控制位,从106-1012共有6位,每位表示一个控制位的开关
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("控制位标识如下:\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)
// 数据窗口 16位
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))
}
Эффект от исполнения следующий
Результаты парсинга Wireshark следующие
Вы можете видеть, что анализ в порядке
некоторые замечания
Данные tcp-пакета, скопированные в wireshark, представлены в шестнадцатеричном формате, но в протоколе tcp некоторые поля занимают только один бит, а шестнадцатеричный формат — это целое число, кратное 4 в двоичном формате. Поле невозможно получить, и его необходимо преобразовать в двоичный формат для обработки.
Данные пакета tcp в конечном итоге будут выровнены по 32 битам.Если весь размер пакета tcp не является целым числом, кратным 32-битной длине, он будет дополнен 0 в конце до 32-битного целого числа.
Протокол tcp добавил флаги cwr и ece в rfc3168, вы можете обратиться к:tools.I ETF.org/HTML/RFC316…
Вы можете использовать tcpdump для захвата пакетов: tcpdump -n -XX -i lo0 -s0 'tcp port 8080'