2

我有兴趣计算所有 LDAP/Kerberos/DNS 数据包。

我尝试了以下方法,但这会捕获完整的数据包。

tcpdump -i any -Z root "tcp 端口 389 或 tcp 端口 88 或 udp 端口​​ 53" -w ~/ldap_kerberos_dns.cap

有没有一种方法可以捕获交换了多少个 ldap/Kerberos/DNS 数据包
而不实际捕获完整数据包。

预期的输出应该是这样的:

LDAP:     100  
Kerberos: 200  
UDP:      300  
4

2 回答 2

3

看一下 tshark 统计数据:

$ tshark -r 04.pcap -q -z io,phs
==================================================== ==================
协议层次统计
筛选:

eth 帧:649 字节:124780
  ipv6 帧:605 字节:116558
    udp 帧:212 字节:33686
      dhcpv6 帧:171 字节:28044
      dns 帧:25 字节:2914
      ntp 帧:10 字节:1300
      cldap 帧:6 字节:1428
    icmpv6 帧:80 字节:7008
    tcp 帧:313 字节:75864
      nbss 帧数:108 字节:24063
        smb 帧:7 字节:1554
        smb2 帧:101 字节:22509
          tcp.segments 帧:1 字节:103
      dcerpc 帧:16 字节:4264
        epm 帧数:2 字节:544
        tcp.segments 帧:1 字节:214
        drsuapi 帧:8 字节:2352
      kerberos 帧:16 字节:9358
        tcp.segments 帧:8 字节:2130
      dcerpc.cn_deseg_req 帧数:1 字节:1514
      ldap 帧:16 字节:5945
        tcp.segments 帧:3 字节:1101
          ldap 帧:1 字节:803
  ip 帧:40 字节:8018
    udp 帧:40 字节:8018
      nbdgm 帧:30 字节:7300
        smb 帧:30 字节:7300
          邮槽帧:30 字节:7300
            浏览器框架:30 字节:7300
      dns 帧:10 字节:718
  arp 帧:4 字节:204
==================================================== ==================

有关更多信息,请参见手册页

于 2013-01-31T05:27:15.683 回答
3

tshark方法

如果您有Wireshark(基于问题标签,而不是实际问题)tshark,那么如果您不介意其详细的统计信息输出,那么按照 @joke 的评论是一种方法:

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单独接近。另一种更为冗长的方法是:

tshark -q -z io,phs "tcp port 389 or tcp port 88 or udp port 53"

这两个命令不写入捕获文件。当您准备好退出时使用Ctrl+ ,或查看下面关于自动停止条件的评论。需要注意的是,这些统计数据依赖于协议解析器,而不是源/目标端口,因此可能存在差异(例如,没有数据的连接,或内容不符合协议),将报告“格式错误”的数据包。这也意味着如果您优化并且每个数据包仅捕获 40 个字节(将报告“短”TCP 或 UDP 数据包),您将无法获得可靠的结果。C-a

tcpdump 方法

一个简单但不优雅的方法是运行多个tcpdump实例(假设 bash 作为一个 shell)——

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

perl 方法

由于这是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"); } 
}
于 2013-01-30T22:58:22.677 回答