Убить завершенные сокеты (используя libpcap - tcpdump/tcpkill)
Я пытаюсь создать небольшой сервис, который отслеживает и убивает сокеты с флагом FIN. Я могу получить их с помощью tcpdump (я также попробовал tcp[13] & 1):
tcpdump "tcp[tcpflags] & tcp-fin != 0"
Предполагается, что tcpkill использует тот же интерфейс, что и tcpdump, но он не работает так же. Я пробовал несколько команд, но это должно быть просто (-i eth0 необязательно):
tcpkill -9 "tcp[tcpflags] & tcp-fin != 0"
Который говорит (но ничего больше, успешный tcpkill выводит данные):
tcpkill: прослушивание eth0 [tcp[tcpflags] & tcp-fin!= 0]
Глядя на источник, он должен передавать правильный фильтр в pcap (между скобками [ ]). Используя скрипт perl с Net::Pcap, я могу определить, что фильтр работает нормально. Я не знаю, что я делаю неправильно, или, если это более старая версия tcpkill / pcap, это проблема. Будем благодарны за любую помощь с tcpkill или за помощь в использовании perl Net::Pcap для уничтожения сокетов. Спасибо!
#!/usr/bin/perl
use strict;
use warnings;
use Net::Pcap;
my $err = '';
my $dev = 'eth0';
my ($address, $netmask);
Net::Pcap::lookupnet($dev, \$address, \$netmask, \$err);
my $pcap = Net::Pcap::open_live($dev, 1500, 1, 0, \$err);
my $filter;
Net::Pcap::compile($pcap, \$filter, "tcp[tcpflags] & tcp-fin != 0", 0, $netmask);
Net::Pcap::setfilter($pcap, $filter);
while(1)
{
Net::Pcap::loop($pcap, 1, \&process_packet, "packet found");
}
Net::Pcap::close($pcap);
sub process_packet
{
my($user_data, $header, $packet) = @_;
print "$user_data\n";
}
exit 0;
1 ответ
Рассматривая исходный код tcpkill, он использует libnet для генерации RST-пакетов, чтобы разорвать данное TCP-соединение. Я не уверен, почему он не работает (хотя проверка версии PCAP, против которой он был создан, - отличное место для начала). Вы также можете использовать tcpdump для поиска пакетов RST, которые он должен отправлять.
Что касается реализации эквивалента в Perl, мне когда-то приходилось делать что-то похожее. Ниже приведен (непроверенный!) Код, который может указать вам правильное направление.
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
use Net::RawIP;
... (the rest of your script) ...
sub process_packet {
my ($user_data,$header,$packet) = @_;
my $ethernet_frame = NetPacket::Ethernet::strip($packet);
my $ip_packet = NetPacket::IP->decode($ethernet_frame);
my $tcp = NetPacket::TCP->decode($ip_packet->{data});
my $reset_packet = new Net::RawIP;
$reset_packet->set({
ip => {
saddr => $ip_packet->{dest_ip},
daddr => $ip_packet->{src_ip}
},
tcp => {
source => $tcp->{dest_port},
dest => $tcp->{src_port}
},
rst => 1,
seq => $ip->{acknum},
data => 'access denied'
});
$reset_packet->send();
}
tcpkill более усовершенствован с точки зрения определения правильного порядкового номера, для чего и нужны флаги -1..9. Вы пытались использовать разные значения для этого флага?