tshark アプローチ
Wiresharkを使用している場合(実際の質問ではなく、質問タグに基づく)、tshark
@joke のコメントの行に沿って進むのが 1 つの方法です。詳細な統計出力が気にならない場合:
tshark -i any -n -q -z 'io,stat,0,FRAMES()tcp.port==389,FRAMES()tcp.port==88,FRAMES()udp.port==53'
Capturing on Pseudo-device that captures on all interfaces
^C142 packets captured
=============================================
| IO Statistics |
| |
| Interval size: 4.319 secs (dur) |
| Col 1: FRAMES()tcp.port==389 |
| 2: FRAMES()tcp.port==88 |
| 3: FRAMES()udp.port==53 |
|-------------------------------------------|
| |1 |2 |3 |
| Interval
| Interval | FRAMES | FRAMES | FRAMES |
|-------------------------------------------|
| 0.000 <> 4.319 | 100 | 200 | 300 |
=============================================
それからの出力は冗長ですが、一人で近づくことはできないと思いますtshark
。もう 1 つのアプローチは、さらに冗長ですが、次のようになります。
tshark -q -z io,phs "tcp port 389 or tcp port 88 or udp port 53"
これら 2 つのコマンドは、キャプチャ ファイルを書き込みません。Ctrl終了する準備ができたら+を使用するか、自動停止条件Cに関する以下のコメントを参照してください。注意点の 1 つは、これらの統計は送信元/宛先ポートではなく、プロトコル ディセクタ-a
に依存しているため、不一致 (データのない接続、プロトコルに準拠していないコンテンツなど) が発生する可能性があり、代わりに「不正な形式の」パケットが報告されることです。また、最適化してパケットあたり 40 バイトしかキャプチャしない場合、信頼できる結果が得られないことも意味します (「短い」TCP または UDP パケットが代わりに報告されます)。
tcpdump アプローチ
シンプルだが洗練されていない方法は、複数のtcpdump
インスタンスを実行することです (bash をシェルと仮定します) --
for pp in "tcp port 88" "tcp port 389" "udp port 53"; do
tcpdump -i any -Z root $pp -w /dev/null 2> ${pp// /-}.stats &
done
パケットはキャプチャ ファイルに書き込まれません( によって破棄されます/dev/null
)。次に、必要に応じて待機し、tcpdump
プロセスを強制終了して (リストされている PID によって、またはkill %1 %2 %3
他のバックグラウンド ジョブがない場合)、.stats
ファイルを調べます。
grep captured *.stats
tcp-port-389.stats:0 packets captured
tcp-port-88.stats:0 packets captured
udp-port-53.stats:4 packets captured
パールアプローチ
これはstackoverflowであるため、簡単で汚い perl/libpcap ソリューションを次に示します (エラー処理を追加するだけです)。
#!/usr/bin/perl
use Net::Pcap;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use strict;
use warnings;
my ($dev,$err,$address, $netmask,$pcap,$filter,$cfilter,$fd,%stats);
my $bail=0;
my ($rin,$rout)=('','');
$SIG{INT} = sub { print "quit...\n"; $bail=1; };
$filter='(tcp port 88 or tcp port 389 or udp port 53)';
$dev=Net::Pcap::lookupdev(\$err);
Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err);
$pcap = Net::Pcap::open_live($dev, 60, 1, 0, \$err);
Net::Pcap::pcap_setnonblock($pcap, 1, \$err);
$fd=Net::Pcap::pcap_get_selectable_fd($pcap);
vec($rin,$fd,1)=1;
Net::Pcap::compile( $pcap, \$cfilter, $filter, 0, $netmask);
Net::Pcap::setfilter($pcap, $cfilter);
while (Net::Pcap::dispatch($pcap,0, \&handlepackets, '')>=0) {
select($rout=$rin,undef,undef,0.250);
printf("."); $|=1;
$bail && last;
};
Net::Pcap::freecode($cfilter);
Net::Pcap::close($pcap);
sub handlepackets() {
my ($user_data, $header, $packet) = @_;
my $ether = NetPacket::Ethernet::strip($packet);
my $ip = NetPacket::IP->decode($ether);
my $tcp = NetPacket::TCP->decode($ip->{'data'});
if ($tcp->{'src_port'} < 1024) {
$stats{$tcp->{'src_port'}}++;
} elsif ($tcp->{'dest_port'} < 1024) {
$stats{$tcp->{'dest_port'}}++;
}
}
END {
if (keys %stats) {
for my $kk (sort keys %stats) {
my ($name, $aliases, $port, $prot)=getservbyport($kk,"tcp");
printf("%12s %4i\n",$name,$stats{$kk});
}
} else { printf("No stats...\n"); }
}