Configuración de un Cortafuegos en Linux (ejemplo)

Santiago González Herrero, sgonzale@bigfoot.com
Agosto 1999


Este documento tan sólo pretende el equivalente a unos apuntes de la información mínima necesaria para configurar las reglas de un cortafuegos para una conexión PPP con Linux a Internet. Caso de necesitar una información más exhaustiva, por favor visita [PPP-HOWTO, IP_Masquerade-mini-HOWTO, IPCHAINS-HOWTO] Este documento no es más que el ejemplo de una realización de un cortafuegos adaptado a una conexión PPP a internet de una red privada mediante Linux. Una fuente importante de información es la página "Linux LAN & Internet Firewall FAQ" en la que me basé para la realización de este script.

En el IES Valliniello - Avilés  tenemos la necesidad de conectar nuestra intranet a Internet de una forma transparente, de manera que cada puesto de cualquier aula pueda acceder a cualquier servicio de internet. Para ello disponemos de una Intranet que conecta 5 segmentos de red (aulas de Informática) y un segmento especial en el que residen los servidores. Mediante una línea RDSI y un ordenador ejecutando Red Hat Linux 6.0 que, entre otros servicios, hace de router hacia internet mediante IP_Masquerade nos es posible realizar una conexión eficiente a Internet a un coste ridículo. Esta conexión supone un riesgo de accesos externos y posibles problemas de seguridad que mediante un filtrado de paquetes IP pretendemos reducir. Este documento te muestra cómo es el script que utilizamos para filtrar paquetes de Internet. En base a él podrás adaptar uno parecido a tus necesidades.

Nota Importante: Este documento es una chuleta para un administrador de redes habituado a trabajar con Linux. En ningún caso pretende ser un tutorial. Como se puede comprobar hay muchos aspectos que no se tocan (nociones TCP/IP, ppp, compilación del kernel, etc). Para un manual más exhaustivo, te remito a los documentos NET-3-HOWTO, IP-Masquerade-HOWTO, IPCHAINS-HOWTO, y Guía del administrador de redes. Muchos de estos documentos están traducidos ya sea por INSFLUG o por LuCAS. Este script ha sido creado y adaptado a mis necesidades basándome en el documento "Linux LAN & Internet Firewall FAQ" de obligada visita..


Introducción

Cuando utilizas un sistema Linux apra conectar tu red local a Internet, tienes la posibilidad de permitir o no cierto tipo de tráfico. Las cabeceras de los paquetes IP contienen información sobre el destino (de forma que se puede prevenir el acceso a ciertos sitios de internet), el origen (se pueden evitar conexiones desde sitios concretos de Internet). Otra información que se obtiene de las cabeceras es el protocolo utilizado (ICMP, UDP, TCP) y el puerto. Normalmente los protocolos de alto nivel utilizan para sus conexiones puertos determinados (también llamados well known sockets). De esa forma, la mayor parte de las peticiones de documentos html se harán a destinos de Internet por el puerto 80, el envío de correo se hará por el puerto 25, o las conexiones vía telnet se harán usando el puerto 23. Para más información echa un vistazo en /etc/services.

Mediante el programa ipchains, se puede filtrar el tráfico por una gran variedad de criterios, mediante reglas (algo así como sentencias si condición entonces acción). Las reglas se integran en tres grupos diferenciados, reglas de entrada (para paquetes que llegan al router), reglas de encaminamiento (decisión sobre encaminar paquetes o no), y reglas de salida (paquetes que salen del router por algún interfaz). Este programa es tan versátil que nos permite indicar en cada regla, la cadena (entrada, encaminamiento, salida) el protocolo, interfaz, direcciónes de origen y destino, y el puerto utilizado en la conexión, así como la acción a tomar (denegar, rechazar, aceptar o aceptar y enmascarar) caso que determinado paquete cumpla la regla.

Para una completa explicación de las capacidades de ipchains ver el IPCHAINS-HOWTO que viene incluido en la documentación del paquete.

Nota: En versiones de kernel 2.0.x, en vez de ipchains se usa ipfwadm (versión anterior de programa de filtrado de paquetes IP). Si bien el enfoque es ligeramente diferente, la sintaxis es muy parecida y los fundamentos son los mismos.
 

