go 网络数据包分析(1)

参考链接:

https://blog.csdn.net/warrior_0319/article/details/83150408

https://blog.lfoder.cn/2018/06/17/Golang%E8%B0%83%E7%94%A8gopacket%E5%BA%93%E7%BC%96%E5%86%99%E7%BD%91%E7%BB%9C%E6%95%B0%E6%8D%AE%E5%8C%85%E6%8D%95%E8%8E%B7%E3%80%81%E6%B3%A8%E5%85%A5%E3%80%81%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7/

https://cloud.tencent.com/developer/article/1025427

https://github.com/google/gopacket/tree/master/examples

https://golang.hotexamples.com/zh/examples/github.com.google.gopacket.layers/IPv6/-/golang-ipv6-class-examples.html

 

demo1:获取所有的网络设备信息

package main

import (
        "fmt"
        "github.com/google/gopacket/pcap"
        "log"
)

func main() {
        // Find all devices
        devices, err := pcap.FindAllDevs()
        if err != nil {
                log.Fatal(err)
        }

        // Print device information
        fmt.Println("Devices found:")
        for _, device := range devices {
                fmt.Println("
Name: ", device.Name)
                fmt.Println("Description: ", device.Description)
                fmt.Println("Devices addresses: ", device.Description)

                for _, address := range device.Addresses {
                        fmt.Println("- IP address: ", address.IP)
                        fmt.Println("- Subnet mask: ", address.Netmask)
                }
        }
}

运行结果:

Name:  ens33
Description:  
Devices addresses:  
- IP address:  192.168.1.100
- Subnet mask:  ffffff00

demo2:打开设备实时捕捉

package main

import (
        "fmt"
        "github.com/google/gopacket"
        "github.com/google/gopacket/pcap"
        "log"
        "time"
)

var (
        device       string = "ens33"
        snapshot_len int32  = 1024
        promiscuous  bool   = false
        err          error
        timeout      time.Duration = 30 * time.Second
        handle       *pcap.Handle
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        // Use the handle as a packet source to process all packets
        packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
        for packet := range packetSource.Packets() {
                // Process packet here
                fmt.Println(packet)
        }
}

运行结果:

PACKET: 1024 bytes, truncated, wire length 1750 cap length 1024 @ 2020-10-29 14:58:06.569083 +0800 CST
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..1010..] SrcMAC=00:0c:29:10:dc:10 DstMAC=00:50:56:c0:00:08 EthernetType=IPv4 Length=0}
- Layer 2 (20 bytes) = IPv4     {Contents=[..20..] Payload=[..990..] Version=4 IHL=5 TOS=16 Length=1736 Id=3808 Flags=DF FragOffset=0 TTL=64 Protocol=TCP Checksum=41354 SrcIP=192.168.1.100 DstIP=192.168.1.1 Options=[] Padding=[]}
- Layer 3 (20 bytes) = TCP      {Contents=[..20..] Payload=[..970..] SrcPort=22(ssh) DstPort=59004 Seq=3324909626 Ack=463955946 DataOffset=5 FIN=false SYN=false RST=false PSH=true ACK=true URG=false ECE=false CWR=false NS=false Window=988 Checksum=35440 Urgent=0 Options=[] Padding=[]}
- Layer 4 (970 bytes) = Payload 970 byte(s)

demo3:抓取结果保存为pcap格式文件

package main

import (
        "fmt"
        "os"
        "time"

        "github.com/google/gopacket"
        "github.com/google/gopacket/layers"
        "github.com/google/gopacket/pcap"
        "github.com/google/gopacket/pcapgo"
)

var (
        deviceName  string = "ens33"
        snapshotLen int32  = 1024
        promiscuous bool   = false
        err         error
        timeout     time.Duration = -1 * time.Second
        handle      *pcap.Handle
        packetCount int = 0
)

