在Linux上探测TCP的内部状态

发现一篇使用ss获取TCP内部状态信息的好文,不由的记录一笔。
并结合之前会的方法适当总结总结。


Inspecting Internal TCP State on Linux

这种好文当然是推荐去读原文了,这里对文章中的方法只做简单摘要。
而这类相似方法还有哪些,以及各自的优缺点可以看看下一节的总结。

// 可查看尽量多的显示socket相关的内部信息  
# ss -eipn  

Internally, ss uses the tcp_diag kernel module to extract
information (this is done via an AF_NETLINK socket).

// 通过crash根据sk的内存地址,获取更多的sk结构体item信息
# sudo crash -e emacs

crash > struct tcp_sock.rcv_nxt,snd_una,reordering ffff8802305a0800

总结

目前掌握的获取TCP内部状态的方法,这里讨论的方法都是不需要额外在内核中做开发的:
a. 使用tcp_probe内核模块
改改tcp_probe几乎可以获取TCP内部的任何状态
具体怎么使用tcp_probe模块,在之前的这篇博客中有详细的介绍。

优点(考虑适当自定制该模块):
    1. 功能性:可查看TCP流的几乎所有的内部状态
    2. 灵活性:定制一次必须重编一次模块
缺点:
    1. 功能性:不适合线上设备使用,大量不同流的信息混在一起简直是灾难(如何有效的使用过滤策略是一个好问题)
    2. 可用性:如果没有kernel-devel包,无法自定制编译使用内核模块

b. 使用systemtap脚本

优点:
    1. 功能性:几乎可以探测TCP流在任何处理逻辑(内联函数是一个痛点)处的信息
    2. 灵活性:方便设置过滤策略,(相对tcp_probe而言)可方便的统计出想要的信息。
       不管是通过指定脚本参数,还是直接修改脚本,都比修改tcp_probe内核模块方便
缺点:
    1. 可用性:依赖kernel-devel, kernel-debuginfo, kernel-debuginfo-common包
       而为了避免暴露自定制内核的内部实现,这些包默认都是不安装的

c. ss+crash
如果只需要ss默认支持的信息,那这种方法当然是最佳的。
但可信的就是ss默认支持的信息,还是太少,因此可能需要crash来补充

优点:
    1. 功能性:在仅需要ss默认支持的信息时,最实用。只要安装ss软件即可
       本质上ss输出的信息,是内核统计的,ss只是一个输出工具而已
缺点:
    1. 功能性:受限于内核统计的信息,受限与ss工具的选择的输出信息
    2. 可用性:如果试图通过ss得到的sk内存地址,利用crash进一步获得信息,则需要内核image能找到。
       这点在线上设备上也显然是不现实的

不过受ss+crash这种方法的启发,既然能拿到sk结构体的内存地址,有没有更简单,
方便的方法来获取sk内部item的值呢?
如果大家有更好的方法,非常欢迎留言交流。