Información blog

Linux, tutoriales, noticias, sistemas, redes y seguridad informática, entre otras cosas.

viernes, 15 de febrero de 2013

Creación de VPN con openVPN

Una VPN(Virtual Private Network) se trata de una red virtual a la que sólo tienen acceso un número limitado de personas escogidas por el creador de ésta. Esta tecnología ha sido pensada para proteger la información de los numerosos peligros que pueden hacer en la red, tales cómo los hackers.

La red es un lugar peligroso, donde la información circula libremente, estando a disposición de usuarios maliciosos. La red que circula dentro de una red privada es confidencial, pero imaginemos que tenemos un equipo fuera de dicha red, que queramos que tenga acceso a la información del servidor, o de un equipo de la red. Esto es posible hacerlo, pero la información puede ser robada:



Con una VPN garantizamos la integridad de nuestros datos, aseguramos una red privada con IPs virtuales en la que simularíamos una transferencia de datos por un cable físico, siendo imposible que nadie vea el contenido de dicha transferencia. Es por ello que se llama red virtual privada, porque simula las características de una red privada física.




OpenVPN es una de las soluciones existentes para realizar dicha tarea. Su principal punto a favor, es que combina todas bondades de otras soluciones VPN, tales cómo L2Sec e IPSec, aunque tiene la desventaja de que sólo funciona al 100% en los servidores Linux. OpenVPN usa los standards SSL/TLS para cifrar y combinar todas sus características, siendo una buena opción para integrar tanto en entornos domésticos cómo para profesionales. Primero, ante todo debemos pensar la arquitectura de nuestra VPN: ¿Que ip tendrá nuestra VPN? ¿Cuántos clientes tendrá nuestro servidor VPN? El router que esté conectado a nuestro servidor DEBE tener NAT, ¿Tenemos un router que cumpla ese requisito? ¿Son capaces de verse entre sí todos los routers que actuarán en la VPN? Una vez tengamos claras nuestras ideas, lo mejor es hacer un esquema que nos guíe, cómo el que muestro yo cómo ejemplo, ejemplo que seguiré para la explicación de la VPN.



Para empezar hay que instalar openVPN en un servidor Linux, siendo tan fácil cómo instalar apt-get install openvpn. Con esto ya tendríamos la aplicación instalada pero, evidentemente, carece de configuración alguna. Para ello lo primero y más importante es crear los certificados que tendrán tanto nuestro servidor, cómo los clientes; sin esto no se podrá construir VPN alguna. Yo en este caso utilizaré certificados ssl, que no sólo se crean con facilidad, sino que además son muy seguros. Para ello, primero hay que instalar openssl con apt-get install openssl. Una vez instalado el software escribimos cd /usr/lib/ssl/misc, accediendo a la carpeta donde se almacenan los scripts de openssl que serán las herramientas que usaremos para la creación de las licencias. Lo primero y más importante es conceder los permisos necesarios para poder ejecutar dichos scripts. Lo ideal es que sólo nosotros los administradores root, tengamos la posibilidad de ejecutar estos, con lo que escribiremos: chmod 755 –R *. Ya teniendo los permisos, es el momento de crear un nuevo certificado CA, que es indispensable en todos los equipos que usen openVPN, ya sea cliente o servidor. Para ello escribimos ./Ca.sh –newca , con el cual haremos nuestro nuevo certificado. El nombre dejadlo por defecto y la contraseña usad la que os convenga, pero SIEMPRE usad la misma para todos los certificados o claves que generemos a partir de ahora. Con esto ya tendríamos el certificado almacenado en la carpeta demoCA, pero no necesitamos firmarlo para que sea valido, con lo que vamos a la carpeta demora y renombramos el archivo con el nombre “newca.pem” para luego firmarlo mediante esta sentencia:

openssl –x506 –in newca.pem –days 10000 –out cacert.pem –signkey private/cakey.pem

Gracias a esto ya tenemos un certificado CA con una validez de 10000 días; ahora es el turno de hacer los certificados personales para cada equipo, ya sea cliente o servidor. Comenzaremos con el de servidor, para el cual debemos escribir lo siguiente manteniendo el orden:

./CA.sh –newreq Aquí os irá pidiendo algunos datos relativos al equipo. La mayoría de ellos no tienen demasiada importancia pero el Common Name poner un nombre conciso, pues es el nombre que mostrará en cualquier informe de la VPN.
./CA.sh –sign Firmamos el certificado
mv newcert.pem Server-cert.pem Renombramos los certificados creados
mv newkey.pem Server-priv.pem Renombramos los certificados creados

Ahora cómo está. Cada vez que arranquemos el servicio vpn nos pedirá la clave del certificado. Lo cual es engorroso, así que con el siguiente comando haremos que no nos pidan nada:
openssl rsa –in Server-priv.pem –out Server-private.pem






Es recomendable crear una carpeta donde almacenar todo lo referente a claves, certificados, etc… relacionados con vpn. Por ello yo por ejemplo he creado la carpeta “keys” en el directorio de openvpn con el comando mkdir /etc/openvpn/keys y después copiado los ficheros creados ahora ha dicho directorio:
cp Server-cert.pem Server-private.pem /etc/openvpn/keys
cp demoCA/cacert.pem /etc/openvpn/keys

Ya tenemos las claves del servidor creadas y almacenadas adecuadamente para su posible futura gestión. Aún así todavía faltan por incluir dos cosas:

Uno es un tipo de certificado que sólo va en el servidor llamado Diffie Hellman. Para generarlo solo habría que ir a la carpeta keys y escribir: openssl dhparam-out dh1024.pem 1024, generando un archivo llamado dh1024.dh; Lo otro se trata de generar la clave secreta que sólo los miembros de la vpn tendrán mediante el comando:
openvpn –genkey –secret ta.key

Ahora sólo faltarían crear los certificados de los clientes, cuyo proceso no cambia, con lo que yo he hecho el siguiente script para automatizar el proceso:

  1. #!/bin/bash
  2. #Introducir el codigo nombre del cliente
  3. echo 'Introduzca el nombre del cliente'
  4. read cliente
  5. #Se mueve al directorio donde se ejecutan los scripts openssl
  6. cd /usr/lib/ssl/misc
  7. #Se crea el nuevo cliente con su nombre clave, etc...
  8. #Common name debe ser IGUAL al nombre del cliente que hemos introducido
  9. ./CA.sh -newreq
  10. ./CA.sh -sign
  11. #Se renombran los certificados con el nombre del cliente
  12. mv newcert.pem ${cliente}-cert.pem
  13. mv newkey.pem ${cliente}-priv.pem
  14. openssl rsa -in ${cliente}-priv.pem -out ${cliente}-private.pem
  15. #Se copian los certificados a la carpeta adecuada
  16. cp ${cliente}-cert.pem /etc/openvpn/keys/
  17. cp ${cliente}-private.pem /etc/openvpn/keys/
  18. #Mensaje Final
  19. echo 'Cliente introducido correctamente'

Creadas todas las licencias lo primero que hay que hacer siempre también(no importa que sea servidor o cliente), es coger el fichero de configuración de ejemplo y copiarlo en la carpeta openvpn con el comando:

cat /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/openvpn.conf

