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:
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.
- ############SCRIPT DE CREACIÓN UN FIREWALL BÁSICO#############
- #!/bin/bash
- ### BEGIN INIT INFO
- # Provides: Nombre del script
- # Required-Start: $remote_fs
- # Required-Stop: $remote_fs
- # Default-Start: 2 3 4 5
- #!/bin/bash
- #inicio indispensable en todo script
- #No es indispensable, pero si recomendable escribir
- ### BEGIN INIT INFO
- # Provides: iptables.sh
- # Required-Start: $syslog
- # Required-Stop: $syslog
- # Default-Start: 2 3 4 5
- # Default-Stop: 0 1 6
- # Short-Description: blabla
- # Description:
- #
- ### END INIT INFO
- #Primero hacemos que no nos puedan hacer ping.
- #Esto no es parte de iptables pero es recomendable hacerlo
- echo '1' > /proc/sys/net/ipv4/icmp_echo_ignore_all
- echo '1' >/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
- #Partiendo de la base de que estamos en un entorno domestico
- #pensamos en que nos interesa salir al exterior sin restricciones,
- #pero que solo queremos que entre el trafico justo a nuestro ordenador
- #es decir Internet, ssh y el DNS
- #Las politicas por defectos son ACCEPT pero me gusta escribirlas
- #Por si en un futuro quisiese editarlo
- #Cómo queremos tener por defecto todo bloqueado,
- #hacemos que la politica INPUT bloquee todo el acceso abriendo solo lo que nos interesa
- iptables -P INPUT DROP
- iptables -P FORWARD ACCEPT
- iptables -P OUTPUT ACCEPT
- #Permitimos el acceso del propio equipo al localhost
- iptables -A INPUT -i lo -j ACCEPT
- #Dejamos abierto el puerto 80 para permitir el acceso a Internet.
- #si no abrimos este puerto no podremos tener contacto con el exterior.
- iptables -A INPUT -p tcp --dport 80 -j ACCEPT
- iptables -A INPUT -p udp --dport 80 -j ACCEPT
- #Dejamos abierto el puerto por ssh.
- iptables -A INPUT -p tcp --dport 22 -j ACCEPT
- #DNS
- iptables -A INPUT -p tcp --dport 53 -j ACCEPT
- iptables -A INPUT -p udp --dport 53 -j ACCEPT
- #Opcional Esto es por si quisiesemos acceder por ftp
- iptables -A INPUT -p tcp --dport 21 -j ACCEPT
- iptables -A INPUT -p udp --dport 21 -j ACCEPT
- #Por otro lado está el olvidado, pero importante ipv6,
- #el cual también necesita un trato a menos que queramos que aprovechen esa entrada.
- #Si tenemos ipv6 deshabilitado no tenemos que preocuparnos de nada, de esto.
- #En caso contrario habría que escribir las mismas reglas que arriba pero orientadas a ipv6.
- ip6tables -P INPUT DROP
- ip6tables -P FORWARD ACCEPT
- ip6tables -P OUTPUT ACCEPT
- ip6tables -A INPUT -i lo -j ACCEPT
- ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT
- ip6tables -A INPUT -p udp --dport 80 -j ACCEPT
- ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT
- ip6tables -A INPUT -p tcp --dport 53 -j ACCEPT
- ip6tables -A INPUT -p udp --dport 53 -j ACCEPT
- ip6tables -A INPUT -p tcp --dport 21 -j ACCEPT
- 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.
No hay comentarios :
Publicar un comentario