ネットワーク2
DTraceを使うとネットワーク通信に関するデータを簡単にモニタリングしたり集計して表示させることができます。コマンドを使っても似たようなデータは得られますが、
まず簡単なサンプルから見てみましょう。次のDTraceスクリプトはtcp:::accept-establishedをモニタリングして、
#!/usr/sbin/dtrace -s
#pragma D option quiet
dtrace:::BEGIN
{
printf("Tracing... Hit Ctrl-C to end.\n");
}
tcp:::accept-established
{
@num[args[2]->ip_saddr, args[4]->tcp_dport] = count();
}
dtrace:::END
{
printf(" %-26s %-8s %8s\n", "HOST", "PORT", "COUNT");
printa(" %-26s %-8d %@8d\n", @num);
}
実行すると次のような結果が得られます。ファイアウォールやinetdを使って似たようなデータを取得することもできますが、
# ./tcpaccept.d Tracing... Hit Ctrl-C to end. ^C HOST PORT COUNT 192.168.1.101 22 1 192.168.1.39 22 1 192.168.1.101 2049 2 #
似たようスクリプトで対象をtcp:::accept-establishedではなくtcp:::connect-establishedを使っても似たようなデータを取得できます
#!/usr/sbin/dtrace -s
#pragma D option quiet
dtrace:::BEGIN
{
printf("Tracing... Hit Ctrl-C to end.\n");
}
tcp:::connect-established
{
@num[args[2]->ip_daddr, args[4]->tcp_dport] = count();
}
dtrace:::END
{
printf(" %-26s %-8s %8s\n", "HOST", "PORT", "COUNT");
printa(" %-26s %-8d %@8d\n", @num);
}
# ./tcpconnect.d Tracing... Hit Ctrl-C to end. ^C HOST PORT COUNT 192.168.1.10 57507 1 #
tcp:::sendとtcp:::receiveをモニタリングして送信元IP、
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option switchrate=10hz
dtrace:::BEGIN
{
printf("%-3s %15s:%-5s %15s:%-5s %6s %s\n", "CPU",
"LADDR", "LPORT", "RADDR", "RPORT", "BYTES", "FLAGS");
}
tcp:::send
{
this->length = args[2]->ip_plength - args[4]->tcp_offset;
printf("%-3d %15s:%-5d -> %15s:%-5d %6d (", cpu,
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("%-3d %15s:%-5d <- %15s:%-5d %6d (", cpu,
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");
}
実行すると次のような感じです。
# ./tcpio.d CPU LADDR:LPORT RADDR:RPORT BYTES FLAGS 0 192.168.185.50:80 <- 192.168.185.1:60622 30 (FIN|ACK) 0 192.168.185.50:80 -> 192.168.185.1:60622 30 (ACK) 0 192.168.185.50:80 -> 192.168.185.1:60622 30 (FIN|ACK) 0 192.168.185.50:80 <- 192.168.185.1:60622 30 (ACK) 0 192.168.185.50:22 <- 192.168.185.1:52416 82 (PUSH|ACK) 0 192.168.185.50:22 -> 192.168.185.1:52416 58 (PUSH|ACK) 0 192.168.185.50:22 <- 192.168.185.1:52416 30 (ACK) 0 192.168.185.50:80 <- 192.168.185.1:60621 575 (PUSH|ACK) 0 192.168.185.50:80 -> 192.168.185.1:60621 210 (PUSH|ACK) 0 192.168.185.50:80 <- 192.168.185.1:60621 30 (ACK) ^C #
特定の通信に絞り込めばTCPハンドシェークがどのように進むのかの概要も見ることができます。ネットワーク通信の中身を感じ取る方法としてはなかなか手軽で公開的な方法ではないかと思います。
※ ここに掲載したサンプルスクリプトは"DTrace Dynamic Tracing In Oracle Solaris, Mac OS X & FreeBSD", by Brendan Gregg and Jim Mauro P.
勉強会
第61回 3月23日(木)19:00~FreeBSD勉強会:リキャップ・ザ・AsiaBSDCon 2017 ~日本語でふりかえるABC~
2017年3月9~12日まで東京でAsiaBSDCon 2017が開催される予定です。ぜひこのカンファレンスにご参加いただきたいわけなのですが、
3月のFreeBSD勉強会では、
FreeBSD勉強会 発表者募集
FreeBSD勉強会では発表者を募集しています。FreeBSDに関して発表を行いたい場合、