在osx上使用dtrace显示TCP信息的难度

时间:2018-03-18 03:41:18

标签: macos networking tcp tcp-ip dtrace

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

有没有办法在osx上这样做?我注意到osx没有TCP提供程序(与solaris不同),但还有另一种方法吗?

1 个答案:

答案 0 :(得分:2)

OSX 确实拥有TCP提供商。以下是如何确认:

sudo dtrace -l | perl -pe 's/^.*?\S+\s+(\S+?)([0-9]|\s).*/\1/' | 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)

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

将过滤器/execname == $1/添加到三个块tcp:::sendtcp:::receivetcp:::send, tcp:::receive中的每一个块上。
这允许您按进程名称进行筛选:

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

将过滤器/progenyof($target) || pid == $target/添加到三个块tcp:::sendtcp:::receivetcp:::send, tcp:::receive中的每一个块上。
这允许您按PID过滤:

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