Nuestro caso

En mi caso, se trata de un Pentium a 90Mhz con 64Mb de RAM y 6,4Gb de disco, ejecutando Linux Red Hat 6.0 que es servidor local Web, de correo, noticias, IRC, FTP, servidor de ficheros mediante SAMBA, ofrece su CD mediante NFS para otras instalaciones Linux en equipos sin CD, sirve de Sistema para prácticas Unix, hace de router hacia Internet mediante IP-Masquerade a través de RDSI, y actúa de Proxy-Caché para el acceso a la WWW.

Obviamente, al ofrecer todos estos servicios, y a la vez hacer de router a Internet, es  muy necesario denegar el acceso desde el exterior a todos esos servicios. El siguiente script se encarga de "cerrar" el acceso exterior a todos estos servicios, manteniendo abierto el acceso desde la red local y realizando el trabajo de encaminador hacia Internet.

Nota importante: Este script no es en absoluto una barrera infranqueable para los hackers, pero es un primer paso importante, les pone las cosas más difíciles y la mayor parte desistirán.. No debes nunca de dejar de examinar los archivos de log. Por supuesto, la estabilidad de Linux es otra ayuda importante.
 

Configuración

Para ejecutar las reglas del script correctamente se deben tener dos datos: la dirección IP del interfaz por el que nos conectamos a Internet y el nombre de ese interfaz.

En este caso, la conexión es mediante PPP con asignación dinámica de IP (nos conectamos mediante Infovía Plus) por lo que recibimos la IP y el nombre del interfaz del programa PPP que al establecer la conexión nos pasa esa información en dos variables de entorno que son $IFNAME e $IPLOCAL (man pppd).

La ejecución del script es invocada en /etc/ppp/ip-up.local
Nota: Caso de tener conexión directa o IP fija, la llamada a rc.firewall debe realizarse en otro sitio (por ejemplo /etc/rc.d/rc.local) y estos datos, asignarse a mano. También habría que modificar esto en el caso de conexión mediante DHCP (ej. acceso a Internet por cable).

/etc/ppp/ip-up.local

Este fichero se encarga de realizar las acciones que podamos necesitar una vez que se establezca la conexión PPP. Por ejemplo, registrar conexiones, o en nuestro caso, establecer las reglas del cortafuegos. En nuestro caso invocaremos en él la llamada a un script /etc/rc.d/rc.firewall en el que incluiremos las reglas de filtrado de paquetes.

    #!/bin/sh
    /etc/rc.d/rc.firewall
 

#!/bin/sh
#------------------------------------------------------------------------
#                      CONFIGURACIÓN DEL CORTAFUEGOS
#------------------------------------------------------------------------
# Incluir la llamada a este script en /etc/ppp/ip-up.local
#------------------------------------------------------------------------
# Variables de entorno activadas por pppd al establecera la comunicación
#------------------------------------------------------------------------
# IPLOCAL <- dirección IP del interface ppp
# IFNAME  <- nombre del interface local
 

# Asignaciones locales

LOCALNET="192.168.0.0/24"
IPADDR=$IPLOCAL
TODAS="0.0.0.0/0"

# Nombres de Interfaz

PPP=$IFNAME
ETH="eth0"
LO="lo"

# Direcciones

LOOPBACK="127.0.0.1/32"
CLASE_A="10.0.0.0/8"
CLASE_B="172.16.0.0/16"
CLASE_C="192.168.0.0/16"
MULTICAST="240.0.0.0/3"
BROADCAST_0="0.0.0.0"
BROADCAST_1="255.255.255.255"

# Puertos conocidos

ROOT="0:1023"           # Puertos reservados a root
NO_ROOT="1024:65535"    # puertos no root
NFS="2049"              # (TCP/UDP) NFS
OPENWINDOWS="2000"      # (TCP) OpenWindows
XWINDOWS="6000:6001"    # (TCP) X Window
PORTS="1020:1023"       # Rango de puertos de SSH
PORTS="6667"            # Puertos del servidor IRC

#--------------------------------
# Limpiamos las reglas anteriores
#--------------------------------
/sbin/ipchains -F

