用Go实现网络流量解析和行为检测引擎

1.前言

最近有个在学校读书的迷弟问我:大德德, 有没有这么一款软件, 能够批量读取多个抓包文件,并把我想要的数据呈现出来, 比如:源IP、目的IP、源mac地址、目的mac地址等等。我说:“这样的软件你要认真找真能找出不少开源软件, 但毕竟没有你自己的灵魂在里面,要不咱自己用Go实现一个吧”, OK , Let's go。

2.摘要

能够实现网络协议解析和分析的工具有很多,最有名使用最多的是基于图形化界面的Wireshark, 除了能够实现网络实时抓包,还能够离线分析Pcap包文件, 虽然它通常用于手动分析网络数据包, 但也支持自动化脚本和插件来提取元数据。而Wireshark还有一个基于命令行版本的Tshark, 可以用于自动化任务, 可以批量处理Pcap文件, 提取所需数据并导出到文件中。

本次用Go语言实现的网络协议解析功能是基于Google公司开发一个开源库:gopacket, 该库帮我们完成了网络协议的一些底层封装, 它允许我们能够捕获、解析和处理网络数据包, 与Wireshark一样,也支持对离线抓包文件的分析。gopacket库提供了一系列功能,包括:数据包捕获、解析和构建, 以及对多种协议的支持,如:Ethernet、IP、TCP、UDP、HTTP等。它还提供了方便的API, 以帮助开发者操作和分析网络数据包。

3.实现原理

谷歌公司开发的gopacket提供了5个子包接口供使用者调用,其中Layers子包负责协议解析;pcap子包实际是libpcap的包装,主要用于数据包格式解析;pfring子包和afpacket用于快速数据库包抓取;tcpassembly用于TCP流重组。 在本篇文章中,主要利用gopacket提供的Layers和pcap接口实现上层业务逻辑。在流量解析引擎中,调用pcap接口对离线pcap抓包文件进行数据包解析,并配合Layers接口实现协议解析,目前根据业务种类,实现的协议解析包括:HTTP协议、TCP/UDP协议、ICMP协议和802.11协议。流量解析引擎的整体架构如下:

我们实现的流量解析引擎主要针对离线pcap包文件, 支持的协议类型包括:HTTP协议、TCP/UDP协议、ICMP协议、802.11(无线协议)

,通过对各类协议的解析,可以实现一些高级功能,例如: 特征库匹配、漏洞扫描检测、一些网络攻击检测等等。

通过对gopacket开源包的研究,整理出其使用方法如下:

  • 利用pcap子包的OpenOffline方法加载离线数据包文件,加载成功返回离线数据包文件句柄。

  • 离线包文件句柄通过SetBPFFilter方法过滤数据类型,调用LinkType()方法获取链路类型。

  • 将第2步中的文件句柄和LinkType作为参数调用方法NewPacketSource。

  • NewPacketSource调用Packet()方法获取离线包文件中所有的数据包,通过遍历每个数据包进行下一步操作。

  • 每个数据包对象通过调用Layer()方法获取数据对象层,参数为数据对象的种类,种类有很多种,根据不同的协议类型进行区分。

  • 获取的数据层级操作对象是数据包解析基础方法需要达到的目的,即将解析的具体数据将在数据层级中进行不同方法的筛选。

大致的调用关系整理如下图:

4.功能代码实现

在我们的工程项目中,首先要引入三个包,它们是:

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

因为我们操作的对象主要是针对离线pcap包, 因此首先要加载离线包文件,代码如下:

handle, err = pcap.OpenOffline(pcapFilePath)
if err != nil {log.Panic(err)
}

handle是加载离线包文件后返回的文件句柄,类型为:*pcap.Handle,接下来我们要设置一下过滤,只针对tcp连接的包,所以通过上面的文件句柄调用过滤函数:

err = handle.SetBPFFilter("tcp")if err != nil {log.Panic(err)
}

根据上面的调用关系图,我们需要调用NewPacketSource方法,代码如下:

packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packets := packetSource.Packets()

packetSource.Packets()方法返回的是一个通道, 用来接收gopacket解析出来的每一个数据包,

因此这里需要做循环接收,并在循环内容解析ethernet层, 解析大致过程如下:

下面我们根据上面的流程图解析LayerTypeEthernet, 代码如下:

for packet := range packetSource.Packets() {ethernetLayer := packet.Layer(layers.LayerTypeEthernet)if ethernetLayer == nil {continue}ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)
}

下面涉及到协议的层级,我们对照Wireshark的包对比看一下,如图:


