Убить завершенные сокеты (используя 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. Вы пытались использовать разные значения для этого флага?

Другие вопросы по тегам