Ya con la plantilla, la configuración se volvería mucho más fácil. Esta configuración en concreto la haré a partir de mi esquema, pero explicaré los puntos importantes para que podáis configurarlo con la misma facilidad, No escribiré de cabo a rabo todo lo que aparece en el fichero aunque si lo importante:

  1. local 172.24.100.50 #ip en la que escuchará el servidor
  2. port 443 #Puerto de escucha. Por defecto pone 1194 pero este es más eficiente
  3. proto tcp #Protocolo. Por defecto udp, recomendado tcp.
  4. dev tun #Tipo de dispositivo. Ni tocar
  5. ca /etc/openvpn/keys/cacert.pem #Certificado de la CA
  6. cert /etc/openvpn/keys/Server-cert.pem #Certificado del servidor
  7. key /etc/openvpn/keys/Server-key.pem #Clave privada del servidor
  8. dh /etc/openvpn/keys/dh1024.dh #parametros Diffie-Hellman
  9. server 10.0.1.0 255.255.255.0 #Subred de la VPN, poner rango diferente a la red fisica
  10. tls-auth ta.key 0 #Clave de autentificacion
  11. ifconfig-pool-persist /etc/openvpn/keys/ipp.txt #Registro del pool de direcciones
  12. cipher AES-256-CBC #Cifrado AES 256(por defecto Blowfish)
  13. auth SHA1 #Ni tocar
  14. verb 3 #Nivel de log

Esta es la configuración importante y necesaria del servidor VPN. Teniendo todo bien, escribiendo /etc/init.d/openvpn restart debería reiniciarse el servicio a la perfección. La prueba de fuego es escribir ifconfig: Si aparece una nueva interfaz de red llamada tun0 con una ip perteneciente al rango de ip asignado por openVPN, es que tenemos el servidor configurado correctamente.

El servidor está configurado a la perfección. Sólo nos falta que la gente que esté fuera de la red pueda acceder a él, pues sino será imposible crear VPN alguna. Para ello debemos configurar el router y en el apartado NAT, tenemos que hacer que todo lo que vaya al router por tcp, por el puerto 443, se redirija al servidor VPN por el mismo puerto. Aquí es imposible explicar explícitamente cómo hacerlo ya que depende del modelo y fabricante de cada uno, pero las interfaces de configuración son muy intuitivas con lo que sabiendo el concepto de lo que hay que hacer, sólo tenéis que adaptarlo a vuestro dispositivo.

Cómo ya se tiene el entorno servidor preparado, sólo hace falta que los clientes se conecten a dicho server. Para ello sólo hay que instalar openvpn y copiar la plantilla ejemplo cómo se ha hecho en el servidor, pero en la configuración hay unas pequeñas pero significativas variaciones. Al igual que en el apartado servidor, escribiré aquello importante que se debe escribir en el servidor. A cada cliente se le tiene que proporcionar cuatro ficheros que por ejemplo los puede guardar /etc/openvpn/keys: cacert.pem, el certificado del usuario, la clave privada del usuario y el ta.key (autentificación de cliente y servidor).

  1. client #Escribiendo esto especificamos que es un cliente
  2. dev tun #Tipo de dispositivo de rutado. Dejarlo cómo está.
  3. proto tcp #Protocolo tcp. Tiene que ser el mismo que el del servidor
  4. remote 192.168.1.1 443 #IMPORTANTE Hay que poner la dirección publica del ROUTER conectado al servidor. Luego con NAT el router te redirige automáticamente al servidor.
  5. ca /etc/openvpn/keys/cacert.pem #certificado de la CA
  6. cert /etc/openvpn/keys/cliente-cert.pem #Certificado del usuario inventado
  7. key /etc/openvpn/keys/cliente-key.pem #Clave privada del usuario inventado
  8. tls-auth /etc/openvpn/keys/ta.key 1 #Autenticacion
  9. cipher AES-256-CBC #Mismo que el servidor
  10. auth SHA1 #Mismo que el servidor

Para acabar hacemos openvpn /etc/openvpn/client.conf. En caso de lograr conectarse al servidor empezará a lanzar y recibir paquetes en la consola. Sólo hay que pulsar ctrl. + C para parar todos los mensajes que aparecen por pantalla y listo. Ahora escribiendo ifconfig, veréis una nueva interfaz en vuestro cliente llamada tun0 con una de las ips del rango asignado en el servidor VPN, teniendo así nuestro primer cliente conectado a ella. Si tenemos algún problema lo primero es revisar que la red está configurada correctamente, en caso de ir todo bien revisar el NAT del router, y sino revisar la configuración de iptables del servidor.

Y así, hemos logrado una VPN gratuita, potente y segura. Cómo podéis observar, el proceso de creación de una VPN no implica demasiada complejidad. Al principio puede resultar lioso pero es cuestión de dedicarle algo de tiempo y ganas. Cierto que puede resultar a ser laboriosa toda la elaboración de la red, pero es algo que merece la pena.  

Saludos.

viernes, 8 de febrero de 2013

Solución a un bug de crontab en Debian.

Debian, que sobre todo es famoso por su estabilidad, no esta carente de bugs; bugs que nos pueden sorprender en los momentos más inesperados. Uno de éstos, es que cuando realizamos un cambio en el archivo /etc/crontab éste no se refleja; El cambio aparece, pero llegada la fecha y hora en la que debe ejecutarse la nueva tarea programada, no ocurre nada. Esto es debido a un pequeño bug, que por suerte tiene una fácil solución que yo he recopilado en un script al que yo he llamado crontab_reloader.sh que ejecuto cuando realizo cualquier cambio en el fichero crontab.

  1. #!/bin/bash
  2. c1=/etc/crontab
  3. c2=/etc/crontab_old
  4.  
  5. cp ${c1} ${c2}
  6. rm ${c1}
  7. touch ${c1}
  8. cat ${c2} > ${c1}
  9. rm ${c2}
  10. /etc/init.d/cron restart
  11. echo 'cron reloaded successfully'

Con sólo ejecutarlo los cambios se reflejarían correctamente, realizando a la perfección todas las tareas programadas que hemos introducido.  

Cómo evitar los warnigns que nos aparecen al intentar incluir un script en el arranque de Linux.

A menudo habréis podido comprobar que al intentar incluir un script en el arranque de un sistema operativo Linux, éste os muestra una serie de warnings, alertándoos de que vuestro script no posee algunas características recomendables. Esto de momento no es demasiado importante, pues no entorpece el funcionamiento del sistema, pero en recomendable solucionarlo, porque en un futuro no muy lejano será obligatorio incluir aquello.

Todo esto proviene de la política LSB (Linux Estándar Base), que ya está siendo implantada en todas las distribuciones y cuyo objetivo es que todos los sistemas sigan unas directrices comunes para estandarizar algunos procesos, entre ellos el arranque. En vista de la constante ampliación del mundo de Linux, es normal encontrarnos con cosas cómo esta, pero por suerte tienen una fácil solución que, aunque suele ser difícil de memorizar, al ser siempre lo mismo puede ser pegado en un fichero al que podamos recurrir cuando queramos realizar un script de arranque. La solución es bien sencilla:

  1. #!/bin/bash
  2.  
  3. ### BEGIN INIT INFO
  4. # Provides:          Nombre del script
  5. # Required-Start:    $remote_fs $network
  6. # Required-Stop:     $remote_fs $network
  7. # Default-Start:     2 3 4 5
  8. # Default-Stop:      0 1 6
  9. # Short-Description: LSB
  10. # Description:       Codigo indispensable para respetar LSB
  11. ### END INIT INFO

