新手入门gopacket

Part1前言

gopacket是谷歌开源的一款抓包库,为go语音提供了处理网卡包的能力。其底层基于libpcap。github地址 https://github.com/google/gopacket。

7c4280d304bca8b70f2fff392fcc8e41.png本文主要从一个新手的角度从零开始使用该库。

Part2go环境搭建

下载地址https://golang.google.cn/doc/install
安装之后,输入go version即可查看版本号

8bafa798c02704718f642690ad6fc6aa.png

vscode调试使用按住ctrl +shift +P。接下来全选进行安装,即可完成代码提升等相关工具的安装。

f06c59635d2ef70b8849522902d9b233.png

Part3gopacket安装

安装命令

go get github.com/google/gopacket
go get github.com/google/gopacket/pcap@v1.1.19

执行完之后,还需要安装抓包库,但是由于我已经安装过了wireshark,所以不需要进行安装了。

1hello示例

package main

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

func main() {
 version := pcap.Version()
 fmt.Println(version)
}

输出结果

Npcap version 0.9991, based on libpcap version 1.9.1

2网卡查找

package main

import (
 "fmt"
 "log"

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

func findDevices() {
 // 得到所有的(网络)设备
 devices, err := pcap.FindAllDevs()
 if err != nil {
  log.Fatal(err)
 }
 // 打印设备信息
 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)
  }
 }
}

即可打印本机的所有网卡

3抓取数据

抓取数据调试了好久,一直抓不到数据,后来发现必须要设置抓包条件,默认不设置就不抓取数据。这里设置了抓取端口为443的数据。err = handle.SetBPFFilter("tcp and port 443")

package main

import (
 "fmt"
 "log"
 "time"

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

func findDevices(ip string) (name string) {
 // 得到所有的(网络)设备
 devices, err := pcap.FindAllDevs()
 if err != nil {
  log.Fatal(err)
 }
 // 打印设备信息
 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)
   if ip == address.IP.String() {
    name = device.Name
   }
  }
 }
 return
}

func Realtimecapture(ethName string) {
 // Open device
 var (
  device       string = ethName
  snapshot_len int32  = 1024
  promiscuous  bool   = false
  err          error
  timeout      time.Duration = 30 * time.Second
  handle       *pcap.Handle
 )

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

 err = handle.SetBPFFilter("tcp and port 443")
 if err != nil {
  log.Fatal(err)
 }
 // Use the handle as a packet source to process all packets
 packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

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

4写成pcap文件

还可以将网卡数据保存为pcap格式的文件,这样还可以通过wireshark进行分析。

func WritePcap(ethName string) {

 // Open device
 var (
  device       string = ethName
  snapshot_len int32  = 1600
  promiscuous  bool   = false
  err          error
  timeout      time.Duration = 30 * time.Second
  handle       *pcap.Handle
  packetCount  int = 0
 )
 f, _ := os.Create("test.pcap")
 w := pcapgo.NewWriter(f)
 var snapshotlen uint32 = 1600
 w.WriteFileHeader(snapshotlen, layers.LinkTypeEthernet)
 defer f.Close()

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

 err = handle.SetBPFFilter("tcp || udp")
 if err != nil {
  log.Fatal(err)
 }
 // Use the handle as a packet source to process all packets
 packetSource := gopacket.NewPacketSource(handle, handle.LinkType())

 for packet := range packetSource.Packets() {
  fmt.Println(packet) // Do something with a packet here.
  w.WritePacket(packet.Metadata().CaptureInfo, packet.Data())
  packetCount++

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

5读取pcap

还可以读取wireshark保存的文件,用来对包进行分析

func ReadPcap() {
 var (
  pcapFile string = "test.pcap"
  handle   *pcap.Handle
  err      error
 )
 // Open file instead of device
 handle, err = pcap.OpenOffline(pcapFile)
 if err != nil {
  log.Fatal(err)
 }
 defer handle.Close()
 // Loop through packets in file
 packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
 for packet := range packetSource.Packets() {
  fmt.Println(packet)
 }
}

6解码各层数据

我们可以将原始数据包数据强制转换为已知的格式,这里是Layer格式。layers层是gopacket的Go库中的新功能,在底层libpcap库中不存在。它是gopacket库的非常有用的一部分。它允许我们轻松地识别数据包是否包含特定类型的层。

func printPacketInfo(packet gopacket.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()
 }
}

Part4总结

本文主要介绍了如何从零开始进行gopacket的使用。其实整个gopacket的应用非常简洁,比较好入门。只不过需要从新学习一门新语言go。最近准备对go语言进行一些研究和学习。

243aeff0622e2bdd0808d70a307864f6.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值