Perl與網絡監控
- 發現主機
-
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封包結構
構造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";
- 嗅探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}++;
}
- 嗅探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}++;
}
- 掃描端口
使用的子產品
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';
}
- 文本顯示
常用子產品
Text::Wrap
Text::Beautify
Text::Autoformat
- 使用Text::Autoformat格式化文本顯示
use Text::Autoformat;
my $a='......
......
......
';
print autoformat($a, {all=>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();
- 文本進度條
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);
- CSV的處理
- 擷取IP位址的實體位置