Este sería el código indispensable en el inicio de todos los scripts de arranque. En Provides habría que poner el nombre de vuestro script.  En Required-Start y stop, veréis varios nombres que comienzan con el símbolo del $. Éstos hacen referencia a los servicios que ya tienen que estar arrancados antes de ejecutarse el script y los que he escrito no son obligatorios, pueden ser los que a nosotros nos convengan porque hay varios para elegir, siendo obligatorio poner al menos uno  .Cada uno tiene el siguiente significado:

  • $local_fs: Todo el sistema local ya está montado antes de iniciarse el script.
  • $network: Las interfaces de red ya han sido activadas.
  • $named: El dns y la red en sí ya están 100% operativas.
  • $remote_fs: Todo el sistema de ficheros local y remoto están montados.
  • $syslog: El log del sistema está operativo.
  • $time: La fecha y hora del sistema ya han sido establecidas correctamente.
  • $portmap: El portmapper está disponible.

Yo personalmente veo indispensable poner siempre por lo menos $remote_fs y según que casos, también $network. El resto son más circunstanciales. Luego están Default_start y stop. Aquellos que tengan familiaridad con update-rc.d verán que lo que he es lo mismo que se suele poner con dicho comando. Esto no es necesario modificarlo con dejarlo cómo está vale, mientras que Short_description y Description, no tienen relevancia en el sistema, no importa lo que se ponga pero lo adecuado es poner siempre algo que ayude al usuario cuando vea el script.

miércoles, 6 de febrero de 2013

Freesshd para Windows sus posibilidades para Linuxeros

Esta vez hablaré sobre una aplicación de Windows que a mí personalmente me resulta muy útil. Aplicación que también puede llegar a interesar a los Linuxeros cómo veréis más adelante. La capacidad de que puedan acceder remotamente a tu equipo por ssh puede llegar a sernos de gran ayuda en momentos dados. En Linux con tan sólo escribir apt-get install openssh-server ya tenemos todo solucionado pero en Windows no tenemos ninguna aplicación instalada por defecto que permita la entrada por ssh. Por ello existe una aplicación que una vez instalada y configurada funciona con la misma eficacia que en Linux: Su nombre es Freesshd. Evidentemente hay más aplicaciones, pero ésta en concreto me parece la más adecuada pues ofrece bastantes opciones de configuración, pudiendo personalizarlo a tu gusto. La instalación es increíblemente sencilla. Con tan sólo ir a la página oficial http://www.freesshd.com/ descargarte la última versión e iniciar su instalación nos basta. Habrá un momento dado en el que nos preguntará si queremos que freesshd actúe cómo un servicio que se iniciará al arrancar Windows… Esto lo dejo a libre elección del usuario, tan sólo tenemos que ver nuestras necesidades aunque para ello habría que tener en cuenta lo siguiente: ¿Va a ser un equipo al que vayan a acceder aún sin estar nosotros presentes? ¿O sólo queremos que entren cuando nosotros queramos? ¿Nos interesa que nos cargue la aplicación siempre que iniciemos Windows, ralentizando el tiempo que tarda en iniciarse el sistema? Yo personalmente lo arranco cuando quiero y listo, pues no siempre me es necesario tenerlo activo además de que me gusta acelerar el arranque de Windows lo más posible. Una vez instalada la aplicación, la iniciamos (a menos que sea un servicio pues en ese caso supuestamente debería arrancar solo) y veremos en la zona inferior derecha del escritorio de Windows un icono cómo este: 

Haciendo click derecho sobre él y pulsando en settings, accederíamos a su configuración, observando que la aplicación puede admitir entradas por ssh y/o Telnet. Posee diferentes pestañas, la mayoría no necesitan ser tocadas pero hay 3 pestañas que si que nos interesan. Dos de ellas son evidentes, son SSH y Telnet, en las cuales podemos configurar las dichas conexiones, desde los puertos hasta la shell de comandos (ésta última es muy interesante ya que permite hacer bastantes cosas). Una vez configurado todo, iríamos a otra pestaña a la que es obligatorio entrar. La pestaña se llama users, donde podemos crear los usuarios que podrán acceder al equipo. A la hora de crear usuarios podemos elegir sus permisos o métodos de autentificación. Los permisos van a gusto del administrador aunque yo veo indispensable que al menos puedan usar la shell; En cambio la autentificación recomiendo por cuestiones de seguridad que sea: “password stored as SHA1 bash”, pues así podemos establecer la contraseña que tendría que introducir dicho usuario para poder entrar. Una vez configurado todo sólo habría que ir a la pestaña Server status e inicializar el servidor deseado. En caso de haber un error que diga algo cómo: “The specified address is alredy in use”; Es porque el puerto del servidor que intentas arrancar ya está en uso, con lo que deberíais dejar libre ese puerto o cambiar el puerto en el que quieres que escuche el servidor. Para ver los puertos abiertos en el sistema ve a inicio->ejecutar y escribe cmd.exe. Hecho eso aparecerá una consola donde habría que escribir netstat –a. En la columna “dirección local”, los números o letras que aparezcan después de los: son los puertos. Una vez todo vaya bien y hayáis arrancado uno de los servidores debería apareceros algo cómo esto:



Ahora con tan sólo intentar entrar por Telnet por el puerto que he abierto, introduciendo el usuario y la contraseña adecuada tendría acceso a Windows sin ningún problema, pudiendo gestionar el equipo a distancia. Lo malo es que para saber moverse bien por el sistema se necesitan sendos conocimientos de la línea de comandos Windows, y a decir verdad hay cosas que no puedes hacer con lo que te ofrece cmd… Es cierto que para lo básico no se tiene problema pero aún así a veces es lioso pues muchas veces, de forma inconsciente tecleas comandos Linux o quieres hacer una cosa que en Linux te resulta fácil y aquí no tanto… Por ello estuve buscando una solución ha dicho problema, solución que al final hallé.

Vayamos paso a paso. Lo primero que necesitamos es tener una aplicación que emule una terminal Linux. Hay varias por Internet, yo en este caso he usado Cygwin, una potente aplicación ampliamente personalizable con una gran variedad de herramientas de Linux. Evidentemente no tiene todo lo que tendría una terminal Linux normal, pero puede cubrir la mayoría de sus funcionalidades. La página oficial de la aplicación es esta: http://www.cygwin.com/. Allí tenéis que bajar el setup.exe, que no es más que un cliente que descargará de sus servidores las herramientas necesarias. Una vez descargado, la instalación de la aplicación es sencilla, sólo tenéis que darle a siguiente hasta llegar al apartado de la instalación de paquetes: por defecto está diseñado para instalarte lo básico, aunque podéis escoger los paquetes que más os interesan para instalarlos, esos paquetes se escogen en esta pantalla:

  
Aquí todo está marcado con default por defecto. Eso significa que sólo te instala lo mínimo para que la terminal funcione, con lo que no os fiéis del default. Si hay algún paquete de la lista que os interese, revisad si lo va a instalar o no, si no pone nada es que no lo instala, con lo que lo tendréis que marcar. Los paquetes que yo personalmente veo indispensables son los de admin, ssh, utilidades de red y editores de texto. Una vez seleccionados los paquetes aceptamos y esperamos a que descargue todo, lo cual tardará un buen rato. Con esto ya tendremos nuestra terminal Linux en Windows.

