Go最新Golang抓包:实现网络数据包捕获与分析_golang pcap(6),2024年最新零基础如何成为高级Golang开发

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

"fmt"
"net"

)

func main() {
interfaces, err := net.Interfaces()
if err != nil {
fmt.Println(“Failed to get interfaces:”, err)
return
}

fmt.Println("Network interfaces:")
for \_, iface := range interfaces {
	fmt.Println("- Name:", iface.Name)
}

}


执行上述代码,会输出计算机上所有的网络设备名称。


可以通过以下代码来打开一个网络设备:



package main

import (
“fmt”
“log”
“net”

"github.com/google/gopacket/pcap"

)

func main() {
device := “eth0” // 要打开的网络设备名称

handle, err := pcap.OpenLive(device, 65536, true, pcap.BlockForever)
if err != nil {
	log.Fatal(err)
}
defer handle.Close()

fmt.Println("Device opened:", device)

}


在上述代码中,我们使用`pcap.OpenLive`函数来打开一个网络设备。该函数接受设备名称、数据包最大长度、是否要抓取数据包的全部内容以及超时时间作为参数。如果打开成功,将返回一个`pcap.Handle`对象,可以用于后续的数据包捕获和分析。


#### 捕获数据包


在打开网络设备之后,我们可以开始捕获数据包。可以通过以下代码来捕获指定数量的数据包:



package main

import (
“fmt”
“log”
“net”
“time”

"github.com/google/gopacket/pcap"

)

func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}

handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
	log.Fatal(err)
}
defer handle.Close()

packetCount := 0
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
	packetCount++
	fmt.Println("Packet:", packetCount)

	// TODO: 进行数据包分析
	time.Sleep(1 \* time.Second) // 仅用于示例,避免数据包流量过大
}

}


上述代码中,我们使用`gopacket.NewPacketSource`函数将打开的设备与`pcap.Handle`对象关联起来,然后使用`PacketSource`的`Packets`方法来获取捕获到的数据包。每次从`Packets`方法获取到一个数据包,我们都会对其进行处理,即打印出数据包的序号(用于示例,实际应用中可能需要根据需求进行其他操作)。


#### 数据包分析


在捕获到数据包后,我们可以对其进行分析并提取所需的信息。gopacket库提供了丰富的工具和功能,用于数据包分析。


以下是一些常见的数据包分析方法:


##### 解析以太网帧



ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
if ethernetLayer != nil {
ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
fmt.Println(“Ethernet source MAC:”, ethernetPacket.SrcMAC)
fmt.Println(“Ethernet destination MAC:”, ethernetPacket.DstMAC)
fmt.Println(“Ethernet type:”, ethernetPacket.EthernetType)
}


以上代码演示了如何解析以太网帧中的源MAC地址、目的MAC地址和以太网类型。


##### 解析IP包



ipLayer := packet.Layer(layers.LayerTypeIPv4)
if ipLayer != nil {
ipPacket, _ := ipLayer.(*layers.IPv4)
fmt.Println(“IP version:”, ipPacket.Version)
fmt.Println(“IP source address:”, ipPacket.SrcIP)
fmt.Println(“IP destination address:”, ipPacket.DstIP)
fmt.Println(“IP protocol:”, ipPacket.Protocol)
}


以上代码演示了如何解析IPv4包中的版本、源IP地址、目的IP地址和协议。


##### 解析TCP包



tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer != nil {
tcpPacket, _ := tcpLayer.(*layers.TCP)
fmt.Println(“TCP source port:”, tcpPacket.SrcPort)
fmt.Println(“TCP destination port:”, tcpPacket.DstPort)
fmt.Println(“TCP sequence number:”, tcpPacket.Sequence)
fmt.Println(“TCP acknowledgment number:”, tcpPacket.Acknowledgment)
fmt.Println(“TCP flags:”, tcpPacket.Flags)
}


以上代码演示了如何解析TCP包中的源端口、目的端口、序列号、确认号和标志位。


##### 解析UDP包



udpLayer := packet.Layer(layers.LayerTypeUDP)
if udpLayer != nil {
udpPacket, _ := udpLayer.(*layers.UDP)
fmt.Println(“UDP source port:”, udpPacket.SrcPort)
fmt.Println(“UDP destination port:”, udpPacket.DstPort)
}


以上代码演示了如何解析UDP包中的源端口和目的端口。


##### 解析应用层协议


在数据包的应用层有各种各样的协议,如HTTP、DNS等。gopacket库提供了根据协议类型解析数据包的方法。以下是解析HTTP协议的示例代码:



