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 CollectPackets{
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 CollectPackets{
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 PrintIfOpen{
#定义回调函数
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 PrintIfOpen{
#定义回调函数
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的处理
涉及的模块
Text::CSV
Text::CSV_XS 速度更快
- 获取IP地址的物理位置
涉及的模块
Geo::IP