使用 perl 确定 IPv4 数据包的源端口

Determine the source port of an IPv4 packet with perl

我有一个 perl 脚本可以从 TunTap 接口读取和处理 IPv4 数据包。精简一点,看起来像这样:

#!/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)进行 layer4 解析。

如果您确定不需要 higher-level NetPacket 模块有意义的额外 header 字段,您可以利用源端口是对于 TCP 和 UDP,在 header 的前 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() 而不是正则表达式替换应该会更快。