Es recomendable manejarla un poco para familiarizarse con ella. Al principio se nos hará un poco raro, pues al escribir “cd /” y “ls” no veréis el contenido de Windows, sino el contenido de la carpeta Cygwin, pero tranquilos, es normal. Sólo tenéis que ir a la carpeta cygdrive y ahí veréis los discos duros locales. A partir de allí os podréis mover con libertad por el sistema.

Bueno ya somos capaces de movernos por nuestro equipo con la línea de comandos Linux, ahora tenemos que hacer que aquellos que entren en nuestro equipo directamente puedan apreciar la terminal de Linux y no de Windows. Esto es posible gracias a las opciones que Freesshd ofrece. Accediendo a la pestaña SSH o Telnet, observamos que hay un cuadro de texto que dice “Command Shell” con una ruta hacia la consola cmd.exe. Por desgracia, no admite otra terminal que no sea cmd (He hecho infinidad de pruebas y doy fe de ello), al igual que no admite scripts o programas que ejecuten terminales. Por ello hay que aprovechar esa línea para combinar cmd con cygwin. Finalmente, encontré la solución, sólo tenéis que cambiar el contenido del cuadro de texto de esta manera:

Antes: C:\WINDOWS\system32\cmd.exe
Despues: C:\WINDOWS\system32\cmd.exe , "/k /cygwin/cygwin.bat"

Con este sencillo cambio, la próxima vez que alguien entre por SSH o Telnet (dependiendo de en qué pestaña hayáis hecho la modificación, aunque podéis modificar las dos también) verá una terminal de Linux, pudiendo ejecutar sus comandos.

Espero que os haya gustado, cómo siempre, un placer. 

martes, 5 de febrero de 2013

Cap. final de iptables: La tabla mangle

La tabla mangle es con diferencia la menos usada de las tres que he explicado, pero yo creo que tiene su importancia pues se pueden llegar a hacer cosas interesantes con ella.  Cosas que de otra manera nos sería imposible de realizar. Por desgracia, esta tabla de por sí sola no hace gran cosa, pues la mayor parte de sus funcionalidades trabajan en conjunto con iproute2, que es la forma en la que llaman el conjunto ip route + ip rule. Por eso es conveniente explicar brevemente la herramienta ip, que es la herramienta que contiene aquellas utilidades entres otras.

Ip es una relativametne nueva herramienta de Linux que pronto derrocará por completo los antiguos comandos cómo ifconfig, arp o route; ya que reúne todas las funcionalidades de gestión de red en una sólo herramienta. Ip posee una larga lista de posibilidades, pero hay algunas que son más usadas que otras, por su relevancia en la administración de la red. Para una información más detallada escribir man ip. En este caso daré solo una pequeña explicación general algunas funcionalidades, para luego centrarme en las que en verdad me interesan: ip route e ip rule, que usaremos para que trabajen con la tabla “mangle”.

  • Ip link: Este comando trata las interfaces activas en linux, entre las cuales se incluyen las físicas(tarjetas de red) y/o virtuales. Este comando tiene diferentes posibilidades tales cómo ip link list o ip link show: muestra todas las interfaces con su información; ip link list nombre_dispositivo: muestra la información especifica de uno; ip link set nombre_dispositivo parámetros (up,down,off,on, dynamic on/off, alias [nombre],etc…): Modifica los parámetros FISICOS de la tarjeta, incluida la MAC por ejemplo pero no se puede modificar la ip y todos los cambios que se le hagan deben hacerse con la interfaz desactivada (ip link set dispositivo down).
  • Ip addr: Este comando te permite mostrar, añadir o borrar ips de una interfaz determinada. Todavía no la veo del todo cómoda, pues por ejemplo no me deja editar una ip sino hay que borrar la antigua e introducir la nueva, lo cual es algo engorroso. Ip addr add ip dev dispositivo: añade una ip al dispositivo deseado; Ip addr del ip dev dispositivo: borra una ip del dispositivo deseado; Ip addr show: muestra las direcciones ip de todos los dispositivos pudiendo especificar con el parámetro “dev” la interfaz deseada.
  • Ip neigh: Este comando emula el comando arp, en el cual podemos añadir una nueva entrada o simplemente mostrar aquellas ips que se encuentran dentro de la tabla arp. Los comandos más usados serían; ip neigh show: muestra las ips almacenadas dentro de la tabla arp. Estas ips se agregan cuando se hace ping a una alcanzable que esté dentro de nuestro rango o cuando añadimos una entrada arp o neigh a mano; ip neigh add/del [ip del otro equipo] lladdr [mac de dicha ip] dev [interfaz propia por el que localizaremos esa ip]: Añade o elimina una ip fija a lista de ips alcanzables.
  • Ip route: Este comando es uno de los que nos interesan para que trabaje junto a la tabla mangle de iptables. Se encarga del enrutamiento que tendrá el equipo y puede trabajar en equipo con ip rule. Los comandos más usados de ip route serían; ip route list: muestra las diferentes rutas y puertas de enlace configurados por el sistema; ip route add default via [ip de la puerta de enlace] dev [dispositivo enlazado a dicha puerta] table [nombre de la tabla]: Establece la puerta de enlace que tendrá la interfaz, el parámetro table es opcional, pero cuando trabajemos con mangle e ip rule será necesario y por eso lo menciono aunque explicaré su significado más adelante.
  • Ip rule: Este comando decide que ruta utilizar siguiendo ciertas reglas cómo por ejemplo la marca que tengan los paquetes. La explicación de este apartado sería bastante tediosa con lo que me centraré en los dos comandos más usados. Ip rule list: Muestra la lista de todas las reglas y sus acciones; ip rule add fwmark [numero] table [número o nombre de la tabla]: Dice que todo aquello de tenga la marca X (por ejemplo 1) se asigne automáticamente a la tabla deseada.

Llegados a este punto hablaré sobre las tablas, las cuales han sido mencionadas ya dos veces. Una tabla almacena las reglas de enrutamiento bajo una misma directiva, haciendo que todo aquello que se asigne a dicha tabla siga las directrices marcadas en dicha tabla. Las tablas van de 1 al 255 aunque las numero 255,254 y 253 están reservadas. Es recomendable no usar ninguna tabla que esté por debajo del número 200, cosa aconsejada por los desarrolladores del kernel de Linux. Cada tabla puede ser llamada haciendo referencia a su número, pero cómo todos somos humanos y nuestra memoria no es perfecta, es recomendable asignarle un nombre a cada tabla sobre la que queramos trabajar. Para eso escribimos echo [numero de tabla] [nombre] >> /etc/iproute2/rt_tables. ¡Importante poner >> y no > si no queremos eliminar el antiguo contenido del fichero! Ejemplo: echo 200 marcador >> /etc/iproute2/rt_tables.

Con esto ya tenemos una noción muy básica de lo que es capaz de hacer ip. Todavía puede hacer más cosas cómo el balanceo de carga o definición de tuneles pero con lo que ya sabemos nos es suficiente cómo para trabajar con iproute + iprule. Ahora nos falta conocer que podemos hacer con la tabla mangle:

