使用 Golang 捕获流量

使用 golang 捕获流量

介绍

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

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

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

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

任务定义

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

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

要求

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

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

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

执行

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

我们将使用这些库:

登录 sloggithub.com/google/gopacket 用于捕获数据包并格式化 pcap 文件格式

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

工作代码

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

package mainimport (    "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 开始他们在这个领域的旅程。

后记

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

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

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

以上就是使用 Golang 捕获流量的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2322365.html

(0)
上一篇 2025年2月28日 18:41:35
下一篇 2025年2月27日 22:08:32

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 使用版本管理和 VS Code 扩展设置 Go

    也可与 mise 和 wsl 配合使用! 来自我在官方 go – vs code extension 存储库中的回答: 对于任何使用mise(以前称为rtx)的人来说,解决方案是指向mise where go 或which go…

    2025年2月28日
    200
  • Golang 函数如何实现反射?

    反射是 golang 中检查和操作函数的功能,它允许在运行时获取函数类型信息、调用函数、修改参数和返回结果。具体操作步骤包括:获取函数类型信息:使用 reflect.typeof() 函数。调用函数:使用 reflect.value.cal…

    2025年2月28日
    200
  • Golang 函数的返回值如何声明和使用?

    Go 函数的返回值:声明和使用 在 Go 中,函数可以返回多个值,通过在函数签名中声明它们来实现。返回值的类型必须明确指定,就像参数的类型一样。 声明返回值 使用 func 关键字声明函数时,返回值可以放在括号中的参数列表后面。每个返回值的…

    2025年2月28日
    200
  • Golang 函数和 method 的区别

    go 函数和方法的区别在于:接收者:函数无接收者,方法有特定接收者类型。可访问性:函数从任何地方可访问,方法仅从接收者类型及其子类型可访问。调用方式:函数直接调用,方法通过接收者值调用。 Go 函数与方法的区别 在 Go 语言中,函数和方法…

    2025年2月28日
    200
  • 如何使用 Golang 函数指针

    函数指针是 go 中允许将函数作为值处理的类型,具有创建、分配和调用函数指针的功能。它们用于映射操作,例如将 slice 中的每个元素传递给函数指针以执行特定操作。函数指针提升了代码的可重用性和可测试性,是函数式编程的利器。 使用 Gola…

    2025年2月28日
    200
  • golang框架的代码生成器如何在大型项目中应用

    代码生成器在大规模 go 项目中的应用代码生成器在大型 go 项目中提供优势,包括:提高开发效率提高代码质量确保代码与契约一致 Go 框架的代码生成器在大型项目中的应用 代码生成器是根据预定义的模板自动生成代码的工具。在大型项目中,它们可用…

    2025年2月28日
    200
  • Golang 函数是如何声明和调用的?

    go 中函数声明使用 func 关键字,签名包括参数类型和返回值类型。函数调用时按函数名和参数顺序进行,返回值可存储于变量或直接使用。实战案例中,add 函数实现了两个整数相加并打印结果。 Go 中函数的声明和调用 函数声明 Go 中的函数…

    2025年2月28日
    200
  • 如何在 Golang 函数中处理错误

    如何在 Go 函数中处理错误 在 Golang 中,函数可以通过返回一个 error 值来指示错误情况。如果不处理错误,它将被传播到调用函数的调用者,依此类推,直到最终被处理或到达应用程序的顶级。这对于确保程序在错误发生时不会无声失败至关重…

    2025年2月28日
    200
  • Golang 函数如何实现接口?

    go 中的函数可以通过实现接口来提供访问特定行为的方式,而无需修改函数本身,增强代码的灵活性。函数实现接口的方法必须与接口定义的签名完全匹配。通过使用实现接口的函数,可以计算不同形状的面积和周长,提供更灵活和更可重用的代码。 Go 中函数如…

    2025年2月28日
    200
  • Golang 函数如何进行类型检查?

    go 函数的类型检查验证函数调用与声明的类型是否匹配。类型声明定义函数的参数和返回值类型。类型检查器检查实际参数类型与声明的参数类型是否匹配,并产生不匹配时的编译错误。例如,sumarray 函数计算数组元素的总和,其类型检查验证数组类型为…

    2025年2月28日
    200

发表回复

登录后才能评论