httpLayer := packet.Layer(layers.LayerTypeHTTP)
if httpLayer != nil {
httpPacket, _ := httpLayer.(*layers.HTTP)
fmt.Println(“HTTP method:”, httpPacket.Method)
fmt.Println(“HTTP host:”, httpPacket.Host)
fmt.Println(“HTTP user-agent:”, httpPacket.UserAgent)
}


以上代码演示了如何解析HTTP包中的方法、主机和用户代理信息。


#### 示例:捕获HTTP请求


现在,我们将结合以上的知识来实现一个简单的示例:捕获HTTP请求,并提取请求的URL和请求头信息。



package main

import (
“fmt”
“log”
“net”
“strings”
“time”

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

)

func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}

handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
	log.Fatal(err)
}
defer handle.Close()

packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
for packet := range packetSource.Packets() {
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		ethernetPacket, \_ := ethernetLayer.(\*layers.Ethernet)

		ipLayer := packet.Layer(layers.LayerTypeIPv4)
		if ipLayer != nil {
			ipPacket, \_ := ipLayer.(\*layers.IPv4)

			tcpLayer := packet.Layer(layers.LayerTypeTCP)
			if tcpLayer != nil {
				tcpPacket, \_ := tcpLayer.(\*layers.TCP)

				httpLayer := packet.Layer(layers.LayerTypeHTTP)
				if httpLayer != nil {
					httpPacket, \_ := httpLayer.(\*layers.HTTP)

					fmt.Println("Source MAC:", ethernetPacket.SrcMAC)
					fmt.Println("Destination MAC:", ethernetPacket.DstMAC)

					fmt.Println("Source IP:", ipPacket.SrcIP)
					fmt.Println("Destination IP:", ipPacket.DstIP)

					fmt.Println("Source Port:", tcpPacket.SrcPort)
					fmt.Println("Destination Port:", tcpPacket.DstPort)

					fmt.Println("HTTP Method:", httpPacket.Method)
					fmt.Println("HTTP Host:", httpPacket.Host)

					headers := strings.Split(string(httpPacket.Headers), "\r\n")
					for \_, header := range headers {
						fmt.Println("HTTP Header:", header)
					}
					
					fmt.Println("--------")
				}
			}
		}
	}

	time.Sleep(1 \* time.Second) // 仅用于示例,避免数据包流量过大
}

}


以上示例代码中,我们使用了嵌套的条件语句来逐级解析数据包的各个层级,并提取所需的信息。其中,我们关注以太网帧、IPv4包、TCP包和HTTP协议,提取了包括源MAC地址、目的MAC地址、源IP地址、目的IP地址、源端口、目的端口、HTTP方法、主机和请求头信息等。


### 案例


#### 案例一:统计流量


我们可以使用抓包技术来统计特定端口的流量。以下示例代码演示了如何捕获HTTP流量,并统计总共传输的数据量:



package main

import (
“fmt”
“log”
“net”
“strings”
“time”

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

)

func main() {
device, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}

handle, err := pcap.OpenLive(device[0].Name, 65536, true, pcap.BlockForever)
if err != nil {
	log.Fatal(err)
}
defer handle.Close()

packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
totalBytes := 0
startTime := time.Now()
for packet := range packetSource.Packets() {
	ethernetLayer := packet.Layer(layers.LayerTypeEthernet)
	if ethernetLayer != nil {
		ethernetPacket, \_ := ethernetLayer.(\*layers.Ethernet)

		ipLayer := packet.Layer(layers.LayerTypeIPv4)
		if ipLayer != nil {
			ipPacket, \_ := ipLayer.(\*layers.IPv4)

			tcpLayer := packet.Layer(layers.LayerTypeTCP)
			if tcpLayer != nil {
				tcpPacket, \_ := tcpLayer.(\*layers.TCP)

				httpLayer := packet.Layer(layers.LayerTypeHTTP)
				if httpLayer != nil {
					httpPacket, \_ := httpLayer.(\*layers.HTTP)

					if tcpPacket.SrcPort.String() == "80" || tcpPacket.DstPort.String() == "80" {
						totalBytes += len(packet.Data())
					}
				}
			}

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

ata())
}
}
}

[外链图片转存中…(img-RJiZhDLe-1715837051744)]
[外链图片转存中…(img-D59Awg80-1715837051744)]
[外链图片转存中…(img-usRH4Qq1-1715837051744)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值