kitan Posted October 18, 2016 Последнее время наблюдаем резкое повышение исходящего трафика от некоторых клиентов. Выяснилось, что у всех клиентов стоят похожие видеорегистраторы в которых пароль от telnet вшит в прошивку. Регистраторы клиенты подключают напрямую, без роутера. Благодаря этой уязвимости видеорегистраторы заражаются и начинают одновременно Ddos'ить внешние ресурсы. К слову, проблема известная http://www.securitylab.ru/news/483934.php . Инсталяторы клиента ничего сделать с этой проблемой не могут и разводят руки. Прошивка регистраторов непомогает. Некоторые клиенты считают что это не их проблема и делать ничего не хотят. Может кто сталкивался с такой проблемой? Какие варианты борьбы? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Negator Posted October 18, 2016 Регистраторы клиенты подключают напрямую, без роутера. Вот что бывает если выдавать пул реальников на порт каждому. Варианты борьбы следующие: 1. Заблокировать порт телнета. В реале он мало кому нужен. Сообразительные откроют в личном кабинете или по звонку. 2. Отключать таких клиентов до решения проблемы. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
maxlapshin Posted October 18, 2016 в шутку могу вам предложить самостоятельно перепрошить такой регистратор. Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
kitan Posted October 19, 2016 maxlapshin, черевато вероятностью получить кирпич. Пока ничего лучше не приходит в голову, чем написать скрипт, который будет анализировать netflow и на заданное время гасить порты клиентов Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
maxlapshin Posted October 21, 2016 Кирпич можно, но это крайне редко. За этот год мы в кирпич смогли превратить только две камеры: одну прошили не той прошивкой (от другого чипсета, надо через SPI перешивать) и камеру Сони (там посерьезнее проверка). Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
SerJiо Posted November 8, 2016 Я обладатель такого регистратора. Как решить эту проблему? Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Blacklotus Posted November 8, 2016 Что за рег используете? http://forum.nag.ru/forum/index.php?showtopic=123303 Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
roysbike Posted November 18, 2016 (edited) Да , была такая проблема. Модифицировал spamblock (разработчик скрипта на этом сайте). Анализирует и блокирует на 9600 сек IP адрес на dst port 23 и 25 #iptables #Spamblock ipset destroy spammers ipset -N spammers iphash --probes 2 --resize 100 timeout 9600 $IPTABLES -A FORWARD -p tcp --dport 23 -m set --match-set spammers src -j DROP $IPTABLES -A FORWARD -p tcp --dport 25 -m set --match-set spammers src -j DROP spamblock.pl.conf #!/bin/sh # spamblock.conf IFACE="eth0" #uplink FIREWALL_TYPE="ipset" IPSET_NAME=spammers IPFW_TABLE="15" POLICY="5 1 10 3 15 6 20 10 60 60 300 600 1000 3000" EMAIL=your_mail@mail.ru" WHITELIST="1.2.3.4, 5.6.7.8" ## EOF ## cat spamblock.pl #!/usr/bin/perl # # spamblock -- detect and block spammers on FreeBSD- and Linux-based routers. # # Written at Jun 2009, Apr 2010 by ilya.evseev@gmail.com # Distributed as public domain from here: # http://sources.homelink.ru/spamblock/ # use strict; use warnings; use FindBin; use Config::General; use Time::Local; my $cfgname = @ARGV ? shift @ARGV : "$FindBin::Bin/$FindBin::Script.conf"; my $cfgfile = new Config::General($cfgname) or die "Cannot open $cfgname: $!\n"; my %Config = $cfgfile->getall; my $watch_iface = ($Config{IFACE} || $ARGV[0]) or die "Configuration line missing: IFACE=<string>\n"; my $BLOCK_TTL = $Config{BLOCK_TTL} || 3600; my $blocks_filename = $Config{BLOCKS_FILE} || '/var/log/spamblock_blocklist.txt'; my $stats_filename = $Config{STATS_FILE} || '/var/log/spamblock_fullstats.txt'; my $import_semaphore = $Config{IMPORT_SEMAPHORE} || '/var/lock/spamblock_import.semaphore'; my $export_semaphore = $Config{EXPORT_SEMAPHORE} || '/var/lock/spamblock_export.semaphore'; my $email_recipient = $Config{EMAIL}; # ..good for default: root@localhost? my %whitelist = map { $_ => 1 } split(/[,\s]\s*/, $Config{WHITELIST} || ''); my $check_policy = $Config{POLICY} or die "Configuration line missing: POLICY=\"count_1 period_1 count_2 period_2\"\n"; my @checks = split(/\s+/, $check_policy) or die "Configuration line empty: POLICY\n"; die "Policy MUST be even-sized in \"count period ...\" format" if @checks % 2; my %stats; # IP => { count => lasttime, ... } my %blocks; # IP => 1 my $tstamp = time; my $tstart = $tstamp; my $total_checks = 0; my $total_blocks = 0; my $fw; #use Data::Dumper; sub tprint { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($tstamp); printf("[ %04d.%02d.%02d %02d:%02d:%02d ] @_\n", $year+1900, $mon+1, $mday, $hour, $min, $sec); } sub import_state() { tprint "Import state..."; my %new_blocks; $fw->import_state(\%new_blocks); my ($readed, $added, $deleted, $total) = (0,0,0,0); while (my ($ip, undef) = each %blocks) { $total++; next if $new_blocks{$ip}; $deleted++; delete $blocks{$ip}; $total--; } while (my ($ip, undef) = each %new_blocks) { $readed++; next if $blocks{$ip}; $added++; $blocks{$ip} = 1; $total++; } tprint sprintf("Import done. Total %d, readed %d, added %d, deleted %d blocks.", $total, $readed, $added, $deleted); } sub mkoutfile($$) { my ($fname, $desc) = @_; return if not $fname or $fname eq '-'; tprint "Dump $desc to $fname..."; my $fd; unless (open $fd, "> $fname") { print STDERR "Cannot open $fname: $!\n"; return; } $fd; } sub ip2hex($) { my @a = split(/\./, shift); my $b = 0; $b = $b * 256 + $_ foreach @a; sprintf("%08X", $b); } sub export_blocks() { my $fd = mkoutfile($blocks_filename, 'blocks') or return; print $fd "$_\n" foreach sort { ip2hex($a) cmp ip2hex($b) } keys %blocks; close $fd; } sub export_stats() { $tstamp = time; my $fd = mkoutfile($stats_filename, 'stats') or return; printf $fd "# Uptime: %d seconds, %d checks, %d blocks.\n", ($tstamp - $tstart), $total_checks, $total_blocks; printf $fd "# %-18s%8s %6s", 'IP', 'Checks', 'Blocks'; my @iplist = sort { ip2hex($a) cmp ip2hex($b) } keys %stats; foreach my $ip (@iplist) { my $stat = $stats{$ip}; my @fields = sort { # use numeric-based sorting for numeric fields ($a =~ /^\d+$/ and $b =~ /^\d+$/) ? ($a <=> $b) : ($a cmp $b); } keys %$stat; printf $fd "%-20s%8d%6s\n", $ip, $stat->{total_count} || 0, $stat->{blocks_count} || '-'; } close $fd; } sub export_state() { tprint "Dump state..."; export_blocks(); export_stats(); tprint "Dump done."; } sub handle_semaphore($$$) { my ($fname, $handler, $description) = @_; return if not $fname or $fname eq '-' or not -w $fname; tprint "Found $fname semaphore, perform $description..."; $handler->(); unlink $fname; tprint "Delete $fname, $description done."; } my $typ = lc($Config{FIREWALL_TYPE} || 'auto'); $fw = new ipset (\%Config) if $typ eq 'ipset' or ($typ eq 'auto' and -x '/sbin/ipset'); $fw ||= new iptables(\%Config) if $typ eq 'iptables' or ($typ eq 'auto' and -x '/sbin/iptables'); $fw ||= new pf (\%Config) if $typ eq 'pf' or ($typ eq 'auto' and -w '/dev/pf'); $fw ||= new ipfw (\%Config) if $typ eq 'ipfw' or ($typ eq 'auto' and -x '/sbin/ipfw'); tprint "Started now."; import_state(); #tprint "Debug export and exit!"; export_state(); exit; $SIG{USR1} = \&import_state; $SIG{USR2} = \&export_state; open F, "tcpdump -lnnqttpi $watch_iface tcp and dst port 23 or dst port 25 and 'tcp[13] == 2' 2>&1 |" #open F, "tcpdump -lnnqttpi $watch_iface tcp 2>&1 |" #open F, "tcpdump -lnnqttpi $watch_iface tcp and dst port 23 2>&1 |" or die "Cannot run tcpdump: $!\n"; select((select(F), $|=1)[0]); # ..disable buffering while(<F>) { #chomp; #tprint "line = \"$_\""; next unless /^(\d+)\.(\d+) IP (\d+\.\d+\.\d+\.\d+)\.\d+ \> \d+\.\d+\.\d+\.\d+\.2[3,5]: /; my ($tstamp0, $tstamp0_msecs, $ip) = ($1, $2, $3); $total_checks++; handle_semaphore($import_semaphore, \&import_state, 'import'); handle_semaphore($export_semaphore, \&export_state, 'export'); my $s = ($stats{$ip} ||= {}); ($s->{total_count} ||= 0)++; $tstamp = time; next if $whitelist{$ip}; next if $blocks{$ip} and $tstamp0 - $blocks{$ip} < $BLOCK_TTL; my @stats; my $blockmsg; for (my $i = 0; $i < @checks; $i+=2) { my $maxcount = $checks[$i]; my $period = $checks[$i+1]; $s->{$maxcount} ||= $tstamp0; next if $s->{total_count} % $maxcount; my $delta = $tstamp0 - $s->{$maxcount}; push @stats, "$maxcount:$delta"; if ($delta >= $period) { $s->{$maxcount} = $tstamp0; next; } $total_blocks++; ($s->{blocks_count} ||= 0)++; $blocks{$ip} = $tstamp0; $blockmsg = "Block $ip: trap #$s->{blocks_count}" ." by rule $maxcount:$period ticks:seconds," ." actually $delta seconds"; $fw->block($ip); last; } tprint sprintf(" %-20s%8d:%d \t@stats", $ip, $s->{total_count}, $tstamp - $tstart); next unless $blockmsg; tprint $blockmsg; # Report by email next if not $email_recipient or $email_recipient eq '-'; unless (open M, "| mail -s 'SpamBlock $ip' $email_recipient") { warn "Cannot run mail: $!\n"; next; } print M $blockmsg, "\n"; close M; } close F; #======================================================================= package fwbase; sub new($$$$$) { my ($class, $cfg, $paramname, $hint) = @_; my ($package, $filename, $line) = caller; ::tprint "Firewall type: $package"; my $val = $cfg->{$paramname} or die "Missing $hint in configuration file!\n"; bless({ $paramname => $val }, ref($class) || $class); } sub import_custom($$$$) { my ($class, $blocks, $infile, $filter) = @_; open S, $infile or die "Cannot get $infile: $!\n"; while (<S>) { $blocks->{$1} = 1 if $_ =~ $filter; } close S; $blocks; } #======================================================================= package ipfw; use base 'fwbase'; sub new($$) { my ($class, $cfg) = @_; my $self = $class->SUPER::new($cfg, 'IPFW_TABLE', 'IPFW_TABLE=<number>'); bless($self, ref($class) || $class); } sub import_state($$) { my ($self, $blocks) = @_; $self->import_custom($blocks, "/sbin/ipfw table $self->{IPFW_TABLE} list |", '^(\d+\.\d+\.\d+\.\d+)\/\d+ \d+$'); } sub block($$) { my ($self, $ip) = @_; system("/sbin/ipfw -q table $self->{IPFW_TABLE} add $ip"); } #======================================================================= package pf; use base 'fwbase'; sub new($$) { my ($class, $cfg) = @_; my $self = $class->SUPER::new($cfg, 'PF_TABLE', 'PF_TABLE=<string>'); bless($self, ref($class) || $class); } sub import_state($$) { my ($self, $blocks) = @_; $self->import_custom($blocks, "/sbin/pfctl -t $self->{PF_TABLE} -T show |", '^\s*(\d+\.\d+\.\d+\.\d+)$'); } sub block($$) { my ($self, $ip) = @_; system("/sbin/pfctl -t $self->{PF_TABLE} -T add $ip"); } #======================================================================= package ipset; use base 'fwbase'; sub new($$) { my ($class, $cfg) = @_; my $self = $class->SUPER::new($cfg, 'IPSET_NAME', 'IPSET_NAME=<string>'); bless($self, ref($class) || $class); } sub import_state($$) { my ($self, $blocks) = @_; $self->import_custom($blocks, "/sbin/ipset -L $self->{IPSET_NAME} |", '^(\d+\.\d+\.\d+\.\d+)$'); } sub block($$) { my ($self, $ip) = @_; system("/sbin/ipset -A $self->{IPSET_NAME} $ip"); #system("/usr/sbin/ipset -qA $self->{IPSET_NAME} $ip"); } #======================================================================= package iptables; use base 'fwbase'; sub new($$) { my ($class, $cfg) = @_; my $self = $class->SUPER::new($cfg, 'IPTABLES_CHAIN', 'IPTABLES_CHAIN=<string>'); bless($self, ref($class) || $class); } sub import_state($$) { my ($self, $blocks) = @_; $self->import_custom($blocks, "/sbin/iptables -nL $self->{IPTABLES_CHAIN} |", '^(\d+\.\d+\.\d+\.\d+)$'); } sub block($$) { my ($self, $ip) = @_; system("/sbin/iptables -nL $self->{IPTABLES_CHAIN}" ." | grep -q -- ' $ip '" ." || /sbin/iptables -I $self->{IPTABLES_CHAIN} -s $ip -j DROP" ); } ## EOF ## Запускать /opt/spamblock.pl >> /var/log/spamblock.log 2>&1 & Edited November 18, 2016 by roysbike Вставить ник Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...