Antispam y bloqueo de IP.
Resumen.
Este artículo está orientado a la seguridad, por lo que para un obsesionado con ella como yo, es de la máxima importancia. Implementar un sistema antispam es de suma importancia en todos aquellos formularios que están a disposición del público, como pueden ser el formulario de contacto, el de registro o el de logeo. Con el antispam nos protegeremos de las acciones automáticas realizadas por robots, con el bloqueo de IP, negaremos acciones a ciertos usuarios.Artículo.
Si hay algo que no podemos descuidar nunca es la seguridad de nuestro sitio Web, ya hablamos en su momento sobre la validación de los datos del lado del servidor, ahora lo haremos desde otros dos puntos de vista, por un lado diferenciando usuarios reales de acciones automatizadas mediante un sistema antispam y por otro lado, negando acciones a ciertos usuarios mediante el bloqueo de su dirección IP (Protocolo de Internet).
Empezaremos por crear un sistema antispam, cuya lógica es muy sencilla:
1) Generar un cierto valor.
2) Enviar ese valor por dos vías o rutas.
3) Comparar si las dos vías envían el mismo valor.
Así, podemos generar un valor de forma aleatoria por ejemplo, con la función mt_rand(min,max). Esta función genera valores numéricos seudoaleatorios entre un valor mínimo y máximo. También podríamos usar otras como esta que puede generar cadenas seudoaleatorias formadas por los caracteres que deseemos.
En nuestro caso vamos a optar por la primera opción, los valores numéricos seudoaleatorios.
Via 1: Así vamos a generar dos valores, y estos dos valores, aleatoriamente, los sumamos o los multiplicamos, el resultado, lo propagamos como variable de sesión.
Via 2: Vamos o mostrar esos dos valores al usuario y le vamos a pedir que realice la correspondiente operación de suma o multiplicación, e introduzca ese valor en un campo.
Una vez se envía el formulario, se recupera el valor mediante la variable de sesión, mientras que el otro valor, (el calculado por el usuario) se envía por POST, si ambos coinciden, se realizan las acciones correspondientes (envío de un formulario de contacto, registro de un usuario…).
El código con el que generamos estos valores es este:
antispam.php
Lo que hemos hecho es sencillo, hemos generado un valor aleatorio entre 0 y 10, y en función de si este valor es par o impar, sumamos los dos valores generados o los multiplicamos. Y el resultado de la operación matemática lo propagamos como variable de sesión.
Agregar que estos valores de cara a mostrarlos en página al usuario, lo vamos a codificar en ASCII mediante la siguiente función:
función_asc.php
Así, nuestro formulario de contacto toma la siguiente forma:
form.php
Ahora vamos a ver como procesamos este formulario.
procesa.php
Vamos a desgranar un poco lo que hemos hecho. Lo primero inicializar las sesiones y cargar la función de bloqueo de IP. Seguidamente recibimos los cuatro campos del formulario mas el campo antispam que introduce el usuario y recogemos la variable de sesión creada en el archivo antispam.php.
El segundo paso será agregar la función de bloqueo de IP, para ello definimos en la variable $ip_bloqueadas un conjunto de direcciones IP (OJO, estas direcciones son arbitrarias, solo es un ejemplo) separadas por pleca “|”a las que queremos denegar el acceso, también capturamos la IP del usuario activo.
Tras aplicar la función, creamos el siguiente condicional:
Que nos viene a decir, si $ip_aceptada toma el valor 0, no hacemos nada, salvo declarar nula la variable $aviso para que no nos de error.
Si toma el valor 1, y aquí viene lo importante, declaramos la variable $antisp, la que envía el usuario, le asignamos un valor fuera de rango, es decir, un valor mayor que el valor máximo que puede proporcionar antispam.php, que es 11*10=110. De esta forma, como esta variable ($antisp) la declaramos después de que el usuario haya enviado su valor, tomará el nuevo valor, es decir 9999, por lo que nunca podrá coincidir con el valor de la variable $sesion_antisp. De esta forma, el antispam siempre dará como resultado usuario no válido.
Cuando se cumple la condición $antisp es igual a $sesion_antisp entonces realizamos las acciones que nos interesa, en este caso, simplemente hemos mostrado en pantalla los datos que envía el usuario. Aquí podríamos poner el código que guarda el mensaje en una base de datos y/o el que envía el mensaje a una dirección de e-mail.
Cuando no se cumple la condición, mostramos el aviso de IP bloqueada, y por tanto, AntiSapam no válido. Si simplemente hay error con el antispam y la IP no esta bloqueada, solo aparecerá AntiSpam NO valido. Por supuesto, el aviso de IP bloqueada, como ejemplo ilustrativo y mientras se trabaja, esta bien, pero en la práctica de su uso, probablemente lo mejor sea omitirlo, eso ya queda a vuestro criterio.
Y con esto, finalizamos la protección de formularios con sistema antispam y bloqueo de IP, sin olvidar, que la validación de datos a nivel de servidor, que aquí no hemos mencionado, es clave.
Empezaremos por crear un sistema antispam, cuya lógica es muy sencilla:
1) Generar un cierto valor.
2) Enviar ese valor por dos vías o rutas.
3) Comparar si las dos vías envían el mismo valor.
Así, podemos generar un valor de forma aleatoria por ejemplo, con la función mt_rand(min,max). Esta función genera valores numéricos seudoaleatorios entre un valor mínimo y máximo. También podríamos usar otras como esta que puede generar cadenas seudoaleatorias formadas por los caracteres que deseemos.
En nuestro caso vamos a optar por la primera opción, los valores numéricos seudoaleatorios.
Via 1: Así vamos a generar dos valores, y estos dos valores, aleatoriamente, los sumamos o los multiplicamos, el resultado, lo propagamos como variable de sesión.
Via 2: Vamos o mostrar esos dos valores al usuario y le vamos a pedir que realice la correspondiente operación de suma o multiplicación, e introduzca ese valor en un campo.
Una vez se envía el formulario, se recupera el valor mediante la variable de sesión, mientras que el otro valor, (el calculado por el usuario) se envía por POST, si ambos coinciden, se realizan las acciones correspondientes (envío de un formulario de contacto, registro de un usuario…).
El código con el que generamos estos valores es este:
antispam.php
<?php $par_impar = mt_rand(1,10); $resto = $par_impar % 2; // Calcula el resto de una division if($resto == 0){ $valorA = mt_rand(0,20); $valorAcod = Cod_Asci("$valorA"); // Entre comillas para que sea interpretado como cadena, no numerico $valorB = mt_rand(0,20); $valorBcod = Cod_Asci("$valorB"); // Entre comillas para que sea interpretado como cadena, no numerico $resultado = $valorA + $valorB; $operacion = Cod_Asci('+'); $_SESSION['resultado_atsp'] = $resultado; }else{ $valorA = mt_rand(0,11); $valorAcod = Cod_Asci("$valorA"); // Entre comillas para que sea interpretado como cadena, no numerico $valorB = mt_rand(0,10); $valorBcod = Cod_Asci("$valorB"); // Entre comillas para que sea interpretado como cadena, no numerico $resultado = $valorA * $valorB; $operacion = Cod_Asci('x'); $_SESSION['resultado_atsp'] = $resultado; } ?>
Lo que hemos hecho es sencillo, hemos generado un valor aleatorio entre 0 y 10, y en función de si este valor es par o impar, sumamos los dos valores generados o los multiplicamos. Y el resultado de la operación matemática lo propagamos como variable de sesión.
Agregar que estos valores de cara a mostrarlos en página al usuario, lo vamos a codificar en ASCII mediante la siguiente función:
función_asc.php
De esta forma, los valores no se presentan directamente en el código fuente.<?php function Cod_Asci($cdna){ for($i=0;$i<strlen($cdna);$i++){ @$cod_asci.=''.ord($cdna[$i]); } return $cod_asci; } ?>
Así, nuestro formulario de contacto toma la siguiente forma:
form.php
<?php session_start(); include('funcion_asc.php'); include('antispam.php'); ?><!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8" /> <title>Formulario antispam.</title> <link rel="stylesheet" href="https://www.artesaniaweb.es/arch_dw/estilos_dw.css"> </head> <body> <div align="center"> <h2>Formulario de contacto.</h2> <table width="60%"> <tr><td> <form method="POST" action="procesa.php" name="antispam"> <fieldset> <legend> Contactar </legend> <label for="nombre">Nombre:</label> <input class="cmp100" type="text" id="nombre" name="nombre"> <label for="mail">E-mail:</label> <input class="cmp100" type="email" id="mail" name="mail"/> <label for="clave_new2">Asunto:</label> <input class="cmp100" type="text" id="asunto" name="asunto"/> <label for="mensaje">Mensaje:</label> <textarea class="cmp100" rows="10" id="mensaje" name="mensaje"></textarea> <input type="hidden" name="usu" value=""> <label for="antisp"><b><?php echo "$valorAcod $operacion $valorBcod"; ?> = </b> <input class="cmp15" type="number" id="antisp" name="antisp"></label> <div style="clear: both"></div> <input class="btn_reset" type="reset" value="Limpiar" /> <input class="btn" type="submit" value="Enviar" /> </fieldset> </form> <td><tr> </table> </body> </html>
Ahora vamos a ver como procesamos este formulario.
procesa.php
<?php session_start(); include('funcion_bloqueoIP.php'); $nombre = $_POST['nombre']; $mail = $_POST['mail']; $asunto = $_POST['asunto']; $mensaje = $_POST['mensaje']; $antisp = $_POST['antisp']; $sesion_antisp = $_SESSION['resultado_atsp']; // Recuperamos sesion // Aplicamos la funcion de bloqueo de IPs $ip_bloqueadas = '45.155.204.6|216.244.66.246|157.90.209.81|51.89.201.226|81.41.141.19'; $ip_entrada = $_SERVER['REMOTE_ADDR']; // Si encuentra 45.155.204. la IP esta bloqueada $ip_aceptada = BloqueoIP($ip_bloqueadas,$ip_entrada); if($ip_aceptada == 0){ // IP permitida $aviso = null; }else{ // IP bloqueada $antisp = 9999; $aviso = "<p>La IP $ip_entrada esta bloqueada.</p>"; } if($antisp == $sesion_antisp){ unset($_SESSION['resultado_atsp']); // Eliminamos la sesion // Mostramos los datos enviados echo "<p>$nombre <br /> $mail <br /> $asunto <br /><br /> $mensaje <br /> <hr> La IP $ip_entrada no esta bloqueada.</p>"; }else{ echo "$aviso <p>AntiSpam NO valido.</p>"; } ?>
Vamos a desgranar un poco lo que hemos hecho. Lo primero inicializar las sesiones y cargar la función de bloqueo de IP. Seguidamente recibimos los cuatro campos del formulario mas el campo antispam que introduce el usuario y recogemos la variable de sesión creada en el archivo antispam.php.
El segundo paso será agregar la función de bloqueo de IP, para ello definimos en la variable $ip_bloqueadas un conjunto de direcciones IP (OJO, estas direcciones son arbitrarias, solo es un ejemplo) separadas por pleca “|”a las que queremos denegar el acceso, también capturamos la IP del usuario activo.
Tras aplicar la función, creamos el siguiente condicional:
if($ip_aceptada == 0){ // IP permitida $aviso = null; }else{ // IP bloqueada $antisp = 9999; $aviso = "<p>La IP $ip_entrada esta bloqueada.</p>"; }
Que nos viene a decir, si $ip_aceptada toma el valor 0, no hacemos nada, salvo declarar nula la variable $aviso para que no nos de error.
Si toma el valor 1, y aquí viene lo importante, declaramos la variable $antisp, la que envía el usuario, le asignamos un valor fuera de rango, es decir, un valor mayor que el valor máximo que puede proporcionar antispam.php, que es 11*10=110. De esta forma, como esta variable ($antisp) la declaramos después de que el usuario haya enviado su valor, tomará el nuevo valor, es decir 9999, por lo que nunca podrá coincidir con el valor de la variable $sesion_antisp. De esta forma, el antispam siempre dará como resultado usuario no válido.
if($antisp == $sesion_antisp){ unset($_SESSION['resultado_atsp']); // Eliminamos la sesion // Mostramos los datos enviados echo "<p>$nombre <br /> $mail <br /> $asunto <br /><br /> $mensaje <br /> <hr> La IP $ip_entrada no esta bloqueada.</p>"; }else{ echo "$aviso <p>AntiSpam NO valido.</p>"; }
Cuando se cumple la condición $antisp es igual a $sesion_antisp entonces realizamos las acciones que nos interesa, en este caso, simplemente hemos mostrado en pantalla los datos que envía el usuario. Aquí podríamos poner el código que guarda el mensaje en una base de datos y/o el que envía el mensaje a una dirección de e-mail.
Cuando no se cumple la condición, mostramos el aviso de IP bloqueada, y por tanto, AntiSapam no válido. Si simplemente hay error con el antispam y la IP no esta bloqueada, solo aparecerá AntiSpam NO valido. Por supuesto, el aviso de IP bloqueada, como ejemplo ilustrativo y mientras se trabaja, esta bien, pero en la práctica de su uso, probablemente lo mejor sea omitirlo, eso ya queda a vuestro criterio.
Y con esto, finalizamos la protección de formularios con sistema antispam y bloqueo de IP, sin olvidar, que la validación de datos a nivel de servidor, que aquí no hemos mencionado, es clave.
Tags: Antispam || bloqueo IP || codificación ASC || REMOTE_ADDR || captcha