【问题标题】:Adding custom layer to packet from capture fails从捕获向数据包添加自定义层失败
【发布时间】:2019-01-06 16:56:33
【问题描述】:

我正在尝试在 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()
    }
}

大部分代码来自this great post by devdungeon

【问题讨论】:

    标签: go gopacket


    【解决方案1】:

    由于没有人回应,我现在将自己回答。

    基本上我们有 3 个选项来处理这个问题:

    1. 创建一个扩展的 TCP 层来处理我们的额外字节,并通过将 layers.LinkTypeMetadata[layers.LinkTypeTCP] 设置为我们的扩展版本来覆盖默认层。 Have a look at this example.

    2. 使用gopacket.NewPacketfirstLayerDecoder 设置为CustomLayerType 从TCP 有效负载创建一个新数据包并正常解码。

    3. 因为您通常不需要实际的层,而是需要填充的 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.Payloadpacket.ApplicationLayer().Payload() 相同

    【讨论】:

    • 我猜你选择了第三个选项。我正在学习 GO,我想更好地了解这三个选项的优缺点。感谢您的问题/答案!
    猜你喜欢
    • 1970-01-01
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 2013-03-02
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多