La tabla mangle es muy sencilla una vez conocidas las tablas NAT y filter. Trabaja con las mismas cadenas que NAT además de usar la cadena FORWARD, aunque las más usadas y útiles son PREROUTING y POSTROUTING. Mangle al igual que NAT sirve para alterar paquetes, pero de forma mucho más sutil que su compañero. Esta tabla no cambia la ip ni hace nada que sea “visible” a primera vista, pero esas sutiles transformaciones pueden ser de gran ayuda dependiendo de nuestras necesidades. Para hacer dichas alteraciones su usan tres targets, aunque uno de ellos está en una fase muy temprana y no es recomendable usarlo pues no es apenas soportado y está en fase de desarrollo, con lo que sólo hablare de los dos que son “estables”.

  • TTL: El target TTL (Time To Live), sirve para establecer o modificar el tiempo de vida que tendrán los paquetes que cumplan la regla impuesta en iptables. Ello hace que los paquetes se destruyan pasar por X puntos o equipos o que todos los paquetes posean el mismo tiempo de vida. El target TTL tiene las siguientes opciones: TTL --ttl-set (numero): Establece un tiempo de vida exacto a los paquetes; TTL --ttl-dec (numero): Acorta el tiempo de vida en un número determinado de paquetes. Para este caso lo mejor sería poner un ejemplo:

Iptables –t mangle –A PREROUTING –i eth0 –j TTL --ttl-dec 2

Aquí decimos que todos los paquetes que lleguen por la interfaz eth0 acorten su tiempo de vida en 2. Es decir que si el tiempo de vida que tiene al llegar al equipo es de 60, su TTL pasaría a ser 58.

Evidentemente, al igual que podemos acortar su vida, también podemos alargarla mediante --ttl-inc (numero).

  • MARK: El target MARK es el más famoso de la tabla mangle. Sirve para marcar los paquetes que cumplan la regla impuesta en iptables. Esta marca sólo se mantiene dentro del equipo, una vez el paquete salga, dicha marca desaparece y sólo puede ser una marca numérica de 32 bits. Este target sólo tiene una opción que sirve para establecer la marca mediante MARK --set-mark. Ejemplo:

Iptables –t mangle –A PREROUTING –i eth0 –p tcp --dport 80 –j MARK --set-mark 1

En este caso todos los paquetes que hayan entrado por el puerto 80 mediante la interfaz eth0 han sido marcados con el número 1. El marcado de paquetes de por sí es inútil, pero combinado con iproute e iprule podemos hacer que los paquetes marcados con el número 1 sigan una ruta distinta del resto.

Con esto ya conocemos la tabla mangle. La modificación de la TTL es obvia, pero el marcado de paquetes y su utilidad todavía no ha quedado demasiado claro con lo que lo mejor será exponer un pequeño pero esclarecedor caso práctico con los pasos a seguir al respecto. Antes de explicar nada es indispensable (al igual que en NAT) tener el ip_forward igualado a 1, con lo que haremos (si es que no lo tenemos hecho ya):

echo 1 > /proc/sys/net/ipv4/ip_forward

Bien ahora os mostraré el esquema de este sencillo ejemplo:



Queremos gestionar que algunos paquetes generados por el equipo salgan por una puerta de enlace y otros por la otra, dependiendo del puerto. Primero añadimos dos tablas que representarán los dos routers:

echo 200 router1 >> /etc/iproute2/rt_tables
echo 201 router2 >> /etc/iproute2/rt_tables

Luego hacemos que cada tabla tenga asignada una marca especifica. Esto va a nuestro gusto pero para mantener una estructura les asignaremos las marcas 1 y 2.

ip rule add fwmark 1 table router1
ip rule add fwmark 2 table router2

Ahora asociamos las tablas a las puertas de enlace, en este caso los routers, teniendo en cuenta que dichas tablas harán que todos los paquetes con la misma marca que las tablas, vayan por la puerta de enlace de dichas tablas.

ip route add default via 192.168.1.1 dev eth0 table router1
ip route add default via 192.168.2.1 dev eth1 table router2

Con esto ya tenemos nuestras tablas preparadas para que todos los paquetes con las marcas 1 y 2 vayan por sus respectivos gateways. Ahora necesitamos marcar nuestros paquetes y para eso tenemos la tabla mangle. Una vez más yo recomiendo hacer un script que se ejecute en el arranque de Linux para tener las reglas activadas desde el arranque.

  1. #!/bin/bash
  2.  
  3. ### BEGIN INIT INFO
  4. # Provides:          Nombre del script
  5. # Required-Start:    $remote_fs  
  6. # Required-Stop:     $remote_fs  
  7. # Default-Start:     2 3 4 5
  8. # Default-Stop:      0 1 6
  9. # Short-Description: LSB
  10. # Description:       Codigo indispensable para respetar LSB
  11. ### END INIT INFO
  12.  
  13. iptables –t mangle –A OUTPUT –p tcp --dport 80 –j MARK --set-mark 1
  14. iptables –t mangle –A OUTPUT –p tcp --dport 22 –j MARK --set-mark 2
  15. iptables –t mangle –A OUTPUT –p tcp --dport 110 –j MARK --set-mark 1
  16. iptables –t mangle –A OUTPUT –p tcp --dport 20:21 –j MARK --set-mark 2
  17. iptables –t mangle –A OUTPUT –p tcp --dport 443 –j MARK –set-mark 1

Un pequeño pero funcional código que hace que los paquetes generados que pasen por el puerto 80,110 y 443 pasarán a través del ROUTER1 mientras que los paquetes que pasen por el puerto 20,21 y 22 pasarán por ROUTER2. Son casos rebuscados y poco usados pero que a veces pueden llegar a ser útiles. Sólo se necesita saber combinar iptables e iproute/iprule para encontrar la solución adecuada.

Espero que os haya resultado útil, un placer.

Configuración de NAT con iptables

Ahora que ya se conoce el funcionamiento general de iptables. Hablaré de otra tabla bastante usada en Linux. Se trata de NAT(Network Address Translation). Esta vez seré más breve que en el anterior manual pues se supone que ya poseemos algunos conocimientos fundamentales. Por ello me enfocaré en la materia en sí, que trata de lo que es capaz de hacer NAT y de sus parámetros.

La tabla de NAT, es la encargada del redireccionamiento y enmascaramiento de los paquetes de red. Esto es realmente útil en servidores, equipos que actúan cómo firewall o equipos de relevancia en la red.

La tabla NAT está formada de tres cadenas:

  • PREROUTING:Esta cadena redirige los paquetes entrantes antes de enroutarlos
  • POSTROUTING: Esta cadena modifica los paquetes justo antes de enviarlos
  • OUTPUT: Sólo altera los paquetes generados localmente por el propio equipo.

Cuidado con el orden de las reglas escritas, pues la primera tiene prioridad. Es decir que si un paquete encuentra una regla que lo define, aún habiendo más tarde otra que también; ejecutará hará caso a la primera y hará lo que esta le diga.

Para que NAT pueda hacer su tarea es necesario hacer una acción previa de importancia vital. No importa que nuestras reglas estén escritas perfectamente pues no harán nada si no escribimos el siguiente comando antes.

echo '1' > /proc/sys/net/ipv4/ip_forward

