kitan Опубликовано 18 октября, 2016 Последнее время наблюдаем резкое повышение исходящего трафика от некоторых клиентов. Выяснилось, что у всех клиентов стоят похожие видеорегистраторы в которых пароль от telnet вшит в прошивку. Регистраторы клиенты подключают напрямую, без роутера. Благодаря этой уязвимости видеорегистраторы заражаются и начинают одновременно Ddos'ить внешние ресурсы. К слову, проблема известная http://www.securitylab.ru/news/483934.php . Инсталяторы клиента ничего сделать с этой проблемой не могут и разводят руки. Прошивка регистраторов непомогает. Некоторые клиенты считают что это не их проблема и делать ничего не хотят. Может кто сталкивался с такой проблемой? Какие варианты борьбы? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Negator Опубликовано 18 октября, 2016 Регистраторы клиенты подключают напрямую, без роутера. Вот что бывает если выдавать пул реальников на порт каждому. Варианты борьбы следующие: 1. Заблокировать порт телнета. В реале он мало кому нужен. Сообразительные откроют в личном кабинете или по звонку. 2. Отключать таких клиентов до решения проблемы. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 18 октября, 2016 в шутку могу вам предложить самостоятельно перепрошить такой регистратор. Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
kitan Опубликовано 19 октября, 2016 maxlapshin, черевато вероятностью получить кирпич. Пока ничего лучше не приходит в голову, чем написать скрипт, который будет анализировать netflow и на заданное время гасить порты клиентов Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
maxlapshin Опубликовано 21 октября, 2016 Кирпич можно, но это крайне редко. За этот год мы в кирпич смогли превратить только две камеры: одну прошили не той прошивкой (от другого чипсета, надо через SPI перешивать) и камеру Сони (там посерьезнее проверка). Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
SerJiо Опубликовано 8 ноября, 2016 Я обладатель такого регистратора. Как решить эту проблему? Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
Blacklotus Опубликовано 8 ноября, 2016 Что за рег используете? http://forum.nag.ru/forum/index.php?showtopic=123303 Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...
roysbike Опубликовано 18 ноября, 2016 (изменено) Да , была такая проблема. Модифицировал 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 & Изменено 18 ноября, 2016 пользователем roysbike Вставить ник Цитата Ответить с цитированием Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах More sharing options...