天天看點

Perl與網絡監控

Perl與網絡監控

  1. 發現主機
  • Net::Ping

    可以發送ICMP,TCP,UDP的Ping包。但該子產品需要管理者權限。

use Net::Ping;
use Net::Netmask;

my $ping=Net::Ping->new('icmp'); #需要root權限

#輸入掩碼
die $Net::Netmask::error unless my $netblock=new2 Net::Netmask($ARGV[0]); #new2方法調用失敗傳回undef, 而new則傳回空對象。
my $blocksize=$netblock->size()-1;

my (@addrs);
for(my $i=1;$i<=$blocksize;$i++){
    my $addr=$netblock-nth($i);
    push(@addrs, $addr) if $ping->ping($addr, 1);
}
print "Found\n", join("\n", @addrs), "\n" if scalar @addrs;      
  • Net::Ping::External

    可以不依賴管理者權限。它幫助權限不足的Perl腳本調用作業系統内置的ping可執行程式,而該ping程式已經為普通使用者設定了合适的執行權限,也能免于安全檢查。它讓Perl腳本可以不考慮不同平台的輸入輸出差異。

use Net::Ping::External qw(ping);

# Ping a single host
my $alive = ping(host => "127.0.0.1");
print "127.0.0.1 is online" if $alive;

# Or a list of hosts
my @hosts = qw(127.0.0.1 127.0.0.2 127.0.0.3 127.0.0.4);
my $num_alive = 0;
foreach (@hosts) {
  $alive = ping(hostname => $_, timeout => 5);
  print "$_ is alive!\n" if $alive;
  $num_alive++;
}
print "$num_alive hosts are alive.\n";

# Using all the fancy options:
ping(hostname => "127.0.0.1", count => 5, size => 1024, timeout => 3);      
  • 建構ARP封包
nemesis arp -v -S 192.168.13.13 -D 192.168.13.18      

ARP封包結構

Perl與網絡監控

構造ARP封包還可以使用如下子產品

Net::Packet

Net::Pcap

當然也可以使用如下子產品來完成arp的掃描

Net::Arping

use Net::Arping;

my $arping=Net::Arping->new(); #如果收到ARP響應,arping()會傳回其中的MAC位址
my $return=$arping->arping($ARGV[0]);
print "$ARGV[0]" .
    ($return)? "($return) is up\n" : "is down\n";      
  1. 嗅探ARP流量
use Net::PcapUtils;
use NetPacket::Ethernet;
use NetPacket::ARP;

my $filter='arp';
my $dev='eth1';
my %addresses=();

die 'Unable to perform capture: '.Net::Pcap::geterr($dev)."\n" 
    if(Net::PcapUtils::loop(\&CollectPackets,
                            FILTER=>$filter,
                            DEV=>$dev,
                            NUMPACKETS=>100, #監聽100個包
        )
    );

print join("\n", keys %addresses), "\n";

sub{
    my ($arg, $hdr, $pkt)=@_;
    #将IP位址從十六進制形式轉換為點分十進制形式
    my $ip_add=join(
        '.',
        unpack(
            'C*',
            pack('H*',
                NetPacket::ARP->decode(NetPacket::Ethernet::strip($pkt))
                ->{'spa'}
            )
        )
    );
    $addresses{$ip_addr}++;
}      
  1. 嗅探DHCP流量
use Net::PcapUtils;
use NetPacket::Ethernet;
use NetPacket::IP;

my $filter='dst port 68'; #DHCP用戶端偵聽端口
my $dev='eth1';
my %addresses=();

die 'Unable to perform capture: '.Net::Pcap::geterr($dev)."\n" 
    if(Net::PcapUtils::loop(\&CollectPackets,
                            FILTER=>$filter,
                            DEV=>$dev,
                            NUMPACKETS=>100, #監聽100個包
        )
    );
print join("\n", keys %addresses), "\n";

sub{
    my ($arg, $hdr, $pkt)=@_;
    #将IP位址從十六進制形式轉換為點分十進制形式
    my $ip_add=NetPacket::IP->decode(NetPacket::Ethernet::strip($pkt))->{'src_ip'}; #擷取DHCP Server的IP位址
    $addresses{$ip_addr}++;
}      
  1. 掃描端口

使用的子產品

Nmap::Scanner 調用nmap的子產品

Nmap::Parser 分析XML模式的nmap輸出

Nmap::Scanner的批處理模式

use Nmap::Scanner;

my $nscan=new Nmap::Scanner;
#nmap指令的位置可以給絕對路徑,也可以省略(讓perl從$PATH環境變量中查找)
$nscan->nmap_location('/usr/local/bin/nmap');

#開始掃描
my $nres=$nscan->scan('-p 80 192.168.10.0/24');
my $nhosts=$nres->get_host_list();

#周遊找到的主機
while(my $host=$nhosts->get_next()){
    print $host->hostname()."\n" if $host->get_port("tcp", 80)->state() eq 'open';
}      

Nmap::Scanner的事件驅動模式

use Nmap::Scanner;

my $nscan=new Nmap::Scanner;
$nscan->nmap_location('/usr/local/bin/nmap');

#每發現一個端口就運作&printIfOpen
$nscan->register_port_found_event(\&PrintIfOpen);

my $nres=$nscan->scan('-p 80 118.37.13.0/24');

sub{
    #定義回調函數
    my ($self, $host, $port)=@_; #掃描對象,主機對象,端口對象
    print $host->hostname()."\n" if $port->state() eq 'open';
}      

使用Nmap::Scanner子產品可以識别作業系統和版本。

...
#測試打開的端口是否可以提供服務
my $nres=$nscan->scan('-p 80 -sV 192.168.10.0/24'); #加上-O參數可以識别作業系統
...
sub{
    #定義回調函數
    my ($self, $host, $port)=@_; #掃描對象,主機對象,端口對象
    print $host->get_port('tcp', 80)->sevice->extrainfo().'\n';
    print $host->get_port('tcp', 80)->sevice->product().'\n';
    print $host->get_port('tcp', 80)->sevice->version().'\n';
}      
  1. 文本顯示

常用子產品

Text::Wrap

Text::Beautify

Text::Autoformat

  • 使用Text::Autoformat格式化文本顯示
use Text::Autoformat;
my $a='......
......
......
';
print autoformat($a, {all=>1});      
  1. 文本表格

涉及的子產品

Array::PrintCols

Text::TabularDisplay

Text::FormatTable

Text::ASCIITable

Data::ShowTable

use Text::FormatTable;
my %results=(
    'drummoud'=>{
        status=>'passed',
        owner=>'stracy'
    },
    'brady'=>{
        status=>'passed',
        owner=>'vivid'        
    },
    'hornbeck'=>{
        status=>'passed',
        owner=>'yaboo'                
    }
);
my $table=Text::FormatTable->new('|l|l|l|');
$table->rule('-');
$table->head(qw(Host Status Owner));
$table->rule('-');
foreach (sort keys %results){
    $table->row($_,$results{$_}{status}, $results{$_}{owner});
}
$table->rule('-');
print $table->render();      
  1. 文本進度條
use Text::BarGraph;

my %hoststats=(
            'cbd1'=>10,
            'wcc'=>20,
            'etl'=>30,
            'ppe'=>100,
            'llade'=>55
            );
            
my $g=Text::BarGraph->new();

$g->{columns}=70; #設定列寬
$g->{num}=1; #在條形邊上顯示數值

print $g->graph(\%hoststats);      
  1. CSV的處理
  1. 擷取IP位址的實體位置