Este comando debe hacerse cada vez que arranque el ordenador o sino editar el fichero /etc/systlc.conf y allí donde pone #net.ipv4.ip_forward=1 quitar # para que así hacer que dicho cambio sea permanente. Con ello nos aseguramos que en caso de que no haga caso de una regla, sea por que está mal escrita no porque nos falte algo por hacer.

NAT puede tomar tres acciones, las cuales dependen directamente de las cadenas que se usen, ya que algunas solo pueden ser usada con ciertas cadenas. Pero antes mostraré un esquema del entorno sobre el que se efectuará la explicación.


DNAT: Esta acción redirige todos los paquetes que vayan al servidor hacia otra dirección. Esta acción solo puede realizarse en las cadenas PREROUTING, pues trata los paquetes entrantes. DNAT siempre va seguido de --to dirección de destino a la que queremos redirigir los paquetes. Por ejemplo podemos hacer que un equipo de la red privada aloje un servicio accesible desde Internet desde el puerto 4444. Por ejemplo que posea un servicio instalado, el cual es accesible localmente por el puerto 880. En la red local habría que escribir la dirección del equipo en un navegador. Ej: 172.25.1.5:880. Para poder acceder desde fuera de la red local, habría que escribir lo siguiente.

iptables –t NAT –A PREROUTING –p tcp --dport 444 –i eth0 –j DNAT --to 172.25.1.5:880

Con esta regla activada, escribiendo esto: 192.168.1.1:4444 desde el exterior accederíamos al 172.25.1.5:880 de la red privada. Este caso es puramente hipotético, ya que hay que tener más cosas en cuenta cómo el router (que debería poseer NAT también), el cual habría que configurar también, pero eso es un tema aparte. Este ejemplo solo es para explicar el funcionamiento de DNAT.

SNAT: Esta acción hace que todos los paquetes salientes que cumplan cierta regla adquieran la ip que nosotros le mandemos “ocultando” su verdadera ip. Esta acción solo se puede hacer en las cadenas OUTPUT o POSTROUTING, aunque por lo general es usado sólo para las cadenas POSTROUTING. Esto es útil cuando tenemos ciertos equipos dentro de una red privada que está oculta a la red pública. Por ejemplo hacemos que los paquetes mandados desde equipos dentro de una red privada, se transformen en una ip que pueda comunicarse con el exterior por la interfaz eth0 y que además puede recibir respuesta. Es decir, que se pueda navegar por Internet o tener comunicación con equipos fuera de la red privada. Para ello habría que hacer lo siguiente:

iptables –t NAT –A POSTROUTING –s 172.25.1.0/24 –o eth0 –j SNAT --to 192.168.1.1

En este caso hemos camuflado todos los paquetes que vengan de la red privada con la ip de la tarjeta eth0 del servidor.

MASQUERADE: Posee la misma funcionalidad que SNAT, pero en este caso calcula automáticamente la ip de la tarjeta de salida. Es decir que en vez de poner –j SNAT –to ip de la tarjeta de salida, si pusiésemos MASQUERADE tendríamos el mismo resultado. ¿Entonces cuando saber si poner una u otra? El calculo de la ip de la tarjeta de red por la que saldrán los paquetes, consume una pequeña cantidad recursos del servidor, cosa que no siempre nos interesa. MASQUERADE es útil si la tarjeta de red por la que salen los datos, recibe su ip de un DHCP (Dynamic Host Configuration Protocol), ya que en algún momento dado, por las razones que sean, la tarjeta de red de salida podría recibir una ip distinta, arruinando nuestra regla e impidiendo la salida a Internet de los equipos de la red privada. Pongamos el anterior ejemplo adaptado a MASQUERADE:

iptables –t NAT –A POSTROUTING –s 172.25.1.0/24 –o eth0 –j MASQUERADE

MASQUERADE siempre enmascara los paquetes con la ip de la tarjeta de red por la que salen los paquetes.

Cómo podéis ver el manejo de la tabla NAT de iptables es relativamente fácil. Sólo se debe tener bien claro lo que se desea hacer antes de plasmarlo en las reglas que queramos escribir y podremos hacer lo que queramos. En este caso no haré un script, pues aquí no existe un “Standard”, sino que todo depende de las necesidades de cada uno. Recordad que todas las reglas que hagamos deben incluirse en un script de inicio y que ip_foward debe ser igual a 1.

Las posibilidades de esta tabla son infinitas, sólo se necesita un poco de imaginación. 

domingo, 3 de febrero de 2013

Iptables y su relevancia en la protección de Linux

Habiendo abierto el tema de la seguridad, voy esta vez voy a hablar de otro aspecto fundamental en la protección de un equipo con sistema operativo Linux. Esta vez voy a hablar de iptables, una herramienta instalada por defecto que viene sin configuración alguna, haciendo que así sin más no sea útil para nada. Aún así, es una herramienta que es muy importante saber manejar, ya que dependeremos de ella para mantener seguro nuestro equipo.

Iptables se trata de un software instalado por defecto en Linux cuya funcionalidad más famosa es la de hacer de cortafuegos aunque en realidad se trata más bien de un filtro de paquetes ipv4 que los trata de diferentes formas según nuestras necesidades. Muchos usuarios conocen su existencia aunque pocos se atreven a manejarlo debido a que al principio resulta dificultoso y tedioso establecer cualquier tipo de cambio en el software desde la línea de comandos. Yo mismo tuve mis problemas al principio, aunque con un poco de práctica, uno puede entender las funcionalidades básicas y atreverse a aplicarlas sin tener que andar haciendo constantemente copy paste del código que se topa por Internet. Las posibilidades de iptables son tantas y tan amplias que es imposible escribirlas por aquí sin hacer que al lector le entre el sopor; para todo aquel que quiera ver la información completa y detallada de iptables le recomiendo escribir en la línea de comandos: man iptables. Allí aparecerá toda la información referente a él, yo solamente explicaré el manejo básico. Antes de empezar es conveniente explicar unos pocos conceptos elementales:


Una cadena es una lista de reglas que reúnen una serie de paquetes para su posterior tratamiento. Por ejemplo una cadena es una lista de reglas cuyo factor común es que provienen del exterior hacia nuestro equipo. Estas reglas ya vienen predefinidas aunque un usuario avanzado puede querer decidir crear sus propias reglas

Un “target” u objetivo, es la acción que se realiza en caso de que una regla se cumpla. En iptables se denominan targets aunque para que tengáis una mejor visión mental pensar en ellas cómo acciones.

Una tabla es la encargada de realizar las diferentes acciones que le mandemos. Digamos que cada tabla es una “oficina” encargada de una tarea específica que tan sólo ella puede hacer. Cada tabla reúne un conjunto de cadenas especificas, ya sean predefinidas o definidas por el usuario y son especificadas con el parámetro -t.

