在 go 中从 nftables nflog 获取 MAC 地址

问题描述 投票:0回答:0

我想将我的 netfilter 日志推送到 Grafana Loki 但我无法在 ulogd 和 promtail 之间获得我喜欢的格式,所以我决定 自己写 小实用程序来为我完成这项工作。它工作得很好,除了一件事:我希望能够在输出中获得 MAC(硬件)地址。

我尝试了一些东西,并做了一些观察。首先是,如果我尝试同时解析整个数据包堆栈的日志消息,那是行不通的。在此示例中,“协议”包含以太网、IPV4、TCP4 和 UDP4。当我这样解析它时:

p.decoder = gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, protocols...)

我得到的结果只有一层——以太网——而且是假的。它没有显示错误,但它报告的地址与实际情况不符。如果我从 IP 开始:

p.decoder = gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, protocols...)

然后 IP 被解码,以及上面的任何其他内容(通常是 TCP、UDP 或 ICMP)。

返回的Attributes包括一个叫做HwAddr的东西。这是一串字节,确实看起来像 source MAC 地址,这很好 - 但我想要两个,分别。

如果你直接使用ulogd,它可以看到这些东西。它实际上报告了三件事:

  • MAC = 12 字节的字符串,目标 MAC 后跟源 MAC
  • 字段 mac.saddr.str
  • 字段 mac.daddr.str

ulogd 非常复杂,我很难理解它是从哪里得到这些的。但是,它得到它们的事实让我认为以太网层是由 netfilter 通过的,即使我的规则专门针对 ipv4 或 ipv6。至少,我是这样解释的。

所以我的问题实际上是关于如何将这两个东西连接在一起以获得链路层标头:我认为 gopacket 应该能够解释这些东西,但是来自 nflog 的“以太网”消息与 gopacket 期望的不兼容查看。有没有人成功地将这两件事联系在一起?

更新:为了看看我是否走在正确的轨道上,我遵循了对该问题的评论中的建议。我所做的是转储通过 netlink 套接字发送回给我的原始有效载荷。这是一个例子:

[ 69 0 0 52 197 128 64 0 127 6 65 221 192 168 1 134 129 21 x y

这是通过 netlink 套接字返回的“attribute.Payload”字段,通过这样做我现在可以清楚地看到它是 IP 标头。换句话说,我正在尝试解码不存在的标头。解码以上内容:

version=69
tos=0
length=52,1
id=97,128
offset+flags=64,0
ttl=127
proto=6
hdr_checksum=65,221
src=192 168 1 134
dst=129 21 x y

所以我猜它不存在,这可以解释为什么我无法解码它。

go netfilter netlink gopacket
© www.soinside.com 2019 - 2024. All rights reserved.