从上图的协议结构中我们可以看到,源IP地址和目的IP地址是在IPv4层上, 源端口和目的端口是在TCP层上, 而mac地址是在Ethernet层上, 因此要想获取这6个元数据,我们至少要解析三层协议, 添加以下代码:

for packet := range packetSource.Packets() {ethernetLayer := packet.Layer(layers.LayerTypeEthernet)if ethernetLayer == nil {continue}ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)if ethernetPacket.EthernetType.String() == "IPv4" {ipLayer := packet.Layer(layers.LayerTypeIPv4)if ipLayer == nil { continue }// 这里从IPv4协议层取源IP和目的IP数据ipInfo, _ := ipLayer.(*layers.IPv4)tcpLayer := packet.Layer(layers.LayerTypeTCP)if tcpLayer == nil { continue }// 这里从TCP协议层取TCP数据,获取源端口和目的端口数据tcpInfo, _ := tcpLayer.(*layers.TCP)//下面的代码取具体的PayloadapplicationLayer := packet.ApplicationLayer()if applicationLayer == nil { continue }payload := string(applicationLayer.Payload())// 从GET或POST请求中取出元数据if strings.HasPrefix(payload, "GET") || strings.HasPrefix(payload, "POST") {fmt.Println("源mac地址:", ethernetPacket.SrcMAC.String())fmt.Println("目的Mac地址:", ethernetPacket.DstMAC.String())fmt.Println("源IP地址:", ipInfo.SrcIP.String())fmt.Println("目的IP地址:", ipInfo.DstIP.String())fmt.Println("源端口:", int(tcpInfo.SrcPort))fmt.Println("目的端口:", int(tcpInfo.DstPort))}}
}

5.行为检测实现

这里我们以检测数据库的匿名登录行为为例子, 首先在kali系统上对目标数据库尝试匿名登录,如图:

在登录过程中,使用Wireshark进行网络抓包,如图:

从上面的抓包文件中,我们可以根据Payload偏移提取一些行为特征,例如:

将特征检测的逻辑加入到代码中:

