Не удается добавить пользовательский слой в пакет из захвата
Я пытаюсь реализовать свой собственный уровень декодирования поверх TCP, пока он работает только тогда, когда я создаю пакет без какого-либо заголовка Eth/IP/TCP и вручную устанавливаю его уровень на свой пользовательский уровень. Данные пользовательского протокола находятся внутри обычной полезной нагрузки TCP.
Как мне декодировать только полезную нагрузку уровня TCP как другой уровень?
package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
var (
pcapFile string = "capt.pcap"
handle *pcap.Handle
err error
)
type CustomLayer struct {
SomeByte byte
AnotherByte byte
restOfData []byte
}
var CustomLayerType = gopacket.RegisterLayerType(
2001,
gopacket.LayerTypeMetadata{
"CustomLayerType",
gopacket.DecodeFunc(decodeCustomLayer),
},
)
func (l CustomLayer) LayerType() gopacket.LayerType {
return CustomLayerType
}
func (l CustomLayer) LayerContents() []byte {
return []byte{l.SomeByte, l.AnotherByte}
}
func (l CustomLayer) LayerPayload() []byte {
return l.restOfData
}
func decodeCustomLayer(data []byte, p gopacket.PacketBuilder) error {
p.AddLayer(&CustomLayer{data[0], data[1], data[2:]})
// nil means this is the last layer. No more decoding
return nil
}
func main() {
handle, err = pcap.OpenOffline(pcapFile)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
fmt.Println("TCP layer detected.")
tcp, _ := tcpLayer.(*layers.TCP)
fmt.Println("Sequence number: ", tcp.Seq)
customLayer := packet.Layer(CustomLayerType)
if customLayer != nil { // always nil
customLayerContent, _ := customLayer.(*CustomLayer)
// Now we can access the elements of the custom struct
fmt.Println("Payload: ", customLayerContent.LayerPayload())
fmt.Println("SomeByte element:", customLayerContent.SomeByte)
fmt.Println("AnotherByte element:", customLayerContent.AnotherByte)
}
}
fmt.Println()
}
}
Большая часть кода взята из этого замечательного поста devdungeon.
1 ответ
Поскольку никто не ответил, я собираюсь ответить на него сам сейчас.
В основном у нас есть 3 варианта, чтобы справиться с этим:
Создайте расширенный слой TCP, который обрабатывает наши дополнительные байты, и переопределите один по умолчанию, установив
layers.LinkTypeMetadata[layers.LinkTypeTCP]
к нашей расширенной версии. Посмотрите на этот пример.Создайте новый пакет из полезной нагрузки TCP, используя
gopacket.NewPacket
установкаfirstLayerDecoder
вCustomLayerType
и декодировать это нормально.Поскольку вам в основном не нужен фактический слой, а вместо этого заполненная структура CustomLayer просто напишите
DecodeBytesToCustomStruct
функция, где вы передаете полезную нагрузку TCP. Таким образом, мы можем даже вернуть несколько структур из одного пакета, что иначе было бы невозможно.
Опустить весь код CustomLayer сверху.
type CustomStruct struct {
SomeByte byte
AnotherByte byte
restOfData []byte
}
func (customStruct *CustomStruct) DecodeStructFromBytes(data []byte) error {
customStruct.SomeByte = data[0]
customStruct.AnotherByte = data[1]
customStruct.restOfData = data[2:]
return nil
}
В вашем main.go
for packet := range packetSource.Packets() {
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
if tcp.Payload != nil && len(tcpLayer.Payload) > 0 {
customStruct := CustomStruct{}
customStruct.DecodeStructFromBytes(tcp.Payload)
fmt.Println("SomeByte element:", customStruct.SomeByte)
}
}
}
tcp.Payload
такой же как packet.ApplicationLayer().Payload()