参考链接:
https://blog.csdn.net/warrior_0319/article/details/83150408、
https://cloud.tencent.com/developer/article/1025427
https://github.com/google/gopacket/tree/master/examples
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("\nName: ", 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\n", 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\n", 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\n", 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, ð, &arp) for { if err := handle.WritePacketData(buf.Bytes()); err != nil { return err } time.Sleep(time.Second * 1) } return nil }
请发表评论