for packet := range packetSource.Packets() {ethernetLayer := packet.Layer(layers.LayerTypeEthernet)if ethernetLayer == nil {continue}ethernetPacket, _ := ethernetLayer.(*layers.Ethernet)if ethernetPacket.EthernetType.String() == "IPv4" {ipLayer := packet.Layer(layers.LayerTypeIPv4)if ipLayer == nil { continue }// 这里从IPv4协议层取源IP和目的IP数据ipInfo, _ := ipLayer.(*layers.IPv4)if ipInfo.Protocol.String() == "TCP" {tcpLayer := packet.Layer(layers.LayerTypeTCP)tcp, _ := tcpLayer.(*layers.TCP)if (len(tcp.Payload) > 36 && bytes.Equal(tcp.Payload[13:37], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})) || (len(tcp.Payload) > 39 && bytes.Equal(tcp.Payload[13:40], []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 111, 111, 116})) {fmt.Println("发现数据库匿名登录行为!")}}}
}

将上面的代码编译后加载离线pcap包跑一下,可以看到已经匹配到行为特征,如图:

可以看到,已经成功命中行为特征。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/186697.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在Android平板上远程连接Ubuntu服务器code-server进行代码开发?

文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以,这里以VMwhere ubuntu系统为例 下载code serve…

解析虚拟文件系统的调用

Linux 可以支持多达数十种不同的文件系统。它们的实现各不相同,因此 Linux 内核向用户空间提供了虚拟文件系统这个统一的接口,来对文件系统进行操作。它提供了常见的文件系统对象模型,例如 inode、directory entry、mount 等,以及…

关于 国产系统UOS系统Qt开发Tcp服务器外部连接无法连接上USO系统 的解决方法

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134254817 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

【中间件篇-Redis缓存数据库03】Redis高级特性和应用(发布 订阅、Stream)

Redis高级特性和应用(发布 订阅、Stream) 发布和订阅 Redis提供了基于“发布/订阅”模式的消息机制,此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道( channel)发布消息,订阅该频道的每个客户端都可以收到该消息。 …

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装

R | R包安装报错-github连接速度慢或无法访问 | metaboanalystR | Retip | rJava安装 一、metaboanalystR 安装1.1 Bioconductor报错,无网络连接1.2 github520-修改hosts文件 二、retip安装2.1 rJava包加载报错及安装2.2 安装Retip包 三、从Bioconductor安装Rdisop报…

LeetCode【78. 子集】

78. 子集 中等 2.2K 相关企业 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums [1,2,3] 输出&…

Python 实践

文章目录 一、HttpRequests 一、Http Requests python——Request模块

IntelliJ IDEA - Git Commit 后 Commit 窗口不消失解决方案

这个现象是在 2023 年版本后开始的,一开始以为是 Mac 系统的原因,后来发现原来 Windows 也这样,所以应该只跟 IDEA 版本有关 可以看到左侧 commit 后,这个侧边栏还在,按理讲在以前的版本是之前消失,这样使…

kotlin 基本语法

const val INFO "ZZZ is Success Result" fun main(){ var name: String? "zzz" name null name?.capitalize() //?问号的意思是如果name是null ,后面的方法不执行,如果name不是null,后面方法执行 var name: String? &q…

Linux安装MySQL8.0服务

Linux安装MySQL8.0服务 文章目录 Linux安装MySQL8.0服务一、卸载1.1 查看mariadb1.2 卸载 二、安装2.1 下载2.2 上传2.3 解压2.4 重命名2.5 删除2.6 创建目录2.7 环境变量2.8 修改配置2.9 配置文件2.9 用户与用户组2.10 初始化2.11 其它 三、开启远程连接MySQL 一、卸载 首先第…

Fabric: 使用InvokeChaincode实现跨通道数据访问

因为工作中遇到一些问题考虑使用Fabric的跨通道链码调用方法InvokeChaincode()来解决,这篇文章主要是记录以下在Fabric测试网络中InvokeChaincode()的使用过程及遇到的问题。 1 前期准备 1.1 认识InvokeChaincode InvokeChaincode的作用是调用指定的链码。而被调用…

C++之旅(学习笔记)第6章 基本操作

C之旅(学习笔记)第6章 基本操作 6.1 基本操作 class X{ public:X(Sometype); // "普通的构造函数": 创建一个对象X(); // 默认构造函数X(const X&); // 拷贝构造函数X(X&&); // 移动构造函数X& operator(const …

微信小程序将后端返回的图片文件流解析显示到页面

说明 由于请求接口后端返回的图片格式不是一个完整的url,也不是其他直接能显示的图片格式,是一张图片 后端根据模板与二维码生成图片,返回二进制数据 返回为文件流的格式,用wx.request请求的时候,就自动解码成为了下面这样的数据数据格式,这样的数据没…

Go-服务注册和发现,负载均衡,配置中心

文章目录 什么是服务注册和发现技术选型 Consul 的安装和配置1. 安装2. 访问3. 访问dns Consul 的api接口go操作consulgrpc下的健康检查grpc的健康检查规范动态获取可用端口号 负载均衡策略1. 什么是负载均衡2. 负载均衡策略1. 集中式load balance2. 进程内load balance3. 独立…

SOLIDWORKS软件提供了哪些特征造型方法?硕迪科技

SOLIDWORKS作为一款三维设计软件,为用户提供了多种特征造型方法,以下是其中几种常用的: 实体建模特征:SOLIDWORKS使用实体建模技术来创建和编辑三维几何体。通过使用基本几何体(如立方体、圆柱体、圆锥体等&#xff09…

计算机视觉驾驶行为识别应用简述

一、什么是计算机视觉识别? 计算机视觉识别是一种基于图像处理和机器学习的人工智能应用技术,可以用于多个场景。常见应用场景包括人脸识别、场景识别、OCR识别以及商品识别等。今天以咱们国产系统豌豆云为例,为大家梳理一下在车辆驾驶行为中…

docker部署redis6

前言:在离线服务器上(无联网),部署redis的方式,采用docker是比较方便的。下面将描述如何使用docker部署单机版redis 环境:centos 7 redis:6.2.14 docker:20.10.9 1.下载 redis 镜像…

工业相机基本知识理解:工业相机IO接口,功耗和供电方式

I-input 相机接收外部信号,可用于触发相机(硬触发),也可用于定制不同的 功能,例如使用不同信号宽度来改变相机的曝光时间。主要用于现场设 备控制相机使用,常常配合各种传感器使用 O-output 相机输出信号&a…

单链表(增删改查)【超详细】

目录 单链表 1.单链表的存储定义 2.结点的创建 3.链表尾插入结点 4.单链表尾删结点 5.单链表头插入结点 6.单链表头删结点 7.查找元素,返回结点 8.在pos结点前插入一个结点 ​编辑 9.在pos结点后插入一个结点 10.删除结点 11.删除pos后面的结点 12.修改…

一文读懂RestCloud AppLink

RestCloud AppLink是什么? RestCloud AppLink 是一种应用程序集成解决方案,它提供了一套工具和技术,用于实现不同应用程序之间的无缝集成和交互。平台旨在解决企业中应用程序之间数据孤岛、信息孤立和业务流程不畅的问题,提高企业…