Linux 使用perl确定IPv4数据包的源端口
我有一个从TunTap接口读取和处理IPv4数据包的perl脚本。稍微简化一下,它看起来是这样的:Linux 使用perl确定IPv4数据包的源端口,linux,perl,ip,tun,Linux,Perl,Ip,Tun,我有一个从TunTap接口读取和处理IPv4数据包的perl脚本。稍微简化一下,它看起来是这样的: #!/usr/bin/perl use warnings; use strict; use Common; use Linux::TunTap; use NetPacket::IP; use IO::Socket; $|++; ###### Predecs ##### my $tun; my %config = Loadconfig(); $tun = Linux::TunTap->ne
#!/usr/bin/perl
use warnings;
use strict;
use Common;
use Linux::TunTap;
use NetPacket::IP;
use IO::Socket;
$|++;
###### Predecs #####
my $tun;
my %config = Loadconfig();
$tun = Linux::TunTap->new(NAME => $config{'localtun_name'})
or die "Couldn't connect to Interface $config{localtun_name}\n";
print "Interface up: " . $tun->{interface} . "\n";
while (my $rawdata = $tun->get_raw()) {
$rawdata =~ s/^....//; # Strip the TunTap header
my $packet = NetPacket::IP->decode($rawdata);
print "$packet->{id} $packet->{src_ip} -> $packet->{dest_ip} $packet->{proto} $packet->{len}\n";
# Do some processing here
}
出于路由原因,我需要知道数据的源端口。我还没有找到一种使用
NetPacket::IP
实现这一点的方法,所以有没有其他方法来确定这一点?由于调试原因,我目前仅使用NetPacket::IP
,因此我没有真正设置该模块,特别是如果其他模块允许我提取序列号、大小、源IP、,和目标IP。NetPacket::IP
只处理没有端口概念的IP数据包。端口仅在TCP/UDP(或您在IP上分层的任何端口)层起作用,因此您需要例如NetPacket::TCP
来获取此信息。您可能需要查看$packet->{proto}来决定要将哪个模块(TCP或UDP)用于第4层解析
如果您确定不需要更高级别的NetPacket
模块所需要的额外报头字段,那么您可以利用TCP和UDP的源端口都位于报头的前16位这一事实,因此您可以说
# Untested, so I'm not sure about the case returned in
# $packet->{proto}
if($packet->{proto} eq 'tcp' or $packet->{proto} eq 'udp') {
$port = unpack('n', $packet->{data});
...
}
编辑:顺便说一句,如果需要的话,使用substr()代替regexp替换应该会更快。干杯,今晚将测试这是否符合我的需要,并重新评估将整个项目在模型中向下移动一层好的,尝试一下。我现在能够从其他模块中提取src_端口(
NetPacket::TCP
和NetPacket::UDP
)。至于代码片段,$packet->{proto}
返回一个协议号(TCP为6),因此这里只有一个轻微的更改,但是,解包('n',$packet->{data})的结果
与我通过$tcppacket->{'src_port'}
得到的不同。解包功能有没有可能被错误使用?在不应该有源端口的ICMP数据包上进行测试时,unpack()
-line yelds 2048您分别从unpack()
和$tcppacket->{src_port}
中得到了什么?如果你看一下NetPacket::TCP::decode()
,你会发现它们完全是这样做的,只是有更多的字段:($self->{src_port},$self->{dest_port},$self->{seqnum},$self->{acknum},$tmp,$self->{winsize},$self cksum},$self cksum},$self->{cksum},$self
您从ICMP数据包中获取虚假值的原因很简单,因为您正在解码与TCP/UDP中的端口号位于同一位置的类型和代码字段。在使用telnet连接进行测试时,unpack()
方法给出45696,而$packet->{src_port}
给出17680。然而,在剥离前7个字节时,我正在对Linux::TunTap
提供的原始数据使用unpack()
,而$packet->{src_port}
正在使用NetPacket::TCP
方法从所述原始数据创建的NetPacket::TCP
对象。也许我说的不对?不,那不可能是对的。为什么是7字节?IPv4标头的长度介于20到60字节之间,具体取决于选项。您可以使用tcpdump或wireshark检查哪个端口值是正确的。