osx 上的 dtrace 难以显示 TCP 信息

Difficulty showing TCP information with dtrace on osx

我想使用 dtrace 显示有关 tcp 连接、接受和数据发送的信息...但我还想显示端口和 ip 信息。

有没有办法在 osx 上执行此操作?我注意到 osx 没有 TCP 提供程序(与 solaris 不同),但是还有其他方法吗?

OSX 有 TCP 提供商。确认方法如下:

sudo dtrace -l | perl -pe 's/^.*?\S+\s+(\S+?)([0-9]|\s).*//' | sort | uniq

以下 DTrace 脚本已经在 macOS 10.13 High Sierra 和 10.12 Sierra 上进行了测试。

像这样调用:

sudo ./tcpsnoop.d 2>/dev/null
#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option switchrate=10hz

dtrace:::BEGIN
{
    printf("%6s %20s %15s:%-5s      %15s:%-5s %6s %s\n",
        "TIME", "CMD", "LADDR", "PORT", "RADDR", "PORT", "BYTES", "FLAGS");
}

tcp:::send
{
    this->length = args[2]->ip_plength - args[4]->tcp_offset;
    printf("%6d %20s %15s:%-5d  ->  %15s:%-5d %6d (",
        timestamp/1000, execname, args[2]->ip_saddr,
        args[4]->tcp_sport, args[2]->ip_daddr, args[4]->tcp_dport,
        this->length);
}

tcp:::receive
{
    this->length = args[2]->ip_plength - args[4]->tcp_offset;
    printf("%6d %20s %15s:%-5d  <-  %15s:%-5d %6d (",
        timestamp/1000, execname, args[2]->ip_daddr,
        args[4]->tcp_dport, args[2]->ip_saddr, args[4]->tcp_sport,
        this->length);
}

tcp:::send,
tcp:::receive
{
    printf("%s", args[4]->tcp_flags & TH_FIN ? "FIN|" : "");
    printf("%s", args[4]->tcp_flags & TH_SYN ? "SYN|" : "");
    printf("%s", args[4]->tcp_flags & TH_RST ? "RST|" : "");
    printf("%s", args[4]->tcp_flags & TH_PUSH ? "PUSH|" : "");
    printf("%s", args[4]->tcp_flags & TH_ACK ? "ACK|" : "");
    printf("%s", args[4]->tcp_flags & TH_URG ? "URG|" : "");
    printf("%s", args[4]->tcp_flags & TH_ECE ? "ECE|" : "");
    printf("%s", args[4]->tcp_flags & TH_CWR ? "CWR|" : "");
    printf("%s", args[4]->tcp_flags == 0 ? "null " : "");
    printf("\b)\n");
}

输出:

  TIME                  CMD           LADDR:PORT                 RADDR:PORT   BYTES FLAGS
146791177843                 curl   192.168.232.2:56775  ->    151.101.65.69:80     16172 (SYN)
146791206127                 curl   192.168.232.2:56775  ->    151.101.65.69:80     35052 (PUSH|ACK)
146791390070                 curl   192.168.232.2:56775  ->    151.101.65.69:80     13292 (FIN|ACK)

关于如何扩展它的一些建议:

在三个块 tcp:::sendtcp:::receivetcp:::send, tcp:::receive.
的每个块上添加过滤器 /execname == / 这使您可以按进程名称过滤:

sudo ./tcpsnoop.d 2>/dev/null curl

在三个块 tcp:::sendtcp:::receivetcp:::send, tcp:::receive.
的每个块上添加过滤器 /progenyof($target) || pid == $target/ 这使您可以按 PID 过滤:

pgrep 'pritunl-openvpn' | xargs -n 1 sudo ./tcpsnoop3.d 2>/dev/null -p