1

I want to use dtrace to show information about tcp connect, accepts, and data sends...but i also want to show port and ip information.

Is there a way of doing this on osx? I notice that osx does not have a TCP provider (unlike solaris), but is there another way of doing it?

horseyguy
  • 29,455
  • 20
  • 103
  • 145
  • Hey guy who voted to close this as 'not being about programming' - look at bullet point 3 of the list: "software tools commonly used by programmers" --- voting to close because i'm asking about dtrace, is like voting to close for someone asking about gdb! – horseyguy Mar 18 '18 at 03:51

1 Answers1

3

OSX does have a TCP provider. Here's how to confirm:

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

The following DTrace script has been tested on macOS 10.13 High Sierra and 10.12 Sierra.

Invoke like so:

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");
}

Output:

  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)

Some suggestions for how to extend it:

Add a filter /execname == $1/ onto each of the three blocks tcp:::send, tcp:::receive, tcp:::send, tcp:::receive.
This lets you filter by process name:

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

Add a filter /progenyof($target) || pid == $target/ onto each of the three blocks tcp:::send, tcp:::receive, tcp:::send, tcp:::receive.
This lets you filter by PID:

pgrep 'pritunl-openvpn' | xargs -n 1 sudo ./tcpsnoop3.d 2>/dev/null -p
Birchlabs
  • 7,437
  • 5
  • 35
  • 54
  • This is great! How do i do the same for UDP? just using `udp::send` doesn't work :( – horseyguy Apr 10 '20 at 16:12
  • This tcp provider doesn't appear to exist in 10.14 any more. – Matt Jun 05 '20 at 02:30
  • Unless it's something to do with "system integrity protection"? dtrace seems to report it's status a lot now – Matt Jun 05 '20 at 02:33
  • Yep, most dtrace functionality is borked now unless you [disable SIP](https://8thlight.com/blog/colin-jones/2017/02/02/dtrace-gotchas-on-osx.html) – Matt Jun 05 '20 at 02:40