用 LD_PRELOAD 写魔法程序

💡 原文中文,约6600字,阅读约需16分钟。
📝

内容提要

作者利用 MTR 工具排查网络问题,开发了一个平台查询 IP 对应设备。通过 LD_PRELOAD 技术自定义 getnameinfo 函数,使 MTR 直接显示设备名称。尽管遇到日志打印和 Golang 程序死锁等问题,最终成功实现功能并发布。

🎯

关键要点

  • 作者使用 MTR 工具排查网络问题,开发了一个平台查询 IP 对应设备。
  • 通过 LD_PRELOAD 技术自定义 getnameinfo 函数,使 MTR 直接显示设备名称。
  • MTR 支持 DNS PTR 反查,但内网 DNS 没有支持 PTR 记录。
  • 使用 LD_PRELOAD 技术可以自定义 getnameinfo 函数的行为。
  • 编写了简单的 C 语言程序验证 LD_PRELOAD 的可行性。
  • 使用 Go 语言实现逻辑,但遇到日志打印和程序死锁等问题。
  • 解决日志打印问题的方法是将日志输出到 stderr。
  • Golang 程序在 fork 后出现死锁问题,最终用 C 语言实现逻辑解决了问题。
  • 将程序打包成 deb 包发布到内网中,推荐使用 nfpm 工具。

延伸问答

如何使用 LD_PRELOAD 技术自定义 getnameinfo 函数?

可以通过编写一个共享库,重写 getnameinfo 函数,并在运行时使用 LD_PRELOAD 环境变量加载该库,从而实现自定义功能。

MTR 工具的主要功能是什么?

MTR 工具结合了 traceroute 和 ping,可以快速显示网络包的路径及其丢包和延迟情况。

在使用 Golang 实现逻辑时遇到了哪些问题?

遇到了日志打印问题和程序死锁问题,特别是在 fork 后导致的 Goroutines 死锁。

如何解决 MTR 中的日志打印问题?

将日志输出到 stderr,而不是文件,以避免在 fork 后关闭文件描述符导致日志丢失。

为什么内网 DNS 不支持 PTR 记录会影响 MTR 的功能?

因为 MTR 依赖 DNS PTR 记录来显示设备名称,内网 DNS 不支持此记录会导致无法获取设备名称。

如何将程序打包成 deb 包?

可以使用 nfpm 工具来打包程序为 deb 包,nfpm 使用起来相对简单。

➡️

继续阅读