0

0

使用 Golang 捕获流量

PHPz

PHPz

发布时间:2024-09-04 18:10:19

|

467人浏览过

|

来源于dev.to

转载

使用 golang 捕获流量

介绍

大多数软件工程界的人都听说过 tc++pdump、wireshark 等
您很可能听说过 tcpdump 团队开发的 libpcap1 库,用于捕获流量并由 wireshark 使用。

这个库1提供了一个灵活的接口来捕获来自网络接口的流量并在代码中处理它。它提供了编写高性能代码的灵活性,并包含根据需要收集所需数据的尽可能多的业务逻辑。

最近我发现了一项任务,收集所需的数据包、分析它们并保存以供将来的手动审核是一个好主意。要手动检查,可以使用 wireshak 加载 pcap 文件并使用漂亮的 ui 手动检查收集的数据包。

最重要的部分,为什么是 go? go 是一种足够简单的语言,可以编写代码并由多个团队成员支持。它比 c 和 c++ 安全得多,并且其他人支持它所需的经验要少得多,而不会出现意外的意外。除非我们没有要求,必须使用很多高性能语言(c、c++、rust 等),否则我更喜欢选择 golang

任务定义

在我们做某事之前,最好先了解一下,我们想要实现什么结果?让我们定义一个简短的要求列表。

立即学习go语言免费学习笔记(深入)”;

要求

为了使实现尽可能简单,我们只定义几个点:

  1. 我们想要收集出站流量
  2. 让我们收集 ipv4 流量
  3. 忽略专用网络流量
  4. 让我们保留 udp 数据包

这些简单的几点足以了解如何使用 golang 的 libpcap1
之后,在此基础上添加什么逻辑就只是想象的问题了。

执行

在开始之前,我们先定义一下代码不适合生产。我们的目标是查看最小的示例并测试它是否运行良好。

我们将使用这些库:

OSPod.CMS专业建站平台
OSPod.CMS专业建站平台

专业级别的大型网站建站产品,JAVA技术的CMS管理系统,ospod提供上百套专业模板供您选择,包括审批工作流,流量统计和流行网络应用,是公司企业建设专业网站的首选产品,也使用于专业建站人士完成复杂网站项目。管理地址cmsadmin登陆用户名:ospod 密码:ospod1234

下载
  1. 登录 slog
  2. github.com/google/gopacket 用于捕获数据包并格式化 pcap 文件格式

未来代码中的接口将是 eth0,即使您的系统很可能会有不同的接口名称。

工作代码

这是带有注释的代码,您可以复制并在自己的环境中尝试。
由于我们使用 libpcap1,我们的应用程序将使用 cgo 并且我们需要从 root 用户运行该应用程序。

package main

import (
    "bytes"
    "log/slog"
    "net"
    "os"

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

const (
    interfacename = "eth0"
    snaplen       = 1500
)

func main() {
    slog.info("running our applicaiton...")

    // get handler attached to an interface.
    handle, err := pcap.openlive(interfacename, snaplen, true, pcap.blockforever)
    if err != nil {
        slog.error("could not openlive", slog.string("err", err.error()))
        os.exit(1)
    }

    iface, err := net.interfacebyname(interfacename)
    if err != nil {
        slog.error("could not openlive", slog.string("err", err.error()))
        os.exit(1)
    }

    // start new source reader.
    source := gopacket.newpacketsource(handle, handle.linktype())

    // this is suppose to be a file writer, but we will use memory, just for simplification.
    filewriter := bytes.newbuffer(nil)
    pcapwriter := pcapgo.newwriternanos(filewriter)
    err = pcapwriter.writefileheader(snaplen, handle.linktype())
    if err != nil {
        slog.error("could not write pcap header", slog.string("err", err.error()))
        os.exit(1)
    }

    // reading packages.
    for packet := range source.packets() {
        // filter by outcoming traffic only.
        // to filter it, we need to compare mac addresses from out interface and source mac.
        // to access a mac address we need to get an ethernet layer.
        layer := packet.layer(layers.layertypeethernet)

        ethernet, ok := layer.(*layers.ethernet)
        if !ok {
            slog.error("could not get ethernet layer")
            continue
        }

        if !bytes.equal(ethernet.srcmac, iface.hardwareaddr) {
            // our interface did not send this packet. it's not outcoming.
            continue
        }

        // now we need to identify ipv4 layer.
        layer = packet.layer(layers.layertypeipv4)

        ipv4, ok := layer.(*layers.ipv4)
        if !ok {
            // it's not ipv4 traffic.
            continue
        }

        if ipv4.dstip.isprivate() {
            // do not collect private traffic.
            continue
        }

        if ipv4.protocol != layers.ipprotocoludp {
            // ignore not udp protocol.
            continue
        }

        err = pcapwriter.writepacket(packet.metadata().captureinfo, packet.data())
        if err != nil {
            slog.error("could not write a packet to a pcap writer", slog.string("err", err.error()))

            continue
        }

        slog.info("stored packet", slog.any("packet", packet))

        // let's collect only 100k bytes, just for example perposes.
        if filewriter.len() > 100000 {
            break
        }
    }

    slog.info("we have successfuly collected bytes", slog.int("bytes", filewriter.len()))
}

运行后,截断的输出如下所示:

2024/08/31 13:35:36 INFO Running our applicaiton...
2024/08/31 13:37:48 INFO Stored packet packet="PACKET: 105 bytes, wire length 105 cap length 105 ..."
...
2024/08/31 13:37:48 INFO Stored packet packet="PACKET: 1291 bytes, wire length 1291 cap length 1291 ..."
2024/08/31 13:37:48 INFO We have successfuly collected bytes bytes=101018

我希望这个最小的例子能够帮助人们使用 go 开始他们在这个领域的旅程。

后记

如果您在日常任务中遇到任何您不知道如何做的新要求。别急着去问周围的人,私信我,自己研究一下。

研究和沟通是解决所有问题的关键。


  1. libpcap 是一个用于网络流量捕获的便携式 c/c++ 库↩

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

174

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

225

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

335

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

193

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

188

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

191

2025.06.17

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

62

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 2.3万人学习

Git版本控制工具
Git版本控制工具

共8课时 | 1.5万人学习

Git中文开发手册
Git中文开发手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号