pwru 工具介绍和案例一则

pwru1 是排查 Linux 网络问题最好的工具,全称是 Packet where are you?

它是怎么工作的呢?

eBFP 可以让我们往 kernel 的函数上添加 hook,当这个 kernel 函数执行的时候,我们可以通过 eBPF 定义一些额外的动作,比如把这个函数和它的参数记录下来然后打印出来。

Linux 启动的时候,会生成 /proc/kallsyms,pwru 通过读取这个文件,找到所有和 skb (网络包在内核中的数据结构)相关的函数,然后 hook 这些函数。这样,在这个包在内核栈经过的路径,就可以用 eBPF 追踪到了2 3

通过这种方法,pwru 几乎可以解决在 Linux 上遇到的任何网络不通的问题,因为通过函数路径可以很快确定这个包经过了哪些函数处理,没有走到哪些函数。对照函数查看源代码,就可以知道原因了。

它的安装方法很简单:apt install pwru 即可4

然后通过 pwru icmp and dest host 1.1.1.1 就可以开始追踪了。包的过滤语法和 tcpdump 一样。

案例分享

今天遇到的问题,还是网络在 Linux 上网络不通了,网络结构很简单,就是默认路由到一个 vxlan driver 的 interface,经过这个 interface 封装,然后通过物理 interface 发送出去。这种网络不通的问题最适合用 pwru 定位了,这个工具可以直接告诉我们包在 Linux 网络栈经过的代码路径。

我们用以下命令来抓这个包,pwru --filter-track-skb --all-kmods dst 10.1.1.100,得到的输出如下:

pwru 抓包的输出

可以看到数据包的确被 Drop 了,虽然原因是 SKB_DROP_REASON_NOT_SPECIFIED,但是不要紧,我们可以看到 drop 之前的函数是 vxlan_get_route。然后就可以去查看对应的 Linux 源代码5

从源码中可以确认,这个 vxlan_get_route 函数返回错误的原因有 2 个:

  • 一个是 vxlan 封包之后使用的 dev 和现在一样,那就是出现环路了,会导致一直封包一直循环;
  • 另一个就是没有路由;

按照包的封装过程查看 ip route,发现确认有一条多加的路由导致环路了,删除即可恢复。

如果没有 pwru 的话,就得依靠网络的经验逐个地方检查,然后判断出来是路由表配置问题。但是有了 pwru,就可以顺藤摸瓜得排查到根因。

  1. https://github.com/cilium/pwru ↩︎
  2. https://cleveruptime.com/docs/files/proc-kallsyms ↩︎
  3. https://github.com/cilium/pwru/blob/db786876d10bc104be1a7908e13902c890e548d0/internal/pwru/ksym.go#L45 ↩︎
  4. 这个是我司在内网打包的,公网不能这么安装,用户需要按照 Github 的文档来安装。 ↩︎
  5. 相应的代码地址:https://elixir.bootlin.com/linux/v5.15.178/source/drivers/net/vxlan/vxlan_core.c#L2428 ↩︎


Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注