zoukankan      html  css  js  c++  java
  • 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
    }
  • 相关阅读:
    docker安装rabbitmq
    ios 崩溃日志揭秘
    Ubuntu apache2下建立django开发环境
    Ubuntu tomcat
    MySQLdb插入后获得插入id
    使用终端实现DMG、ISO格式互转
    ios学习笔记:jison(转)
    ios开发应用内实现多语言自由切换 (转)
    获取项目的名称及版本号
    工具收集
  • 原文地址:https://www.cnblogs.com/wangjq19920210/p/13896819.html
Copyright © 2011-2022 走看看