#---------------------------------------------
# Establecer la política por defecto
#      Permitir entrada
#      Permitir salida
#      Denegar IP Forward
#---------------------------------------------
/sbin/ipchains -P input   ACCEPT
/sbin/ipchains -P forward DENY
/sbin/ipchains -P output  ACCEPT

#--------------------------------------------------------------------------
#                Spoofing y direcciones ilegales
#--------------------------------------------------------------------------
# Evitar que entren paquetes de fuera indicando como dirección de origen
# nuestra IP

/sbin/ipchains -A input -i $PPP -s $IPADDR -j DENY

# Evitar que lleguen de fuera paquetes con origen o destino 127.0.0.1

/sbin/ipchains -A input -i $PPP -s $LOOPBACK -j DENY
/sbin/ipchains -A input -i $PPP -d $LOOPBACK -j DENY

# Evitar que lleguen de fuera paquetes con origen o destino de direcciones
# reservadas para redes privadas

/sbin/ipchains -A input -i $PPP -s $CLASE_A -j DENY
/sbin/ipchains -A input -i $PPP -d $CLASE_A -j DENY
/sbin/ipchains -A input -i $PPP -s $CLASE_B -j DENY
/sbin/ipchains -A input -i $PPP -d $CLASE_B -j DENY
/sbin/ipchains -A input -i $PPP -s $CLASE_C -j DENY
/sbin/ipchains -A input -i $PPP -d $CLASE_C -j DENY

# Evitar que salgan hacia el exterior paquetes cuyo destino sea nuestra
# propia IP

/sbin/ipchains -A output -i $PPP -d $IPADDR -j REJECT

# Evitar que salgan paquetes con origen o destino 127.0.0.1

/sbin/ipchains -A output -i $PPP -s $LOOPBACK -j REJECT
/sbin/ipchains -A output -i $PPP -d $LOOPBACK -j REJECT

# Evitar que salgan paquetes con origen o destino a direcciones reservadas
# para redes privadas

/sbin/ipchains -A output -i $PPP -s $CLASE_A -j REJECT
/sbin/ipchains -A output -i $PPP -d $CLASE_A -j REJECT
/sbin/ipchains -A output -i $PPP -s $CLASE_B -j REJECT
/sbin/ipchains -A output -i $PPP -d $CLASE_B -j REJECT
/sbin/ipchains -A output -i $PPP -s $CLASE_C -j REJECT
/sbin/ipchains -A output -i $PPP -d $CLASE_C -j REJECT

# Denegar paquetes de broadcast de fuera

/sbin/ipchains -A input -i $PPP -s $BROADCAST_1 -j DENY
/sbin/ipchains -A input -i $PPP -d $BROADCAST_0 -j DENY

#----------------------------------------------------------------------------
# Poner aquí los servicios explícitamente permitidos
# auth (identd) 113, ctcp (irc) (59)
#----------------------------------------------------------------------------
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR  59 -j ACCEPT
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 113 -j ACCEPT

#-----------------------------------------------------------------------------
# Rechazar acceso del exterior a servicios de nuestra máquina
# Echa un vistazo con "netstat -a" para ver qué puertos tienes abiertos por encima
# del 1023 y por tanto deberíass cerrar
#-----------------------------------------------------------------------------
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $ROOT -l -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $ROOT -l -j DENY

/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $NFS -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $NFS -j DENY

/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $OPENWINDOWS -j DENY
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $XWINDOWS -j DENY
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $SSH -j DENY
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR $IRCD -j DENY

/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 3128 -j DENY
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 3130 -j DENY
/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 8080 -j DENY

/sbin/ipchains -A input -p tcp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 1024 -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 1024 -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 1026 -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 1119 -j DENY
/sbin/ipchains -A input -p udp -i $PPP -s $TODAS $NO_ROOT -d $IPADDR 3401 -j DENY

#-----------------------------------------------
# Forward con enmascaramiento para la red local
#-----------------------------------------------
/sbin/ipchains -A forward -s $LOCALNET  -j MASQ


Santiago González Herrero, sgonzale@bigfoot.com
Agosto 1999