最全Golang抓包:实现网络数据包捕获与分析_golang pcap,2024年最新太厉害了

img
img
img

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

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

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

解析应用层协议

在数据包的应用层有各种各样的协议,如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())
						}
					}
				}
			}
		}

		elapsed := time.Since(startTime)
		if elapsed.Seconds() >= 10 {
			fmt.Printf("Total Bytes: %d\n", totalBytes)
			break
		}
	}
}

上述代码中,我们在数据包捕获的过程中判断源端口或目标端口是否为80(HTTP默认端口),如果是则统计这些HTTP流量的数据量。我们使用一个计时器来控制统计的时间,示例中设置为10秒。随着流量的捕获,我们将统计的总数据量打印出来。

案例二:HTTP请求重放

我们可以抓取HTTP请求,并将其重放到目标服务器。以下示例代码演示了如何捕获HTTP请求,并将其重放到指定的目标服务器:

package main

import (
	"log"
	"net/http"
	"strings"

	"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)

						if tcpPacket.SrcPort.String() == "80" || tcpPacket.DstPort.String() == "80" {
							method := httpPacket.Method
							url := "http://" + string(ipPacket.DstIP) + string(httpPacket.URL)
							headers := make(http.Header)
							for \_, header := range strings.Split(string(httpPacket.Headers), "\r\n") {
								parts := strings.SplitN(header, ":", 2)
								if len(parts) == 2 {
									headers.Add(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]))
								}
							}

							client := &http.Client{}
							req, err := http.NewRequest(method, url, nil)
							if err != nil {
								log.Fatal(err)
							}
							req.Header = headers

							resp, err := client.Do(req)
							if err != nil {
								log.Fatal(err)
							}

							log.Println("Response:", resp)
						}
					}
				}
			}
		}
	}
}

上述代码中,我们在抓取到HTTP请求后,构造一个新的HTTP请求,其中包括方法、URL、请求头等信息。然后,我们使用http.Client发送这个新的HTTP请求,并打印出服务器的响应。通过这种方式,我们可以捕获并重放HTTP请求。

案例三:网络嗅探器

我们可以使用抓包技术来实现一个简单的网络嗅探器,监控网络通信并输出相关信息。以下示例代码演示了如何实现一个简单的网络嗅探器:

package main

import (
	"fmt"
	"log"
	"net"

	"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)

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

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

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

					fmt.Println("Payload:", string(tcpPacket.Payload))
				}

				udpLayer := packet.Layer(layers.LayerTypeUDP)
				if udpLayer != nil {
					udpPacket, \_ := udpLayer.(\*layers.UDP)

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

					fmt.Println("Payload:", string(udpPacket.Payload))
				}
			}
		}
	}
}

上述代码中,我们在数据包捕获的过程中,获取到IP层和TCP/UDP层的信息,并将其打印出来。通过此网络嗅探器,我们可以实时监控网络通信,并输出重要的数据包信息。

总结

通过使用gopacket库,我们可以轻松地实现网络数据包的抓取和分析。本文介绍了使用Golang实现抓包功能的基本步骤,包括打开网络设备、捕获数据包和数据包分析等。我们还提供了一些常用的数据包分析方法的示例代码,以帮助读者更好地理解数据包的解析过程。

img
img
img

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

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

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

法的示例代码,以帮助读者更好地理解数据包的解析过程。

[外链图片转存中…(img-0c9N4CnM-1715556501499)]
[外链图片转存中…(img-FTJ2XZmf-1715556501500)]
[外链图片转存中…(img-vd8Jvaol-1715556501500)]

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值