func main() {
        // Open output pcap file and write header
        f, _ := os.Create("test.pcap")
        w := pcapgo.NewWriter(f)
        w.WriteFileHeader(uint32(snapshotLen), layers.LinkTypeEthernet)
        defer f.Close()

        // Open the device for capturing
        handle, err = pcap.OpenLive(deviceName, snapshotLen, promiscuous, timeout)
        if err != nil {
                fmt.Printf("Error opening device %s: %v", deviceName, err)
                os.Exit(1)
        }
        defer handle.Close()

        // Start processing packets
        packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
        for packet := range packetSource.Packets() {
                // Process packet here
                fmt.Println(packet)
                w.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
                packetCount++

                // Only capture 100 and then stop
                if packetCount > 100 {
                        break
                }
        }
}

demo4:设置过滤器

package main

import (
        "fmt"
        "github.com/google/gopacket"
        "github.com/google/gopacket/pcap"
        "log"
        "time"
)

var (
        device       string = "ens33"
        snapshot_len int32  = 1024
        promiscuous  bool   = false
        err          error
        timeout      time.Duration = 30 * time.Second
        handle       *pcap.Handle
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        // Set filter
        var filter string = "tcp and port 80"
        err = handle.SetBPFFilter(filter)
        if err != nil {
                log.Fatal(err)
        }
        fmt.Println("Only capturing TCP port 80 packets.")

        packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
        for packet := range packetSource.Packets() {
                // Do something with a packet here.
                fmt.Println(packet)
        }
}

运行结果:

PACKET: 60 bytes, wire length 60 cap length 60 @ 2020-10-29 15:37:21.20373 +0800 CST
- Layer 1 (14 bytes) = Ethernet {Contents=[..14..] Payload=[..46..] SrcMAC=00:50:56:eb:fe:9f DstMAC=00:0c:29:10:dc:10 EthernetType=IPv4 Length=0}
- Layer 2 (20 bytes) = IPv4     {Contents=[..20..] Payload=[..20..] Version=4 IHL=5 TOS=0 Length=40 Id=54629 Flags= FragOffset=0 TTL=128 Protocol=TCP Checksum=41308 SrcIP=1.1.1.1 DstIP=192.168.1.100 Options=[] Padding=[]}
- Layer 3 (20 bytes) = TCP      {Contents=[..20..] Payload=[] SrcPort=80(http) DstPort=38714 Seq=2115461962 Ack=1321928712 DataOffset=5 FIN=true SYN=false RST=false PSH=true ACK=true URG=false ECE=false CWR=false NS=false Window=64239 Checksum=8462 Urgent=0 Options=[] Padding=[]}

demo5:解码抓取的数据

package main

import (
        "fmt"
        "github.com/google/gopacket"
        "github.com/google/gopacket/layers"
        "github.com/google/gopacket/pcap"
        "log"
        "strings"
        "time"
)

var (
        device      string = "ens33"
        snapshotLen int32  = 1024
        promiscuous bool   = false
        err         error
        timeout     time.Duration = 30 * time.Second
        handle      *pcap.Handle
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
        for packet := range packetSource.Packets() {
                printPacketInfo(packet)
        }
}