No importa sobre que tabla actuemos, podemos ejecutar los mismos comandos sobre todas por igual. Estos son algunos de ellos:

  • -A: Añade una regla a la tabla y cadena especifica.
  • -D: Borra una regla de la tabla y cadena especificada
  • -I : Inserta una regla en una posición especifica de la cadena y regla deseada. Si escribimos la posición 1, será la primera regla. Para este comando se escribe iptables –I numero. Ej: iptables –I 1 ….
  • -R: Sustituye una regla situada en una posición X. Funciona igual que iptables –I.
  • -P: política general de la tabla y cadena especifica. Digamos que si usamos esta cadena diremos luego el “target” que tendrá la cadena en general. Si usamos –P el “target” se especificara acto seguido sin parámetro alguno de por medio. Digamos la política es la regla predominante de la tabla y cadena especificada a menos que le indiquemos lo contrario.
  • -F: Borra todas las reglas de todas las cadenas de la tabla
  • -L: Lista simple de las reglas de una tabla especifica
  • -nvL: Lista detallada de las reglas de una tabla especifica
  • -N: Crea una cadena personalizada
  • -E: Renombra una cadena. Esto solo afecta al nombre, no al funcionamiento de ésta, y será un detalle meramente visual que no hará conflicto con lo ya creado hasta ahora.

Cómo todo comando, las tablas también usan parámetros, estos son algunos de ellos:
  • -p= protocolo
  • -s= dirección ip, host o nombre del dominio de origen.
  • -d= dirección de destino.
  • -i= interfaz de por donde los paquetes van a entrar
  • -o= interfaz por donde saldrán los paquetes.
  • -j= la acción a tomar tras una vez localizado el paquete. Ésta varía según la tabla en la que nos encontremos.

Hay muchísimos más parámetros, pero estos son mucho más complejos y suelen ir seguidos de –m “parámetro” --“subparametro”… Excepto si dicho parámetro maestro ya ha sido nombrado de manera implícita antes cómo –p por ejemplo el cual hace que no necesitemos usar –m. En este caso el comando sería –p “protocolo” --“subparametro”. Entre estos parámetros y subparametros yo veo uno que es esencial saberlo y además es muy fácil de aprender; se trata del subparametro --dport que especifica el número de puerto que revisará la regla. Pongamos un ejemplo muy simple.

iptables –t filter –A OUTPUT –o eth0 –p tcp --dport 80 –j REJECT.

¿Fácil verdad? Aquí decimos que todo aquello que salga por la interfaz de red llamada eth0, usando el protocolo tcp, en caso de querer pasar por el puerto 80 no pueda hacerlo. No os preocupéis sobre el OUTPUT y el REJECT, basta saber que OUTPUT es una cadena y REJECT es un “target”. Más adelante veréis el significado de éstos.

Existen 4 tablas, pero la cuarta apenas se usa nunca con lo que muchos solo cuentan cómo que solo existen tres, y en mi experiencia puedo decir que no he tenido que usar la cuarta, aún así os diré su nombre; el nombre de la cuarta tabla es raw y sirve para “no vigilar” ciertas conexiones que cumplan las reglas que introduzcamos en esta tabla. Para usar cualquiera de éstas debemos escribir –t seguido del nombre de la tabla. Comencemos con la más famosa y usada, que es la que hace de cortafuegos.

Filter: Esta es la tabla que toma por defecto iptables, es decir que en caso de no especificar ninguna, siempre se dará por hecho de que se trata con ésta, cosa que hace que algunos piensen que iptables sólo tiene una función, nada más lejos de la verdad. Esta tabla es la encargada de filtrar los paquetes. Usa cadenas INPUT, OUTPUT y FORWARD. INPUT es una cadena que reúne todo aquello que entra en el equipo, output de todo lo que sale y forward de todo aquello que se reenvía a otra ip o puerto.

Las acciones a tomar en esta tabla serían las siguientes:

ACCEPT Deja que el paquete llegue a su destino
REJECT No le deja pasar al paquete, e informa a aquel que ha intentado lanzar el paquete por dicha vía que no puede pasar por allí.
DROP No le deja pasar al paquete y además no informa de ello.
LOG Registra en el log que cierta ip con cierta mac ha pasado por el filtro.

El mejor ejemplo sería una sentencia cómo esta:

      iptables -A INPUT -s 192.168.0.0/24 -d 192.168.5.0 -p tcp -j ACCEPT

Aquí especificamos que un paquete que llegue desde cualquier ordenador con la ip 192.168.X.X (X significa lo que sea) hacia la ip 192.168.5.X (es decir a toda ip que empiece por 192.168.5) por protocolo tcp, pase por el filtro sin problemas, es decir, que llegue al destinatario. Eso de por sí puede no tener sentido, pues si solo tuviésemos esta regla, llegaría igualmente; pero si por ejemplo, hubiésemos hecho una regla que denegase el acceso, si no pusiésemos esta regla el paquete no llegaría.

Por ejemplo si hubiésemos escrito esto:

iptables -A INPUT -s 192.168.0.0/24 -j REJECT

Con esta regla habríamos denegado a todos los ordenadores procedentes de 192.168. X.X cualquier acceso a cualquier ip sin importar el protocolo que use o el puerto por el que acceda y solo usando la regla escrita anteriormente, cumpliendo las condiciones escritas en ésta, podríamos tener acceso a los ordenadores 192.168.5.X

Algunos os preguntareis si se puede usar iptables con ipv6. La respuesta es sí, pero para ello no sirve iptables, sino que se usa ip6tables, que tiene los mismos comandos y parámetros, sólo que está orientado a ipv6.

Bien, con esto ya se puede decir que aunque estamos lejos de decir que “sabemos” iptables, si que podemos hacer algunos filtros para que no entren intrusos indeseados con lo que vamos a ello: La seguridad del firewall que voy a hacer es simple y rudimentaria, pero al menos nos mantendrá protegidos de la mayoría de intrusiones indeseadas, pues solo dejaré abiertos entre 3 y 4 puertos, el 80 (Internet), el 22 (ssh. Para poder acceder por este puerto a linux debemos instalar openssh-server. Este servicio hace que podamos acceder remotamente al equipo de forma segura), el 53(DNS) y 21(ftp, este es opcional).Evidentemente, si queremos dejar alguno más abierto podemos hacerlo, pero para ello recomiendo poner unas restricciones muy especificas que solo dejen que acceda una ip(o un pequeño rango de ips) especifico.

Antes de nada yo recomiendo reunir todos los comandos en un script, pues si más adelante hacemos algún cambio indeseado en iptables, siempre podremos limpiar iptables y volver a lanzar los comandos sin introducir nada, además de que el introducir los comandos a mano no es nada practico cómo luego veremos. Aparte, podemos guardar el script en un USB para que cuando instalemos otro Linux nos evitemos volver a meter los comandos, ya sean los que he puesto yo aquí o los que introduzcáis vosotros. Si no tenéis conocimientos de shell script no pasa nada pues si seguís los pasos, os debería funcionar a la perfección.

