douyan1453 2018-07-30 12:28
浏览 54
已采纳

将自定义层添加到捕获的数据包失败

I am trying to implement my own decoding layer ontop of TCP, so far it only works when I create a packet without any Eth/IP/TCP header and set its layer to my custom layer manually. The data of the custom protocol is inside an ordinary TCP payload.

How do I decode only the payload of the TCP layer as another layer?

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()
    }
}

Most of the code is from this great post by devdungeon.

  • 写回答

1条回答 默认 最新

  • dqn8235 2018-07-31 08:54
    关注

    As no one responded I am going to answer it myself now.

    Basically we have 3 options to handle this:

    1. Create an extended TCP layer that handles our additional bytes and override default one by setting layers.LinkTypeMetadata[layers.LinkTypeTCP] to our extended version. Have a look at this example.

    2. Create a new packet from the TCP payload using gopacket.NewPacket setting firstLayerDecoder to CustomLayerType and decode it normally.

    3. As you mostly don't need an actual layer but instead a filled CustomLayer struct simply write a DecodeBytesToCustomStruct function where you pass TCP payload. This way we can even return multiple structs from one packets payload which wouldn't be possible otherwise.

    Omit all CustomLayer code from above.

    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
    }
    

    In your 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 is the same as packet.ApplicationLayer().Payload()

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器