func printPacketInfo(packet gopacket.Packet) {
        // Let’s see if the packet is an ethernet packet
        ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
        if ethernetLayer != nil {
                fmt.Println("Ethernet layer detected.")
                ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
                fmt.Println("Source MAC: ", ethernetPacket.SrcMAC)
                fmt.Println("Destination MAC: ", ethernetPacket.DstMAC)
                // Ethernet type is typically IPv4 but could be ARP or other
                fmt.Println("Ethernet type: ", ethernetPacket.EthernetType)
                fmt.Println()
        }

        // Let’s see if the packet is IP (even though the ether type told us)
        ipLayer := packet.Layer(layers.LayerTypeIPv4)
        if ipLayer != nil {
                fmt.Println("IPv4 layer detected.")
                ip, _ := ipLayer.(*layers.IPv4)

                // IP layer variables:
                // Version (Either 4 or 6)
                // IHL (IP Header Length in 32-bit words)
                // TOS, Length, Id, Flags, FragOffset, TTL, Protocol (TCP?),
                // Checksum, SrcIP, DstIP
                fmt.Printf("From %s to %s
", ip.SrcIP, ip.DstIP)
                fmt.Println("Protocol: ", ip.Protocol)
                fmt.Println()
        }

        // Let’s see if the packet is TCP
        tcpLayer := packet.Layer(layers.LayerTypeTCP)
        if tcpLayer != nil {
                fmt.Println("TCP layer detected.")
                tcp, _ := tcpLayer.(*layers.TCP)

                // TCP layer variables:
                // SrcPort, DstPort, Seq, Ack, DataOffset, Window, Checksum, Urgent
                // Bool flags: FIN, SYN, RST, PSH, ACK, URG, ECE, CWR, NS
                fmt.Printf("From port %d to %d
", tcp.SrcPort, tcp.DstPort)
                fmt.Println("Sequence number: ", tcp.Seq)
                fmt.Println()
        }

        // Iterate over all layers, printing out each layer type
        fmt.Println("All packet layers:")
        for _, layer := range packet.Layers() {
                fmt.Println("- ", layer.LayerType())
        }

        // When iterating through packet.Layers() above,
        // if it lists Payload layer then that is the same as
        // this applicationLayer. applicationLayer contains the payload
        applicationLayer := packet.ApplicationLayer()
        if applicationLayer != nil {
                fmt.Println("Application layer/Payload found.")
                fmt.Printf("%s
", applicationLayer.Payload())

                // Search for a string inside the payload
                if strings.Contains(string(applicationLayer.Payload()), "HTTP") {
                        fmt.Println("HTTP found!")
                }
        }

        // Check for errors
        if err := packet.ErrorLayer(); err != nil {
                fmt.Println("Error decoding some part of the packet:", err)
        }
}

运行结果:

Ethernet layer detected.
Source MAC:  00:50:56:c0:00:08
Destination MAC:  00:0c:29:10:dc:10
Ethernet type:  IPv4

IPv4 layer detected.
From 192.168.1.1 to 192.168.1.100
Protocol:  TCP

TCP layer detected.
From port 59004 to 22
Sequence number:  464180954

All packet layers:
-  Ethernet
-  IPv4
-  TCP
-  Payload

demo6:更快地解码数据包

package main

import (
        "github.com/google/gopacket"
        "github.com/google/gopacket/layers"
        "github.com/google/gopacket/pcap"
        "log"
        "net"
        "time"
)

var (
        device       string = "ens33"
        snapshot_len int32  = 1024
        promiscuous  bool   = false
        err          error
        timeout      time.Duration = 30 * time.Second
        handle       *pcap.Handle
        buffer       gopacket.SerializeBuffer
        options      gopacket.SerializeOptions
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        // Send raw bytes over wire
        rawBytes := []byte{10, 20, 30}
        err = handle.WritePacketData(rawBytes)
        if err != nil {
                log.Fatal(err)
        }

        // Create a properly formed packet, just with
        // empty details. Should fill out MAC addresses,
        // IP addresses, etc.
        buffer = gopacket.NewSerializeBuffer()
        gopacket.SerializeLayers(buffer, options,
                &layers.Ethernet{},
                &layers.IPv4{},
                &layers.TCP{},
                gopacket.Payload(rawBytes),
        )
        outgoingPacket := buffer.Bytes()
        // Send our packet
        err = handle.WritePacketData(outgoingPacket)
        if err != nil {
                log.Fatal(err)
        }

        // This time lets fill out some information
        ipLayer := &layers.IPv4{
                SrcIP: net.IP{127, 0, 0, 1},
                DstIP: net.IP{8, 8, 8, 8},
        }
        ethernetLayer := &layers.Ethernet{
                SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA},
                DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD},
        }
        tcpLayer := &layers.TCP{
                SrcPort: layers.TCPPort(4321),
                DstPort: layers.TCPPort(80),
        }
        // And create the packet with the layers
        buffer = gopacket.NewSerializeBuffer()
        gopacket.SerializeLayers(buffer, options,
                ethernetLayer,
                ipLayer,
                tcpLayer,
                gopacket.Payload(rawBytes),
        )
        outgoingPacket = buffer.Bytes()
}

demo7:构造发送数据包

构造UDP报文:

package main

import (
        "log"
        "net"
        "time"

        "github.com/google/gopacket/layers"

        "github.com/google/gopacket"
        "github.com/google/gopacket/pcap"
)

var (
        device       string = "ens33"
        snapshot_len int32  = 1024
        promiscuous  bool   = false
        err          error
        timeout      time.Duration = 30 * time.Second
        handle       *pcap.Handle
        buffer       gopacket.SerializeBuffer
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        // Send raw bytes over wire
        rawBytes := []byte{'A', 'b', 'C'}

        // This time lets fill out some information
        ipLayer := &layers.IPv4{
                Protocol: layers.IPProtocolUDP,
                SrcIP:    net.IPv4(1, 1, 1, 1),
                DstIP:    net.IPv4(2, 2, 2, 2),
                Version:  4,
                TTL:      64,
        }
        ethernetLayer := &layers.Ethernet{
                EthernetType: layers.EthernetTypeIPv4,
                SrcMAC:       net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA},
                DstMAC:       net.HardwareAddr{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
        }
        udpLayer := &layers.UDP{
                SrcPort: 1,
                DstPort: 2,
        }
        if err := udpLayer.SetNetworkLayerForChecksum(ipLayer); err != nil {
                return
        }

        // And create the packet with the layers
        buffer = gopacket.NewSerializeBuffer()
        opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true}
        gopacket.SerializeLayers(buffer, opts,
                ethernetLayer,
                ipLayer,
                udpLayer,
                gopacket.Payload(rawBytes),
        )
        outgoingPacket := buffer.Bytes()
        for {
                time.Sleep(time.Second * 1)
                err = handle.WritePacketData(outgoingPacket)
                if err != nil {
                        log.Fatal(err)
                }
        }

        handle.Close()
}

 构造ARP报文:

