将自定义层添加到捕获的数据包失败
Adding custom layer to packet from capture fails
我正在尝试在 TCP 之上实现我自己的解码层,到目前为止,它仅在我创建没有任何 Eth/IP/TCP header 的数据包并将其层手动设置为我的自定义层时才有效。自定义协议的数据在普通的 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()
}
}
大部分代码来自this great post by devdungeon。
因为没有人回复我现在要自己回答了。
基本上我们有 3 个选项来处理这个问题:
创建一个扩展的 TCP 层来处理我们的额外字节并通过将 layers.LinkTypeMetadata[layers.LinkTypeTCP]
设置为我们的扩展版本来覆盖默认层。 Have a look at this example.
使用 gopacket.NewPacket
将 firstLayerDecoder
设置为 CustomLayerType
从 TCP 负载创建一个新数据包并正常解码。
因为您通常不需要实际的层,而是填充的 CustomLayer 结构,只需编写一个 DecodeBytesToCustomStruct
函数,您就可以在其中传递 TCP 负载。这样我们甚至可以 return 来自一个数据包有效负载的多个结构,否则这是不可能的。
省略上面的所有 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()
我正在尝试在 TCP 之上实现我自己的解码层,到目前为止,它仅在我创建没有任何 Eth/IP/TCP header 的数据包并将其层手动设置为我的自定义层时才有效。自定义协议的数据在普通的 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()
}
}
大部分代码来自this great post by devdungeon。
因为没有人回复我现在要自己回答了。
基本上我们有 3 个选项来处理这个问题:
创建一个扩展的 TCP 层来处理我们的额外字节并通过将
layers.LinkTypeMetadata[layers.LinkTypeTCP]
设置为我们的扩展版本来覆盖默认层。 Have a look at this example.使用
gopacket.NewPacket
将firstLayerDecoder
设置为CustomLayerType
从 TCP 负载创建一个新数据包并正常解码。因为您通常不需要实际的层,而是填充的 CustomLayer 结构,只需编写一个
DecodeBytesToCustomStruct
函数,您就可以在其中传递 TCP 负载。这样我们甚至可以 return 来自一个数据包有效负载的多个结构,否则这是不可能的。
省略上面的所有 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()