Vamos a ver un ejemplo de definición de una política de seguridad
básica utilizando tanto iptables como ipchains; por cuestiones
de simplicidad nos centraremos exclusivamente en el filtrado de paquetes, no en
otros aspectos como la redirección de puertos o el NAT.
Lo primero que posiblemente nos interese antes de comenzar a definir reglas
de filtrado sea `vaciar' las chains, es decir, eliminar todas las reglas
asociadas a cada lista, de forma que no interfieran con las que vamos a
comenzar a definir; para ello podemos utilizar la opción `-F' tanto
de iptables como de ipchains (recordemos que en el primer caso, los
nombres de las chains son los mismos, pero en mayúsculas). Además,
podemos definir una política por defecto mediante la opción `-P' de
ambas herramientas; esta política será la que se aplicará cuando un
paquete no sea contemplado por ninguna de las reglas de una determinada chain:
luisa:~# /sbin/ipchains -P input DENY
luisa:~# /sbin/ipchains -F input
luisa:~# /sbin/ipchains -P output ACCEPT
luisa:~# /sbin/ipchains -F output
luisa:~# /sbin/ipchains -P forward DENY
luisa:~# /sbin/ipchains -F forward
luisa:~#
Como vemos, lo que vamos a hacer por defecto es denegar todo el tráfico que
se dirija al cortafuegos, tanto si va dirigido a él como si se ha de reenviar
a otro sistema, y permitir todo el tráfico de salida. Como vemos, estas
políticas por defecto se pueden definir antes de `limpiar' cada chain, ya que la limpieza sólo afecta a las reglas en sí (y esta
acción por defecto no se considera una regla).
Una vez aplicadas las primeras acciones, nos interesará sobre todo, ya que
la salida la permitimos por completo (y de las redirecciones de tráfico ya
hemos dicho que no vamos a entrar en detalle), definir accesos permitidos a
nuestro sistema; por ejemplo, es posible que necesitemos un acceso total al
puerto 80 para que todo el mundo pueda maravillarse de esas páginas web
que hemos hecho con vi. Si es ese el caso, podemos permitir dicho acceso
mediante una regla similar a la siguiente:
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -d 158.42.22.41 80
luisa:~#
Estamos indicando que se añada (`-A') en la chain `input'
(tramas de entrada)
una regla que permita (`ACCEPT') el tráfico TCP (`-p') cuyo
destino (`-d') sea el puerto 80 de la dirección 158.42.22.41 - en
principio, la IP de nuestro servidor web -. Con iptables, la
sintaxis cambia ligeramente:
luisa:~# /sbin/iptables -A INPUT -p TCP -j ACCEPT -d 158.42.22.41 --dport 80
luisa:~#
Una vez definidas estas reglas, mediante la opción `-L' de ipchains e iptables podemos comprobar que efectivamente se están
aplicando (utilizamos también `-n' para que no se haga resolución
DNS):
luisa:~# /sbin/ipchains -L -n
Chain input (policy DENY):
target prot opt source destination ports
ACCEPT tcp ------ 0.0.0.0/0 158.42.22.41 * -> 80
Chain forward (policy DENY):
Chain output (policy ACCEPT):
luisa:~#
Ahora pensemos que quizás también queremos acceder a nuestro servidor de
forma remota, utilizando SSH, pero en este caso no desde cualquier lugar
de Internet sino desde una dirección concreta; la regla a añadir a la chain `input' en este caso sería la siguiente:
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -s 158.42.2.1 -d \
> 158.42.22.41 22
luisa:~#
Podemos ver que ahora especificamos la dirección origen (`-s') desde
la que vamos a permitir el tráfico (en este ejemplo, 158.42.2.1). Si
utilizáramos iptables la sintaxis sería la siguiente:
luisa:~# /sbin/iptables -A INPUT -p TCP -j ACCEPT -s 158.42.2.1 -d \
> 158.42.22.41 --dport 22
luisa:~#
Tal y como hemos definido hasta ahora nuestra política de seguridad, sólo
estamos permitiendo conexiones al puerto 80 desde cualquier máquina y al
puerto 22 desde la especificada; el resto del tráfico de entrada está siendo
denegado gracias a la política por defecto que hemos establecido para la
chain input (DENY). Así, tráfico como los mensajes ICMP de vuelta, o las llamadas al servicio ident que realizan ciertos
servidores cuando se les solicita una conexión no alcanzarán su destino, lo
cual puede repercutir en la funcionalidad de nuestro entorno: simplemente hemos
de pensar en una comprobación rutinaria de conectividad vía ping o
en el acceso a un servidor FTP externo que sea denegado si no se consigue
la identidad del usuario remoto. Para evitar estos problemas, podemos permitir
el tráfico de ciertos paquetes ICMP y el acceso al servicio auth (puerto 113):
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type \
> destination-unreachable -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type source-quench -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type time-exceeded -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type parameter-problem \
> -j ACCEPT
luisa:~# /sbin/ipchains -A input -p icmp --icmp-type echo-reply -j ACCEPT
luisa:~# /sbin/ipchains -A input -p tcp -j ACCEPT -d 158.42.22.41 113
luisa:~#
Como vemos, hemos ido definiendo las reglas que conforman nuestra política
desde línea de comando; ya hemos comentado que toda esta configuración
se pierde al detener el sistema, por lo que es necesario crear un script
que las vuelva a generar y planificarlo para que se ejecute en el arranque de
la máquina. Para ello no tenemos que escribir línea a línea la
configuración vista en este punto (mejor, la configuración adecuada a
nuestro entorno), o utilizar ipchains-restore o iptables-restore
para leer esa configuración de un fichero; si elegimos esta opción, antes
de detener al sistema hemos de ejecutar ipchains-save o iptables-save para guardar dicha política en el fichero que posteriormente
leeremos. De esta forma, en la parada de la máquina hemos de ejecutar una
orden similar a:
luisa:~# /sbin/ipchains-save >/etc/rc.d/policy
Saving `input'.
luisa:~#
Mientras que en el arranque, en nuestro script cargaremos la política
guardada al detener la máquina con una orden como:
luisa:~# /sbin/ipchains-restore </etc/rc.d/policy
luisa:~#
© 2002 Antonio Villalón Huerta