Golang案例开发之gopacket监听网卡抓包(2)

文章目录


前言

本节实战,监听指定网卡,进行网络抓包,根据分层,解析不同分层包的内容。


二、实践 监听网卡抓包

1.代码

代码如下(示例):

go 复制代码
package main

import (
	"fmt"
	"log"
	"strings"
	"time"

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

// 监听 ens33 网卡上的  目标端口 5100的 TCP包

func main() {

	handler, err := pcap.OpenLive("ens33", 1024, false, time.Second*5)
	if err != nil {
		log.Fatal(err)
	}
	defer handler.Close()

	var filter string = "tcp port 5100"
	handler.SetBPFFilter(filter)
	source := gopacket.NewPacketSource(handler, handler.LinkType())
	for packet := range source.Packets() {
		// fmt.Printf("%v", packet.String())
		printPacketInfo(packet)
	}
}

// 根据网络层级,输出信息
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()
	}

	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer != nil {
		fmt.Println("IPv4 Layer detected")
		if ip, ok := ipLayer.(*layers.IPv4); ok {
			fmt.Printf("From %s to %s \n", ip.SrcIP, ip.DstIP)
			fmt.Println("Protocol", ip.Protocol)
		}
	}

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

}

2.知识点

OpenLive方法

go 复制代码
func OpenLive(device string, snaplen int32, promisc bool, timeout time.Duration) (handle *Handle, _ error)

参数说明:

  • device:要打开的网络接口名称,例如"eth0"、"en0"等。
  • snaplen:要捕获的数据包最大长度,通常设置为65535以便捕获完整的数据包。
  • promiscuous:是否启用混杂模式,即接收所有经过网络接口的数据包,默认为false。
  • timeout:超时时间,表示在没有新数据包到达时等待多久,默认为无限等待。

返回值:handle *Handle error

SetBPFFilter

支持通过handle.SetBPFFilter 方式这是过滤器。

filter的规则和tcpdump的用法类似。

断言

在Go语言中,断言(assertion)是一种重要的机制,它用于判定某个条件是否为真,并在条件不满足时触发相应的操作。

断言的语法格式如下:

bash 复制代码
value, ok := x.(T)

上文中的几处都用到了断言

bash 复制代码
ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
ip, ok := ipLayer.(*layers.IPv4)
tcp, _ := tcpLayer.(*layers.TCP)

总结

本节内容,对gopacket抓包有了一个初步的认识,后期我们需要优化工具。

相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
虎头金猫2 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
伞伞悦读2 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
ttwuai2 天前
Go开源后台管理系统推荐:怎么按技术栈和边界比较4个官方仓库?
golang·gin
大勇前进2 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu2 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端