Firewall: Fundamentos y configuración para principiantes PDF
Document Details

Uploaded by RobustSurrealism527
Tags
Summary
Este documento explica los fundamentos de los cortafuegos o firewalls, cubriendo conceptos como reglas, cadenas, tablas y el uso de iptables en Linux. El documento explora la configuración de firewalls estadoful, el seguimiento de conexiones y los parámetros de iptables, proporcionando lo esencial para la seguridad de redes.
Full Transcript
UNIDAD 06. EL FIREWALL 6.1. Introducción Video: https://www.youtube.com/watch?v=kDEX1HXybrU Una de las medidas de seguridad perimetral más importantes, si no la más, es el cortafuegos o firewall. Un cortafuegos es un sistema que analiza los paquetes que entran por sus interfaces de red y,...
UNIDAD 06. EL FIREWALL 6.1. Introducción Video: https://www.youtube.com/watch?v=kDEX1HXybrU Una de las medidas de seguridad perimetral más importantes, si no la más, es el cortafuegos o firewall. Un cortafuegos es un sistema que analiza los paquetes que entran por sus interfaces de red y, basándose en un conjunto de reglas definidas por el administrador, toma una decisión sobre qué hacer con cada uno de ellos, es decir, lleva a cabo una acción. Dicha acción, en definitiva, consistirá en aceptarlo (dejarlo pasar) o rechazarlo (descartarlo). Podemos afirmar que todos los routers son, en esencia, cortafuegos. La diferencia entre unos y otros está en si su firmware pone a disposición del administrador (o no) la capacidad de establecer reglas. Por ejemplo, los routers domésticos, orientados a un público inexperto cuya única preocupación es disponer de acceso a internet, incorporan un cortafuegos predefinido que solo admite mínimas opciones de configuración. Dichos cortafuegos básicos se basan en las siguientes reglas: Dejar salir cualquier paquete de la red interna (LAN) hacia la interfaz de red de internet (WAN). Rechazar cualquier paquete proveniente de internet (WAN), excepto aquellos que sean respuesta a una solicitud previa, es decir, pertenezcan a una conexión saliente establecida en virtud de la regla anterior. Aunque esto proporciona una protección excelente para usuarios domésticos, no satisface las necesidades del entorno profesional. En el siguiente enlace puedes acceder a un simulador online de la configuración de un router CISCO. Localiza la sección donde se gestiona el Firewall, y experimenta estableciendo algunas opciones y añadiendo algunas reglas. https://www.cisco.com/assets/sol/sb/RV260_Emulators/RV260_Emulator_v1-0-00-14 /index.htm#/systemSummary Los cortafuegos profesionales suelen ser routers que suelen tener entre 4 y 24 interfaces de red (4 son suficientes para la mayoría de las pequeñas empresas), y con un firmware que permite especificar con todo detalle las reglas del cortafuegos. Son los denominados cortafuegos hardware, como es el caso de los pfSense, Mikrotik, WatchGuard, etc., y, por supuesto, los Cisco para grandes empresas. Pero cualquier equipo con dos o más interfaces de red y que enrute tráfico de red puede hacer las funciones de cortafuegos con el software adecuado (cortafuegos software). Algunas de las marcas de cortafuegos hardware ponen a disposición del público su sistema operativo interno para poder instalarlo en equipos PC, como es el caso de Mikrotik con su RouterOS. Por otro lado, también existen cortafuegos open source como son los casos de OPNSense y pfSense, este último disponible también en versión hardware (comercial). En los siguientes enlaces podrás averiguar las características de los distintos cortafuegos software descargables, así como sus respectivas licencias de uso: RouterOS: https://mikrotik.com/software pfSense: https://www.pfsense.org/ OPNsense: https://opnsense.org/ La inmensa mayoría de los cortafuegos hardware están basados en alguna distribución UNIX/Linux, pues su kernel está especialmente diseñado para el enrutamiento y filtrado de paquetes. Aquí trataremos la configuración de un cortafuegos Linux por motivos didácticos. Una vez seamos capaces de configurar un cortafuegos Linux, seremos capaces de configurar cualquier cortafuegos software o hardware. La única diferencia entre unos cortafuegos y otros está en la facilidad que ofrecen al usuario para definir reglas. Pero si entendemos el funcionamiento de un cortafuegos Linux, seremos capaces de comprender y aprender cualquier otro. Solo es necesario un PC (o máquina virtual) con dos o más interfaces de red y una distribución Linux básica (es decir, no es necesario entorno gráfico). Recursos web Algunas marcas de cortafuegos profesionales tienen una demostración online de su software cortafuegos, de modo que es posible probar el producto casi al 100% antes de adquirirlo. Puedes recurrir a estas demostraciones para comparar lo que aquí aprendas con la forma en que ha sido implementado en cada una de estas marcas. Mikrotik (sin password): http://demo.mt.lv SonicWall: http://livedemo.sonicwall.com/demo/demo.html WatchGuard: https://www.watchguard.com/wgrd-products/watchguard-dimension-demo Fortinet: https://www.fortinet.com/demo-center.html Un cortafuegos sirve para impedir conexiones de red no deseadas, pero solo para eso. No podemos caer en el error de pensar que disponer de un cortafuegos protege contra todas las amenazas descritas en este curso. Si una compañía dispone de un servidor web al que es necesario poder acceder desde el exterior, el cortafuegos debe permitir las conexiones entrantes al puerto 80 de dicho servidor, lo que se denomina abrir el puerto; pero, una vez abierto, es imposible evitar ataques al puerto 80 del servidor que aprovechen alguna brecha de seguridad del software del servidor web. Para ello es necesario recurrir a otras técnicas, como el hardening. Un cortafuegos es, pues, una medida de protección más. Decir que es una de las más importantes se debe a que un cortafuegos reduce la superficie de ataque. Si no vamos a ofrecer ningún servicio en el puerto 22, ¿para qué tenerlo abierto? Eso solo serviría para estar expuestos a ataques en busca de vulnerabilidades de nuestro sistema. 6.2. Conceptos previos Antes de profundizar en el estudio del cortafuegos de Linux, es necesario comprender varios conceptos fundamentales. 6.2.1. Paquetes La transmisión de datos por las redes TCP/IP se realiza en forma de pequeños paquetes IP (aproximadamente 1,5 KB de tamaño máximo). Un paquete siempre incluye una cabecera con la información necesaria para que los dispositivos de red (routers y switches) sean capaces de entregarlo a su destino. El resto del paquete, la carga o payload, está formado por los datos se están transmitiendo. Los datos que transportan los paquetes IP pueden ser de muchísimos tipos, pero todos se transmiten dentro de paquetes IP. A veces se transmiten datos HTTP, otras veces datos FTP, etc. Es decir, los paquetes IP contienen información codificada mediante otros protocolos que están por encima en la pila de protocolos TCP/IP. En la siguiente ilustración vemos como un paquete HTTP, que tiene su propia cabecera, es el payload de un paquete TCP; y este, a su vez, es el payload de un paquete IP. Es como si enviamos un papel dentro de una carta, y la carta dentro de una caja; el destinatario abrirá la caja, sacará el sobre, lo abrirá, y leerá el papel. Es lo que denominamos encapsulamiento. El emisor (un navegador web) genera el paquete HTTP, el sistema operativo lo encapsula en un paquete TCP con información importante en su cabecera (puertos origen y destino, entre otros), y este lo encapsula en un paquete IP con información igualmente importante (direcciones de origen y destino, por ejemplo). El paquete IP resultante es entregado a la tarjeta de red para que lo envíe. Al llegar al equipo de destino, este va “desempaquetando" en el sentido contrario, hasta encontrarse con el paquete HTTP original, que es entregado al proceso servidor web. Aquí pueden verse los campos que contiene la cabecera de cualquier paquete IP. No vamos a entrar aquí en el cometido de cada uno de ellos, pero sí queremos hacer mención de tres muy importantes de los que haremos uso en los cortafuegos: protocolo, dirección IP de origen y dirección IP de destino. El campo “protocolo” contiene un código que hace referencia al protocolo utilizado en el payload, que suele ser TCP, UDP o ICMP. Los campos "dirección IP de origen” y “dirección IP de destino” indican las direcciones IP de los equipos remitente y destinatario, respectivamente; dichos campos pueden ser alterados por los routers en determinadas ocasiones como, por ejemplo, cuando hacen uso del protocolo NAT, como vimos en el anterior capítulo. 6.2.2. Reglas y acciones La configuración de un cortafuegos se realiza estableciendo reglas. Una regla estipula, para cada paquete, qué acción u objetivo (target) debe tomarse en función de diversos factores. Aplicación de las reglas del cortafuegos a todos los paquetes. Las acciones posibles son: ACCEPT: aceptar el paquete. REJECT: rechazar el paquete. Haciendo uso del protocolo ICMP, se le envía un mensaje al emisor para advertirle de que el paquete ha sido rechazado. DROP: descartar el paquete. No se envía ningún tipo de aviso al emisor. En realidad hay más acciones posibles, pero de momento tenemos suficiente con estas tres. La única diferencia entre REJECT y DROP reside en el aviso al emisor. Si usamos REJECT, el emisor verá un mensaje de error; si usamos DROP, el emisor quedará esperando una respuesta que nunca llegará. En la mayoría de las ocasiones se utiliza DROP, pues se trata de evitar ataques, no de ser educado con los atacantes. REJECT se usa principalmente para rechazar conexiones HTTP/HTTPS, de modo que el usuario vea el mensaje de error en pantalla. Las condiciones sobre las cuales una regla toma su decisión consisten en comprobaciones sobre: - El contenido de uno o más campos de la cabecera del paquete, como dirección de origen o destino, puerto de origen o destino, protocolo utilizado (TCP, UDP, ICMP), campos específicos de las cabeceras de esos protocolos, etc. - La interfaz de red por la que entra o sale el paquete. - La dirección MAC de origen. - El estado de la conexión (tratamos este concepto más adelante). - Si la dirección de origen (o la de destino) pertenece a una determinada lista de direcciones (de este modo el administrador puede crear una lista negra o blacklist). Así, podríamos definir una regla como la siguiente: “Si el paquete entra en el router por eth0, la dirección de origen es 192.168.1.23, el protocolo es TCP y el puerto de destino es 80, entonces ACCEPT”. Se pueden crear reglas sin condiciones, solo con una acción. Dicha regla se aplicará a todos los paquetes (es decir, equivale en programación a una instrucción “if TRUE then”). Pero cuando una regla contiene condiciones, se deben cumplir todas las especificadas (el equivalente en este caso sería un "if cond1 AND cond2 AND then...”). Cuando se cumple la condición de una regla, se aplica su acción y no se continúa con la siguiente regla, se finaliza la cadena. 6.2.3. Cadenas y tablas Cadenas Las reglas de un cortafuegos se agrupan en cadenas (chains). Es un término que hace referencia a que las reglas están encadenadas una detrás de la otra, como los pasos sucesivos de un algoritmo. Todo cortafuegos dispone de tres cadenas base predefinidas: INPUT: estas reglas se aplican a los paquetes entrantes cuyo destino es el propio router. OUTPUT: estas reglas se aplican a los paquetes salientes (el origen es el router). FORWARD: estas reglas se aplican a los paquetes entrantes cuyo destino no es el router, es decir, son paquetes que deben ser enrutados y, por tanto, volver a salir. En realidad, existen dos más: PREROUTING: Reglas que se aplican a los paquetes que llegan a la máquina. Esta cadena se ejecuta antes de comprobar si el paquete es para la propia máquina o hay que reenviarlo. Se toman acciones antes de que ninguna decisión sobre el enrutamiento del paquete se haya tomado. POSTROUTING: Reglas que se aplican a los paquetes que salen de la máquina, tanto los creados por ella como los que se reenvían. Esta cadena se ejecuta después de consultar la tabla de encaminamiento y justo antes de que el paquete abandone la red.. Como se comentó antes, una cadena no es más que una lista ordenada de reglas. Permiten tomar acciones sobre los paquetes en un determinado punto de su enrutado. Para cada paquete se va comprobando si se le aplica cada regla de la cadena (es decir, si cumple la condición): - Si una regla NO se aplica a un paquete, se pasa a la siguiente regla de la cadena. - Si una regla SÍ se aplica a un paquete, se ejecuta la acción definida en dicha regla. Dependiendo del tipo de acción: - El paquete abandona la comprobación del resto de las reglas y pasa a la siguiente cadena (acciones ej: ACCEPT, DROP). - El paquete continúa con la siguiente regla de la cadena (acción ej: LOG) - Una cadena puede tener definida una política, llamada política de cadena, que es la acción por defecto para la cadena. La política predefinida para todas las cadenas predefinidas es ACCEPT (es decir, aceptar el paquete). - Cuando para un paquete NO se aplica NINGUNA de las reglas de la cadena, se ejecuta para él la política de la cadena (si dicha cadena la tiene). Todos los equipos Linux vienen con un cortafuegos cuyas cadenas INPUT, OUTPUT y FORWARD están vacías (no contienen reglas) y tienen como política la acción ACCEPT. Es decir, un equipo Linux recién instalado no descarta nunca ningún paquete, ¡es como si no tuviera cortafuegos!, todo lo contrario que un equipo Windows. Las reglas tienen una posición determinada (número de regla ) dentro de la cadena. A la hora de añadir una nueva regla en una cadena, hay tres posibilidades: - añadir la regla al final de la cadena, detrás de las ya existentes - reemplazar en una posición a otra regla ya existente - insertar la regla en una posición ya existente, desplazando un lugar a las reglas existentes desde esa posición en adelante. Retomando el ejemplo del apartado anterior ("Si el paquete entra en el router por eth0, la dirección de origen es 192.168.1.23, el protocolo es TCP y el puerto de destino es 80, entonces ACCEPT"), vemos que esta regla tendría sentido en las cadenas INPUT o FORWARD, no en OUTPUT. Tablas Las cadenas, a su vez, se agrupan en tablas. Es una forma de clasificar las cadenas según el uso que el kernel hace de ellas. Las tres cadenas antes mencionadas (INPUT, OUTPUT y FORWARD) forman parte de la tabla filter, pues el objetivo de estas cadenas es filtrar los paquetes (aceptar unos y rechazar otros). Las tablas existentes son las siguientes: filter: para filtrar paquetes. Las que deciden que un paquete continúe su camino o sea descartado. nat: las cadenas de esta tabla sirven para decidir a qué paquetes se les aplica el protocolo NAT de traducción de direcciones. Igual que las reglas de las cadenas en la tabla filter tienen como acciones ACCEPT, REJECT y DROP, las reglas de las cadenas en la tabla nat incluyen acciones propias como SNAT, MASQUERADE, DNAT y REDIRECT. Por citar ejemplos, podríamos tener reglas para realizar redirecciones dentro de nuestra LAN, o reglas para traducir las IP privadas a la IP pública del router. mangle: las cadenas de esta tabla permiten modificar las cabeceras de los paquetes, alterando algún campo o añadiendo alguna marca que sólo tendrá sentido en nuestra red. Realizan alteraciones muy específicas de los paquetes. Por ejemplo, cambiar el valor del TTL de un paquete (tiempo de vida en la red), o el ToS (tipo de servicio) para modificar su prioridad. Existen muchas acciones propias para las reglas de las cadenas de esta tabla, por ejemplo, CHANGE-TTL, MARK-PACKET,... raw: las cadenas de esta tabla se utilizan para el seguimiento de conexiones y se aplican antes que cualquier otra tabla, cuando los paquetes aún están sin alterar y sin clasificar según conexión (raw significa “crudo'). Ejemplos de uso de esta tabla son los de bloquear posibles ataques como SSDP (Protocolo simple de descubrimiento de servicios), o descartar paquetes de la lista negra. Entre las acciones propias de raw a realizar en las reglas, tenemos por ejemplo NOTRACK. La tabla filter incluye las cadenas: - FORWARD - INPUT - OUTPUT La tabla nat incluye las cadenas: - PREROUTING - OUTPUT - POSTROUTING La tabla mangle incluye las cadenas: - PREROUTING - FORWARD - INPUT - OUTPUT - POSTROUTING La tabla raw incluye las cadenas: - PREROUTING - OUTPUT Por lo tanto, cuando un paquete entra al kernel (desde la red u originado por un proceso local) comienza un itinerario por las diferentes tablas y cadenas, esperando a que en alguna de ellas haya una regla que decida qué hacer con él. Si la acción es ACCEPT, el paquete continúa su camino por el kernel, pasando a la siguiente cadena disponible; si la acción es DROP O REJECT, el paquete se elimina y no continúa su camino. El orden en el que se evalúan las reglas de las cadenas en las diferentes tablas es el que se muestra a continuación. Obsérvense los diferentes itinerarios para paquetes entrantes, salientes y en redirección: El paquete puede venir de la red u originarse en el router, y puede ir destinado al router o a otro equipo de la red. En la mayoría de las ocasiones, las cadenas no contendrán ninguna regla, por lo que se aplicará la política por defecto, que si no se ha alterado siempre es ACCEPT, de modo que el paquete continúa su camino. Dicho con otras palabras, la acción ACCEPT significa “el paquete es válido, que continúe su camino. 6.2.4. Seguimiento de conexiones El seguimiento de conexiones o Connection Tracking es la capacidad que tienen los cortafuegos de identificar conexiones entre dos equipos y memorizarlas en el kernel para clasificar los paquetes según aquella a la que pertenecen. Un cortafuegos capaz de identificar y memorizar conexiones abiertas se denomina stateful firewall. En caso contrario, recibe el nombre de stateless firewall. Una conexión queda definida por: - Protocolo utilizado. - IP: puerto origen IP: puerto destino. Es decir, todos los paquetes que tengan los mismos valores en estos cinco campos pertenecen o pueden pertenecer a la misma conexión. El cortafuegos debe memorizar estos valores de todos los paquetes entrantes para comprobar si cada uno de ellos pertenece a una conexión ya abierta o es el primero de una nueva. Para ello, el kernel asigna un estado (state) a todos los paquetes: NEW: el paquete está iniciando una nueva conexión. ESTABLISHED: el paquete pertenece a una conexión ya abierta. RELATED: se ha creado una nueva conexión (normalmente consistente en un único paquete ICMP) a partir de una conexión ya establecida. INVALID: el paquete no es considerado válido por algún motivo, pero aun así se le deja pasar. Lo normal es rechazar (DROP) siempre este tipo de paquetes: aparte de ser inservibles pueden tratarse de parte de un ataque de denegación de servicio. Estado de los paquetes de diferentes conexiones. Cuando un usuario se conecta a nuestro servidor web, el primer paquete que entra en el cortafuegos se etiqueta como NEW. La respuesta del servidor, así como posteriores peticiones y respuestas, se clasificarán como ESTABLISHED. Si el servidor web tuviera que devolver un paquete ICMP para notificar algún error, se trataría de un paquete con estado RELATED. En cambio, si nuestro servidor recibiera un paquete ICMP con algún mensaje "respuesta" y que no hiciera referencia a una conexión conocida, sería inmediatamente marcado como INVALID. Las cadenas INPUT y FORWARD siempre deberían tener DROP como política por defecto y empezar por las dos reglas siguientes: Si el estado del paquete es INVALID DROP. Si el estado del paquete es ESTABLISHED o RELATED → ACCEPT. A continuación, todas las reglas que necesitemos para permitir los accesos que deseemos: Si el paquete entra por eth0, la dirección de destino es la del servidor web, el protocolo es TCP y el puerto destino es 80 → ACCEPT. Si el paquete... etc... etc... + ACCEPT. En estas últimas reglas, el estado de los paquetes siempre será NEW y, por tanto, no hace falta comprobarlo explícitamente. Esto queda esquematizado en esta imagen: Reglas habituales en un cortafuegos con seguimiento de conexiones (cadenas INPUT/FORWARD). 6.3. iptables La parte del kernel de Linux encargada de la manipulación de los paquetes de red se llama netfilter. Para configurarlo, mediante la creación de reglas, se utiliza el comando iptables. Este comando necesita, lógicamente, permisos de root. No podemos continuar sin hacer mención a los sistemas operativos basados en UNIX-BSD, como Mac OS X, OpenBSD (openbsd.org) o FreeBSD (freebsd.org), pues en lugar del módulo netfilter tienen otros llamados PF, ipfirewall (ipfw) e ipfilter (ipf). Cada uno de ellos es una forma diferente de configurar el cortafuegos, y existen simultáneamente para que el administrador pueda elegir aquel con el que se encuentre más cómodo. Funcionalmente son muy similares a netfilter, pero el lenguaje empleado para definir las reglas es completamente distinto. Esto es importante tenerlo en cuenta pues algunos cortafuegos hardware profesionales están basados en alguno de estos módulos, no en netfilter. Por ejemplo, los cortafuegos pfSense están basados, como cabe imaginar, en PF. En cualquier caso, como ya se ha dicho, comprendiendo las nociones subyacentes a netfilter/iptables, podremos aprender a manejar otros cortafuegos, PF entre ellos al ser también de tipo stateful. Video práctico introductorio: https://www.youtube.com/watch?v=H1WPwAjMXRo 6.3.1. Visualizar y añadir reglas Para comenzar, vamos a ver el comando que nos permite visualizar las reglas existentes en nuestro sistema y las políticas por defecto: $ iptables -L Observa que las reglas aparecen agrupadas en cadenas, pero en el listado no hay rastro de las tablas y sabemos que algunas cadenas están presentes en diversas tablas. De hecho, si no especificamos un parámetro para seleccionar una tabla, las reglas que vemos (como en el comando anterior) son las que corresponden a la tabla filter. Si queremos ver las reglas y cadenas establecidas para una determinada tabla, usaremos: $ iptables -t -L (donde tabla puede ser: raw, nat, mangle o filter) La sintaxis de iptables para añadir una regla es la siguiente: $ iptables -t -A -j Si se omite -t, iptables actúa sobre la tabla filter (¡ojo con esto!). El parámetro -A significa añadir la regla al final de la cadena. Para ubicarla en una posición concreta es necesario utilizar -I (insertar) en lugar de -A. El resto de parámetros sirve para definir las condiciones que debe cumplir el paquete para que se le aplique la. Deberán cumplirse todas las condiciones para que se aplique la acción, la cual puede ser cualquiera de las predefinidas (ACCEPT, DROP, etc.) o el nombre de una cadena definida por el usuario para saltar a ella (-j viene, precisamente, de jump, 'saltar'). Veamos un ejemplo: cómo añadir una regla que sirva para detectar los paquetes entrantes (al router), de protocolo TCP, que se dirigen al puerto 80 y que provienen de la red 90.100.21.0/24, para descartarlos: $ iptables -A INPUT -p tcp --dport 80 -s 90.100.21.0/24 -j DROP Observa que hay un parámetro que comienza con doble guión. En el mundo Linux es muy habitual que los parámetros se puedan escribir de dos formas: la corta (un guión) y la larga (doble guión). Por ejemplo, el parámetro -j se podría escribir también como --jump. Ten presente también que ciertos parámetros están permitidos solo si vienen precedidos de otro concreto. En el ejemplo que nos ocupa, solo podemos incluir el parámetro que define el puerto de destino (--dport) si previamente hemos especificado que se trata del protocolo TCP (-p). Conforme escribimos comandos iptables -A o iptables -I, las reglas entran en funcionamiento al instante. Esto puede ser peligroso pues, si nos confundimos al escribir una regla podríamos, incluso, llegar a bloquearnos a nosotros mismos (esto le puede ocurrir a un administrador despistado si se conecta remotamente por SSH a un sistema para hacer cambios en el cortafuegos y, sin quererlo, añade una regla que le corta el acceso a sí mismo). Vamos a comprobarlo. Establecemos la política INPUT por defecto a DROP. Con ello vamos a perder la conectividad: $ iptables -P INPUT DROP Por si esto fuera poco, las reglas de iptables se pierden al apagar el sistema: en el siguiente inicio hay que volver a definirlas. Es decir, no son persistentes. 6.3.2. Persistencia de las reglas Para evitar los problemas descritos al final del apartado anterior existen dos comandos que nos permiten guardar las reglas de iptables en un fichero de texto para así poder leerlas de nuevo en el arranque, haciéndolas así persistentes. Se trata de iptables-save e iptables-restore. El primero de ellos vuelca en la salida la totalidad de las reglas de netfilter, en un formato que tanto iptables-restore como cualquier administrador es capaz de entender. Para guardar el contenido de nuestro cortafuegos escribiremos (el nombre del fichero es indiferente): $ iptables-save > /etc/firewall.rules A partir de ese momento, será posible añadir, borrar, cambiar o reordenar las reglas editando el fichero generado, y ello no tendrá ningún efecto en el sistema hasta que ejecutemos: $ iptables-restore < /etc/firewall.rules Existe una manera “segura” de aplicar nuevas reglas, mediante el comando iptables-apply: $ iptables-apply /etc/firewall.rules Tras realizar alguna modificación a las reglas en nuestro fichero, ejecutamos el comando anterior, el sistema aplicará los cambios y nos pedirá confirmación. Si a los 30 segundos (tiempo durante el cual podemos comprobar que todo va bien), no hemos confirmado la aplicación, las reglas aplicadas son revertidas, para que podamos editar de nuevo nuestro fichero de reglas y corregirlas. Pero solo con lo anterior no hemos conseguido que nuestras reglas sean persistentes, pues estaríamos obligados a ejecutar manualmente el comando iptables-restore tras cada reinicio del sistema. Veamos una forma de ejecutarlo de forma automática, es decir, de conseguir completamente la persistencia: 1. Creamos el fichero /etc/firewall.rules con las reglas actuales de nuestro sistema: iptables-save > /etc/firewall.rules 2. Creamos un script de inicio /etc/network/if-pre-up.d/firewall con este contenido: #!/bin/sh /sbin/iptables-restore < /etc/firewall.rules 3. Creamos el script de cierre /etc/network/if.down.d/firewall con el siguiente contenido: #!/bin/sh /sbin/iptables-save > /etc/firewall.rules 4. Ya sabemos que cada vez que queramos hacer un cambio en nuestro cortafuegos, podemos editar el fichero de reglas y aplicarlas a continuación con iptables-apply: $ nano /etc/firewall.rules $ iptables-apply /etc/firewall.rules 5. No olvidemos hacer ejecutables ambos scripts (chmod +x ). En realidad, los scripts que acabamos de crear no se ejecutan al inicio o cierre del sistema, sino al habilitar o deshabilitar el servicio de red del kernel, lo cual ocurre siempre en los reinicios del sistema, pero también puede ocurrir en más ocasiones. ¿Qué aspecto tiene un fichero de reglas generado por iptables-save? Si ejecutamos dicho comando en un cortafuegos en blanco, obtendremos el siguiente volcado: *filter :INPUT ACCEPT : FORWARD ACCEPT :OUTPUT ACCEPT COMMIT La primera línea indica que, a continuación, se describen las cadenas de la tabla filter. Las siguientes tres líneas indican las políticas por defecto de cada cadena. La última línea ordena (a iptables-restore) que se deben aplicar las nuevas reglas. Si hubiésemos ejecutado iptables-save tras haber añadido la regla del ejemplo del apartado 6.3.1, el resultado sería: *filter :INPUT ACCEPT -A INPUT -p tcp --dport 80 -s 90.100.21.0/24 -3 DROP : FORWARD ACCEPT :OUTPUT ACCEPT COMMIT Como se puede observar, la sintaxis de las reglas equivale a la del comando iptables, pero sin anteponer iptables, y obviando los parámetros -t (tabla) y -A (cadena), pues ya quedan explícitos en las líneas predecesoras. Por lo tanto, añadir, modificar, eliminar y reordenar reglas para el cortafuegos es mucho más cómodo si se hace en un fichero de texto con esta sintaxis, en vez de escribiendo directamente los comandos iptables en el terminal. Un listado con un formato similar de reglas se puede obtener con los parámetros -L (list) y -v (verbose): $ iptables -L -v La opción -v añade información muy interesante a las reglas, al ser un contador de paquetes a los cuales se ha aplicado cada regla. Otro parámetro útil que podemos añadir a los dos anteriores es --line-numbers, cuyo nombre es suficientemente explicativo. 6.3.3. Parámetros de iptables más utilizados El signo de admiración se puede anteponer a la mayoría de los parámetros para invertir la condición. Por ejemplo, para paquetes que no sean del protocolo UDP: iptables ! -p udp etc… [!] -p Protocolo (--protocol) de nivel de transporte del paquete. Puede ser TCP, UDP, UDPLITE, ICMP, ESP, AH O SCTP. [!] -s Dirección IP de origen (--source). Puede expresarse como una dirección de equipo o como dirección de red en formato CIDR. Ejemplo: paquetes que provienen de la red 192.168.1.x: iptables -s 192.168.1.0/24 etc... [!] -d Dirección IP de destino (--destination). Igual que la anterior. Ejemplo: paquetes que provienen de la red 192.168.1.0 y que no van dirigidos a la dirección 10.0.0.15: iptables -s 192.168.1.0/24 ! -d 10.0.0.15...etc... -j Especifica la acción de la regla (el target). Puede escribirse como --jump. Si se omite, la regla no efectúa ninguna acción, pero el contador interno se incrementa igualmente. Las acciones disponibles son bastantes, dependiendo de que otros parámetros se utilicen en la regla (es mejor consultar la documentación); además, algunas acciones solo están disponibles en unas tablas y en otras no. Las más utilizadas son ACCEPT, REJECT, DROP, RETURN, MASQUERADE, DNAT o el nombre de cualquier cadena definida por el usuario. [!] -i Interfaz de red de entrada (--in-interface). Solo se puede utilizar en las cadenas INPUT, FORWARD y PREROUTING. Ejemplo: los paquetes que entren por ETH0: iptables -i eth0...etc... [!] -o Interfaz de red de salida (--out-interface), es decir, por donde se supone que el paquete va a salir del router. Ejemplo: los paquetes que entren por ETH0 y salgan por cualquier otra interfaz: iptables -i eth0 ! -o eth0...etc... [!] --state Estado de la conexión a la que pertenece el paquete, pudiendo ser, como ya sabemos, NEW, ESTABLISHED, RELATED 0 INVALID. Ejemplo: los paquetes que entren por ETH0 y tengan el estado ESTABLISHED O RELATED: iptables -i eth0 --state ESTABLISHED, RELATED..etc... 6.3.4. Un cortafuegos mínimo PRÁCTICA GUIADA A continuación mostramos lo que debería ser el conjunto mínimo de reglas que siempre debemos considerar en todo equipo de escritorio Linux. No son exactamente las reglas que nos pueden servir en un cortafuegos empresarial (obsérvese la ausencia de reglas en la cadena FORWARD), pero nos valen desde un punto de vista didáctico. Por brevedad se omiten los comentarios (-m comment), a pesar de que es una práctica muy recomendable. Antes de comenzar, para evitar utilizar sudo y su autenticación a cada comando, nos logueamos con el usuario root. Paso 1. Verificación de reglas actuales. Es posible que si realizamos esta práctica en el equipo de clase, ya existiese alguna configuración activa del firewall. Para enumerar todas las reglas de iptables activas por especificaciones, ejecuta el comando iptables con la opción -S: $ iptables -S Paso 2. Eliminación de reglas (en el caso que existan) y rechazar todo. a) Eliminar reglas de una cadena Iptables ofrece una forma de eliminar todas las reglas en una cadena. Para eliminar una cadena específica, lo que borrará todas las reglas en dicha cadena, puede usar la opción -F -o su equivalente --flush- seguida por el nombre de la cadena a eliminar. Por ejemplo, para borrar todas las reglas en la cadena INPUT, ejecuta este comando: $ iptables -F INPUT b) Eliminar reglas de todas las cadenas Para eliminar todas las cadenas, lo que borrará todas las reglas de firewall, puedes utilizar la opción -F o su equivalente --flush sin incluir ningún otro parámetro: $ iptables -F Ahora, todas las reglas estarán eliminadas, por lo que el firewall aceptará todas las conexiones, si así están definidas las políticas por defecto. Nota: Ten en cuenta que ésto deshabilitará completamente el firewall. Solo deben seguirse los pasos de esta sección si deseamos volver a comenzar la configuración de nuestro firewall desde el inicio. Comprobemos las políticas por defecto para las cadenas INPUT, OUTPUT y FORWARD: $ iptables -S Debemos obtener un listado parecido a este: -P INPUT ACCEPT -P OUTPUT ACCEPT -P FORWARD ACCEPT Paso 3. Descartar todo por defecto En caso que el listado anterior no muestre nada, establezcamos las políticas por defecto para cada una de las cadenas integradas, en DROP $ iptables -P INPUT DROP $ iptables -P FORWARD DROP $ iptables -P OUTPUT DROP Ahora el firewall no permitirá tráfico en la red. Si comprobamos las reglas, veremos que no hay aún ninguna, pero veremos las tres cadenas por defecto (INPUT, FORWARD y OUTPUT) en estado DROP. Paso 4. Adición de reglas básicas El listado de las reglas que vamos a realizar es el siguiente # (1) A la interface lo (localhost) se le permite todo iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # (2) Se evitan paquetes tcp que llegan como conexiones nuevas iptables -A INPUT -p tcp -m state --state NEW -j DROP # (3) todo lo que sea icmp (ping) y que intente entrar, se descarta # con esto bloqueamos cualquier tipo de paquetes con protocolo icmp # evitando ataques como el del ping de la muerte. Permitimos las respuestas a # nuestros ping iptables -A INPUT -p icmp -m icmp --icmp-type echo-reply -j ACCEPT # (4) Por último las dos siguientes reglas permiten salir del equipo # (output) conexiones nuevas que nosotros solicitamos, conexiones establecidas # y conexiones relacionadas, y deja entrar (input) solo conexiones establecidas # y relacionadas. iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT # --------------------------------------------------------------------------------- Podemos comprobar que las reglas se han añadido satisfactoriamente con: $ iptables -S Si en algún momento queremos eliminar una regla, podemos hacerlo mediante su número y cadena. Para listar las reglas por cadena y número, lanzamos: $ iptables -L --line-numbers Usando el parámetro -D seguido de cadena y número de regla, eliminaríamos la regla correspondiente. Por ejemplo, la 1 de INPUT: $ iptables -D INPUT 1 Ten en cuenta que al introducir estas reglas mediante comandos iptables, las reglas pasan a evaluarse inmediatamente. Ahora vamos a guardar todas estas reglas, que se hallan en memoria, a un archivo: $ iptables-save > firewall.rules Comprueba su contenido: $ cat firewall.rules Verás que todas las reglas añadidas aparecen bajo la tabla *filter, puesto que en los comandos no hemos especificado otra tabla, pero ya sabes que el firewall considera varias tablas, cada una de ellas con sus cadenas. Podemos, si lo deseamos, editar, añadir o modificar las reglas sobre el propio archivo, y luego, aplicarlas. Prueba a hacer un cambio en alguna de las reglas, utilizando por ejemplo el editor nano: $ nano firewall.rules Cuando guardes los cambios, lanza este comando para aplicarlos: $ iptables-apply firewall.rules Verás que el sistema te pide confirmación de que no has perdido ninguna conexión (es el momento de hacer alguna prueba). Si no pulsas ‘Y’ o no pulsas nada en 30 segundos, los cambios se revertirán. Es un modo de añadir aquellas reglas cuyos efectos no estamos seguros si serán los correctos. PARA SABER MÁS: Estupendo resumen, tanto de todo lo relativo a la tabla filter como a la tabla nat: https://sites.google.com/educarex.es/smrseguridadinformatica/u-d-7-seguridad-per imetral/iptables RESUMEN DE ACCIONES La acción es la operación que se lleva a cabo sobre el paquete en caso de que le sea aplicable la regla. Tabla Acción Descripción Se acepta el paquete y no se analizan más reglas de las cadenas de la tabla. ACCEPT iptables -A INPUT -p icmp -j ACCEPT Desecha el paquete sin informar al emisor. Por ello, sólo considerará fallida la conexión tras un tiempo DROP de espera. Obviamente, no es revisada ninguna regla posterior. iptables -A INPUT -p icmp -j DROP Rechaza un paquete enviando al emisor el aviso del rechazo mediante un paquete ICMP. Se puede especificar el tipo de ICMP mediante --reject-with y, en el caso, de conexiones TCP se puedfe usar filter tcp-reset para enviar un paquete RST que cierre elegantemente la conexión. Si no se incluye la opción REJECT se envía port-unreachable. iptables -A FORWARD -p tcp –dport 25 -j REJECT –reject-with tcp-reset Registra en un archivo el paquete que cumple las condiciones de la regla. De las opciones posibles la más útil es --log-prefix que permite añadir un prefijo a las anotaciones, lo cual puede ser útil para filtrar esas anotaciones. Vea más adelante como realizar anotaciones en el registro. El objetivo no altera la LOG comprobación de las reglas posteriores. iptables -A FORWARD -p tcp –dport 25 -j LOG –log-prefix=»[netfilter] iptables -A FORWARD -p tcp –dport 25 -j REJECT –reject-with tcp-reset Cambia la IP de origen del paquete. Sólo está disponible en las cadenas POSTROUTING e INPUT de la tabla nat. Necesita la opción --to-source para indicar cuál es la IP sustituta. SNAT iptables -t nat -A POSTROUTING -o eth0 -j SNAT –to-source 172.22.0.2 nat Cambia la IP de origen del paquete por la IP de salida del cortafuegos. Útil cuando la IP es dinámica. MASQUERADE iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE Cambia la IP de destino del paquete. Debe hacerse en la cadena PREROUTING o en OUTPUT de la tabla nat. Necesita la opción --to-destination para indicar la IP sustituta. Puede además modificarse el DNAT puerto de destino separándolo con dos puntos (»:»). iptables -t nat -A PREROUTING -p udp –dport 53 -j DNAT –to-destination 172.22.0.1 Cambia la IP de destino a 127.0.0.1. Puede añadirse la opción --to-port para modificar el puerto de destino. Puede usarse en PREROUTING o en OUTPUT. REDIRECT iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 3128 Sirve para marcar la representanción del paquete en el núcleo de Linux, con el fin de que más adelante el propio iptables u otro proceso reconozca la marca. Debe usarse con la opción --set-mark para fijar MARK la marca (un byte). iptables -t nat -A PREROUTING -p tcp –dport 22 -j MARK –set-mark 0x2 mangle Cambia el TOS del paquete. TOS iptables -t nat -A PREROUTING -p tcp –dport 22 -j TOS –set-tos 0x10 Cambia el TTL del paquete. TTL iptables -t nat -A PREROUTING -p tcp –dport 22 -j TTL –set-ttl 64 Evitar hacer el seguimiento de la conexión. Puede usarse en las cadenas PREROUTING y OUTPUT. NOTRACK iptables -t raw -A PREROUTING -p udp –dport 53 -j NOTRACK Como lo anterior, pero descarta el paquete en vez de dejarlo pasar y no hacerle seguimiento. Si raw nuestra intención es filtrar un tráfico vaya a la máquina o pretenda atravesarlo, este el mejor momento, ya que sólo requiere una regla en vez de dos, una para cada tabla y, además, se realiza antes de DROP tomar ninguna decisión con lo que es más eficiente. iptables -t raw -A PREROUTING -p udp –dport 53 -j DROP