package main

import (
        "log"
        "net"
        "time"

        "github.com/google/gopacket/layers"

        "github.com/google/gopacket"
        "github.com/google/gopacket/pcap"
)

var (
        device       string = "eth0"
        snapshot_len int32  = 1024
        promiscuous  bool   = false
        err          error
        timeout      time.Duration = 30 * time.Second
        handle       *pcap.Handle
        buffer       gopacket.SerializeBuffer
)

func main() {
        // Open device
        handle, err = pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
        if err != nil {
                log.Fatal(err)
        }
        defer handle.Close()

        // Write our scan packets out to the handle.
        if err := writeARP(handle); err != nil {
                log.Printf("error writing packets on %v: %v", device, err)
                return
        }
}

func writeARP(handle *pcap.Handle) error {
        _, srcAddr, _ := net.ParseCIDR("1.1.1.1/32")
        _, dstAddr, _ := net.ParseCIDR("200.0.100.5/32")

        // Set up all the layers' fields we can.
        eth := layers.Ethernet{
                SrcMAC:       net.HardwareAddr{0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA},
                DstMAC:       net.HardwareAddr{0x00, 0x00, 0x5E, 0x00, 0x01, 0x00},
                EthernetType: layers.EthernetTypeARP,
        }
        arp := layers.ARP{
                AddrType:          layers.LinkTypeEthernet,
                Protocol:          layers.EthernetTypeIPv4,
                HwAddressSize:     6,
                ProtAddressSize:   4,
                Operation:         layers.ARPReply,
                SourceHwAddress:   net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
                DstHwAddress:      net.HardwareAddr{0x00, 0x00, 0x5E, 0x00, 0x01, 0x00},
                SourceProtAddress: []byte(srcAddr.IP),
                DstProtAddress:    []byte(dstAddr.IP),
        }
        // Set up buffer and options for serialization.
        buf := gopacket.NewSerializeBuffer()
        opts := gopacket.SerializeOptions{
                FixLengths:       true,
                ComputeChecksums: true,
        }
        // Send one packet for every address.
        gopacket.SerializeLayers(buf, opts, &eth, &arp)
        for {
                if err := handle.WritePacketData(buf.Bytes()); err != nil {
                        return err
                }

                time.Sleep(time.Second * 1)
        }
        return nil
}
原文地址:https://www.cnblogs.com/wangjq19920210/p/13896819.html