Чтение пакетов с Linux::TunTap
Я собрал perl-скрипт, который считывает пакеты в пользовательское пространство через Linux::TunTap, и кажется, что все работает нормально:
#!/usr/bin/perl
use warnings;
use strict;
use Linux::TunTap;
$tun = new Linux::TunTap(NAME => 'localtun')
or die "Couldn't connect to IF\n";
while (my $packet = $tun->get_raw()) {
print Dumper($packet);
}
Теперь возникает вопрос: как превратить строку, представляющую необработанный IP-пакет, считанный с устройства tuntap, в правильную структуру данных для обработки? В частности, я после источника, назначения и порядкового номера.
Очевидно, что исходный IP-пакет не очень удобен для чтения в исходном формате. Вот вывод после отправки пинга через интерфейс tuntap:
{{{�}/��8V�| !"#$%&'()*+,-./0123456ET��@@4
Как мне перейти отсюда, чтобы иметь возможность обрабатывать эти данные программно?
1 ответ
Основываясь на комментарии, сделанном Steffen Ullrich, я взглянул на NetPacket:: IP, который помог мне decode()
метод. После того, как он был вставлен в мой код, он работал практически из коробки, единственное предостережение в том, что первые четыре байта должны исходить из необработанных данных (см. Ленивое регулярное выражение ниже), так как эти байты формируют дополнительный заголовок, добавленный TunTap слой.
Мой код теперь выглядит так, и работает как задумано:
#!/usr/bin/perl
use warnings;
use strict;
use Linux::TunTap;
use NetPacket::IP;
$tun = new Linux::TunTap(NAME => 'localtun')
or die "Couldn't connect to IF\n";
while (my $rawdata = $tun->get_raw()) {
$rawdata =~ s/^....//; # Using regex to strip 4 bytes, because I'm lazy
my $packet = NetPacket::IP->decode($rawdata);
print "$packet->{id} $packet->{src_ip} -> $packet->{dest_ip} $packet->{proto} $packet->{len}\n";
}
Приведенный выше код печатает последовательность, IP-адрес источника, IP-адрес назначения, номер протокола и длину пакета.