目录 [−]
原文: Packet Capture, Injection, and Analysis with Gopacket by John Leon。
最近准备使用 gopackage 写个工具,搜索了相关的资料,这篇文章是值的推荐的一篇介绍 gopackage的文档,所以动手翻译了一下。
gopacket包为用C编写的libpcap提供了一个go包装器(译者按: 不仅如此,现在gopackage有多种捕获包的binding方式,比如PF_RING,AF_PACKET等),但它不仅仅是一个简单的包装器。它提供了额外的功能,并利用了Go之类的接口,这使得它非常强大。
作者在写这篇文章的时候,在Denver GopherCon 2016 大会上分享了相关的技术,有兴趣的同学可以观看: GopherCon 2016: John Leon - Packet Capture, Analysis, and Injection with Go
开始之前
安装必需的库。你需要go
,libpcap
和gopacket
包。因为gopacket是在libpcap之上构建的,所以我强烈建议您了解该libpcap库是如何工作的。你可以学习如何在C语言中使用libpcap来加深理解。这些示例应该在使用libpcap的Linux/Mac和使用winpcap的Windows上工作。如果出现错误(如cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
),可能需要设置GOARCH=386
。
|
|
你可能还想签出gopacket project, 查看它的godoc文档。
查找设备
|
|
打开一个设备进行实时捕获
|
|
写入到pcap文件
为了写入到pcap格式的文件中,我们需要gopacket/pcapgo
,它包含一个Writer
,还有两个有用的辅助函数:WriteFileHeader()
和 WritePacket()
。
|
|
打开pcap文件
除了打开一个设备实时捕获以外,我们还可以读取pcap文件进行离线分析。你可以通过tcpdump捕获一个文件来测试。
|
|
打开这个文件,遍历其中的packet:
|
|
设置过滤器
下面的代码仅仅返回端口80上的packet:
|
|
解码packet的各层
我们可以获取原始数据包,并尝试将其强制转换为已知格式。它与不同的层兼容,因此我们可以轻松访问ethernet、IP和TCP层。layers
包是gopacket的Go库中的新功能,在底层libpcap库中不存在。它是gopacket库的非常有用的一部分。它允许我们轻松地识别数据包是否包含特定类型的层。这个代码示例将演示如何使用layers包来查看包是否是ethernet、IP和TCP,以及如何轻松访问这些头中的元素。
找到payload
(有效载荷)取决于涉及的所有层。每个协议都是不同的,必须相应地进行处理。这就是layers包的强大之处。gopacket的作者花了很多时间为许多已知层(ethernet、IP、UDP和TCP)创建layer类型。其中payload
(有效负载)是应用程序层的一部分。
|
|
创建和发送packet
下面这个例子做了几个事情。首先,它将演示如何使用网络设备发送原始字节。这样,您就可以像串行连接(serial connection
)一样使用它来发送数据。这对于真正的低层的数据传输很有用,但是如果你想与一个应用程序交互,你可能想建立硬件和软件都能识别的包。
接下来,它将演示如何使用ethernet、IP和TCP层创建数据包。所有的东西都是默认的和空的,所以它实际上不做任何事情。
为了完成它,我们创建了另一个数据包,但实际上为ethernet层填充了一些MAC地址,为IPv4填充了一些IP地址,为TCP层填充了一些端口号。您应该看到如何用它伪造数据包和模拟设备。
TCP层结构具有可读取或设置的SYN, FIN, and ACK 布尔标志。这有利于控制和模糊TCP握手、会话和端口扫描。
pcap库提供了一个发送字节的简单方法,但是gopacket中的layers包帮助我们为各个层创建字节结构。
|
|
更多创建和解码packet的例子
|
|
定制层
下一个程序将演示如何创建您自己的层。这有助于实现当前不包含在gopacket layers包中的协议。如果您想创建自己的l33t
协议,甚至不使用TCP/IP或ethernet,那么它也很有用。
|
|
更快的解码packet
如果我们知道需要什么层,我们可以使用已有的结构来存储packet信息,而不是为每个packet创建新的结构,既浪费内存又浪费时间。使用DecodingLayerParser
可以更快一点。这就像marshalling/unmarshalling数据一样。
|
|
TCP流重组
gopacket提供了Flow
、Endpoint
类型,我没有深入了解这些类型,但是官方文档使用它发送特定的TCP流到一个channel中,参看very deeply but the documentation has an example of using it to send specific TCP streams to a channel of packets. GoDoc gopacket basic usage
更多的信息可以查看官方项目和godoc。