Para ello usamos el editor que más nos guste (mcedit, nano, vi…) y creamos un fichero que yo por ejemplo titularía iptables.sh, y lo alojaría en el directorio /etc/init.d (luego veréis porqué). En caso de querer ponerle otro nombre recordad poner al final siempre .sh, ya que es la extensión que usan los scripts.


  1. ############SCRIPT DE CREACIÓN UN FIREWALL BÁSICO#############
  2. #!/bin/bash
  3. ### BEGIN INIT INFO
  4. # Provides:          Nombre del script
  5. # Required-Start:    $remote_fs  
  6. # Required-Stop:     $remote_fs  
  7. # Default-Start:     2 3 4 5
  8. #!/bin/bash
  9. #inicio indispensable en todo script
  10. #No es indispensable, pero si recomendable escribir
  11. ### BEGIN INIT INFO
  12. # Provides: iptables.sh
  13. # Required-Start: $syslog
  14. # Required-Stop: $syslog
  15. # Default-Start: 2 3 4 5
  16. # Default-Stop: 0 1 6
  17. # Short-Description: blabla
  18. # Description:
  19. #
  20. ### END INIT INFO
  21. #Primero hacemos que no nos puedan hacer ping.
  22. #Esto no es parte de iptables pero es recomendable hacerlo
  23. echo '1' > /proc/sys/net/ipv4/icmp_echo_ignore_all
  24. echo '1' >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
  25. #Partiendo de la base de que estamos en un entorno domestico
  26. #pensamos en que nos interesa salir al exterior sin restricciones,
  27. #pero que solo queremos que entre el trafico justo a nuestro ordenador
  28. #es decir Internet, ssh y el DNS
  29. #Las politicas por defectos son ACCEPT pero me gusta escribirlas
  30. #Por si en un futuro quisiese editarlo
  31. #Cómo queremos tener por defecto todo bloqueado,
  32. #hacemos que la politica INPUT bloquee todo el acceso abriendo solo lo que nos interesa
  33. iptables -P INPUT DROP
  34. iptables -P FORWARD ACCEPT
  35. iptables -P OUTPUT ACCEPT
  36. #Permitimos el acceso del propio equipo al localhost
  37. iptables -A INPUT -i lo -j ACCEPT
  38. #Dejamos abierto el puerto 80 para permitir el acceso a Internet.
  39. #si no abrimos este puerto no podremos tener contacto con el exterior.
  40. iptables -A INPUT -p tcp --dport 80 -j ACCEPT
  41. iptables -A INPUT -p udp --dport 80 -j ACCEPT
  42. #Dejamos abierto el puerto por ssh.
  43. iptables -A INPUT -p tcp --dport 22 -j ACCEPT
  44. #DNS
  45. iptables -A INPUT -p tcp --dport 53 -j ACCEPT
  46. iptables -A INPUT -p udp --dport 53 -j ACCEPT
  47. #Opcional Esto es por si quisiesemos acceder por ftp
  48. iptables -A INPUT -p tcp --dport 21 -j ACCEPT
  49. iptables -A INPUT -p udp --dport 21 -j ACCEPT
  50. #Por otro lado está el olvidado, pero importante ipv6,
  51. #el cual también necesita un trato a menos que queramos que aprovechen esa entrada.
  52. #Si tenemos ipv6 deshabilitado no tenemos que preocuparnos de nada, de esto.
  53. #En caso contrario habría que escribir las mismas reglas que arriba pero orientadas a ipv6.
  54. ip6tables -P INPUT DROP
  55. ip6tables -P FORWARD ACCEPT
  56. ip6tables -P OUTPUT ACCEPT
  57. ip6tables -A INPUT -i lo -j ACCEPT
  58. ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
  59. ip6tables -A INPUT -p udp --dport 80 -j ACCEPT
  60. ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
  61. ip6tables -A INPUT -p tcp --dport 53 -j ACCEPT
  62. ip6tables -A INPUT -p udp --dport 53 -j ACCEPT
  63. ip6tables -A INPUT -p tcp --dport 21 -j ACCEPT
  64. ip6tables -A INPUT -p udp --dport 21 -j ACCEPT

Con esto ya tenemos un script básico, pero perfectamente funcional que nos protegerá de la mayoría de las amenazas. Esto hace que podamos usar el pc con normalidad aunque si queremos usar alguna aplicación que requiera tener un puerto nuestro abierto deberemos configurar iptables para que permita el paso. Ya terminado esto lo guardamos y salimos del editor para después escribir:
Chmod 755 iptables.sh
./iptables.sh

Como saber si funcionan nuestros cambios:

Prueba 1:
Escribir iptables –nvL y ip6tables –nvL. Deberían mostrarse las reglas creadas mediante el script.
Prueba 2:
Probamos nuestra salida a internet escribiendo en consola apt-get update o instalando alguna aplicación mediante el método que prefiráis.
Prueba 3:
Para esta prueba se necesitan tener dos equipos, a menos que tengas instalado linux en una maquina virtual, con lo cual podrías hacer la prueba. Uno es nuestro linux, el otro puede ser un portátil o lo que sea.


Requisitos para la prueba:
  • Tener los dos pcs en el mismo rango de ip. Ejemplo:

PC linux: 192.168.1.10 Mascara: 255.255.255.0
PC externo: 192.168.1.15 Mascara 255.255.255.0

Si tienes una red con un DHCP (es decir que obtengas la ip sin que tengas que configurar nada a mano), y tienes los dos equipos obteniendo ip por ese DHCP, no tienes que preocuparte de saber si están en el mismo rango. En las redes domesticas el router te proveen de ip automáticamente, con lo que tan solo asegúrate de tener los dos equipos conectados a la red.
  • Instalar Filezilla Client en el ordenador desde el que queremos acceder a linux. Hay más vías, pero creo que esta es la más sencilla.

Abrimos Filezilla y escribimos en la sección servidor la ip del equipo Linux (en caso de no saberla ejecutar ifconfig en Linux). Luego introducimos el usuario y contraseña (cómo si fueses a entrar en Linux) y usamos el puerto 22. Si nos deja el acceso, es que tenemos acceso al puerto 22. Podemos hacer la misma prueba usando ipv6 si queremos estar seguros.

Por último. Aprovechando que estamos en el mismo rango de ip probaremos a hacerle ping al equipo. Abrimos una consola ya sea en Linux o en Windows y escribimos ping ip del equipo protegido. Veréis que el equipo no responde a la llamada pues hemos hecho que haga caso omiso a ese tipo de peticiones.

Ya tenemos un ordenador protegido de amenazas exteriores pero hay un pequeño problema… Los cambios no se guardarán iptables ni en ip6tables una vez apaguemos el sistema… Eso significa que al reiniciar el equipo volveremos a estar desprotegidos… ¿cómo resolver eso? Claro podemos volver a ejecutar manualmente el script cómo antes, pero eso requeriría que nos acordásemos de ejecutarlo siempre que encendamos Linux, cosa tediosa y engorrosa. Por ello, la solución más practica es que se ejecute el script al iniciar el sistema (he ahí la razón por la que recomiendo hacer el script, guardándolo en /etc/init.d). El tener el script situado en el directorio antes mencionado, nos da la opción de ejecutarlo en el arranque, aunque para ello necesitamos escribir uno de los siguientes comandos (no importa cual, yo pongo las dos opciones):

update-rc.d iptables.sh defaults” o “insserv iptables.sh”

Ambos hacen lo mismo pero lo malo es que insserv no se usa en las versiones antiguas de linux, mientras que en las nuevas aunque las dos formas están admitidas, es más recomendable usar insserv, pues probablemente, dentro de poco sustituirá por completo update-rcd.

Con esto ya tendríamos nuestro equipo protegido desde el arranque, recordad que hay aplicaciones que requieren tener puertos abiertos con lo que si no os funcionan dichas aplicaciones, tendréis que editar iptables abriendo los puertos adecuados.

Espero que os haya sido útil. 

Un saludo.