Para un proyecto en el exterior escribí InstallingShorelineFirewall4Through42 para instalar la versión 4.2 en inglés.
Aprovechando que la instalación ahora es distinta, voy a hacerlo en castellano (e incluyendo soporte para IPv6 que está tan de moda ahora que se acabaron las direcciones IPv4).
Tabla de Contenidos
Es recomendable tener un firewall en cualquier servidor (en realidad, en cualquier computadora) aun cuando esté en una red "protegida" por algún tipo de firewall.
El que yo prefiero usar en GNU/Linux es el Shoreline Firewall (Shorewall) ya que es suficientemente poderoso como para hacer cualquier cosa que se pueda hacer con netfilter/iptables (el esquema de packet filtering nativo del kernel linux) y es mucho más fácil de configurar que la utilización de comandos iptables en un script. Shorewall sólo utiliza archivos de texto para su configuración (ninguna GUI vistosa, gracias).
Como los paquetes de debian y ubuntu en general están bastante retrasados respecto de la versión estable actual, conviene usar los paquetes fuentes directamente que son fáciles de instalar y actualizar.
En general, cualquier distribución más o menos nueva de GNU/Linux tiene todos los pre-requisitos de Shorewall en su instalación básica.
Bajar e instalar
# La versión actual (2011-08) de shorewall es 4.4.22.3
# Fijarse en http://www.shorewall.net/pub/shorewall/ para ver cuál es la versión actual
MAJOR="4.4"
MINOR="22"
PATCH=".3"
# El ID de la clave GPG de Shorewall (lo vamos a usar para verificar el paquete)
GPGKEY="6C562AC4"
# bajar el software
mkdir -pv ~/soft/shorewall
cd ~/soft/shorewall
# Bajarse la clave de firmas gpg de shorewall (ID 6C562AC4)
# Lamentablemente, no tienen la clave en un servidor público
# de claves y el server https donde la tienen tiene un
# certificado autofirmado, con lo cual nunca podemos estar
# completamente seguros de esta clave gpg.
# De todos modos, bajémosla...
wget --no-check-certificate https://lists.shorewall.net/shorewall.gpg.key
# y agreguémosla a nuestro "llavero"
gpg --import shorewall.gpg.key
# Ahora, bajamos y verificamos los paquetes
wget http://www.shorewall.net/pub/shorewall/${MAJOR}/shorewall-${MAJOR}.${MINOR}/shorewall-${MAJOR}.${MINOR}${PATCH}.tar.bz2
wget http://www.shorewall.net/pub/shorewall/${MAJOR}/shorewall-${MAJOR}.${MINOR}/shorewall-${MAJOR}.${MINOR}${PATCH}.tar.bz2.asc
fi
wget http://www.shorewall.net/pub/shorewall/${MAJOR}/shorewall-${MAJOR}.${MINOR}/shorewall6-${MAJOR}.${MINOR}${PATCH}.tar.bz2
wget http://www.shorewall.net/pub/shorewall/${MAJOR}/shorewall-${MAJOR}.${MINOR}/shorewall6-${MAJOR}.${MINOR}${PATCH}.tar.bz2.asc
# Verificar los paquetes (ignorar los WARNINGs acerca de "trusted signatures")
for PACKAGE in "" 6; do
FILE=shorewall${PACKAGE}-${MAJOR}.${MINOR}${PATCH}.tar.bz2
if [ ! -f ${FILE} ] ; then
FILE=shorewall-${PACKAGE}-${MAJOR}.${MINOR}.tar.bz2
fi
gpg --verify ${FILE}.asc ||
(echo '';echo '';echo '¡¡¡¡STOP!!!!';echo ${FILE} ' PARECE FALSO';echo '')
done
# Si no apareció ningún ¡¡¡STOP!!!! entonces sigamos adelante
# Abrimos los paquetes...
for PACKAGE in "" 6 ; do
FILE=shorewall${PACKAGE}-${MAJOR}.${MINOR}${PATCH}.tar.bz2
tar xjvf ${FILE}
done
# ...y los instalmos.
# Primero el paquete shorewall
cd shorewall-${MAJOR}.${MINOR}${PATCH}
sudo ./install.sh -s
cd ~/soft/shorewall
# Después el paquete shorewall6
cd shorewall6-${MAJOR}.${MINOR}${PATCH}
sudo ./install.sh -s
cd ~/soft/shorewall
ulogd
Para mantener separados los logs de netfilter (si no, se mezclan con todo lo que se loguee en el kernel facility del syslog), instalamos ulogd:
sudo apt-get install ulogd
Configuración
Ahora hay que configurar el firewall.
La opción -s que le pasamos a cada ./install.sh deja limpio el directorio de configuración (/etc/shorewall para shorewall y /etc/shorewall6 para shorewall6). Esto es, sólo deja el archivo de configuración principal (shorewall.conf o shorewall6.conf) y un archivo de parámetros (param) vacío.
Los archivos de configuración "limpios" que normalmente se instalan en /etc/shorewall se pueden copiar de /usr/share/shorewall/configfiles y los que se instalan en /etc/shorewall6 se pueden copiar de /usr/share/shorewall6/configfiles.
Con lo cual ahora tenemos los siguientes archivos:
/etc/shorewall/params: archivo con parámetros (variables) para shorewall IPv4
/etc/shorewall/shorewall.conf: archivo de configuración global de shorewall IPv4
/etc/shorewall6/params: archivo con parámetros (variables) para shorewall IPv6
/etc/shorewall6/shorewall6.conf: archivo de configuración global de shorewall IPv6
shorewall.conf / shorewall6.conf
Vamos a hacer algunos cambios pequeños en la configuración por defecto.
Logging
Cambiamos todos los XXXXXXX_LOG_LEVEL para que en lugar de info (el default) tengan ULOG (siempre todo en mayúsculas).
También cambiamos LOGFILE (ojo que esto no hace que shorewall use ese archivo para escribir los logs (ya que esto lo hace netfilter), si no que le dice dónde leer el archivo para procesar los comandos "show log", "logwatch" y "'dump".
Las variables que cambiamos quedan así en /etc/shorewall/shorewall.conf (en /etc/shorewall6/shorewall6.conf no porque, lamentablemente, IPv6 no soporta ULOG y en ubuntu no tenemos NFLOG).
/etc/shorewall/shorewall.conf:
############################################################################### # L O G G I N G ############################################################################### BLACKLIST_LOGLEVEL=ULOG LOG_MARTIANS=Yes LOG_VERBOSITY=2 LOGALLNEW= LOGFILE=/var/log/ulog/syslogemu.log LOGFORMAT="Shorewall:%s:%s:" LOGTAGONLY=No LOGLIMIT= MACLIST_LOG_LEVEL=ULOG SFILTER_LOG_LEVEL=ULOG SMURF_LOG_LEVEL=ULOG STARTUP_LOG=/var/log/shorewall-init.log TCP_FLAGS_LOG_LEVEL=ULOG
/etc/shorewall6/shorewall6.conf:
############################################################################### # L O G G I N G ############################################################################### BLACKLIST_LOGLEVEL=info LOG_VERBOSITY=2 LOGALLNEW= LOGFILE=/var/log/kern.log LOGFORMAT="Shorewall:%s:%s:" LOGLIMIT= LOGTAGONLY=No MACLIST_LOG_LEVEL=info SFILTER_LOG_LEVEL=info SMURF_LOG_LEVEL=info STARTUP_LOG=/var/log/shorewall6-init.log TCP_FLAGS_LOG_LEVEL=info
zonas anidadas
Para facilitar el funcionamiento de zonas anidadas, habilitamos un CONTINUE implícito (tanto en /etc/shorewall/shorewall.conf como en /etc/shorewall6/shorewall6.conf):
IMPLICIT_CONTINUE=Yes
optimización de reglas
Para optimizar las reglas casi sin afectar la legibilidad de las mismas ponemos (tanto en /etc/shorewall/shorewall.conf como en /etc/shorewall6/shorewall6.conf):
OPTIMIZE=1
Se pueden hacer más optimizaciones pero puede afectar el debugging de reglas. Ver la opción OPTIMIZE en man shorewall.conf y man shorewall6.conf
lock file
Por algún motivo, este parámetro está en blanco y, de acuerdo a la documentación de shorewall en debian (y ubuntu) debe ir así:
/etc/shorewall/shorewall.conf:
SUBSYSLOCK=/var/lock/shorewall
/etc/shorewall6/shorewall6.conf:
SUBSYSLOCK=/var/lock/shorewall6
otros archivos de configuración
Todos los archivos que se utilizan para configurar shorewall deben ir in /etc/shorewall y los que se utilizan para configurar shorewall6 en /etc/shorewall6.
Si bien la instalación no copia nada aquí, hay archivos por default para cada uno de estos en /usr/share/shorewall/configfiles/ y /usr/share/shorewall6/configfiles/ respectivamente.
Además, para cada archivo hay una versión que termina con ".annotated" donde están comentadas las configuraciones posibles en ese archivo.
zones
El archivo zones (tanto en /etc/shorewall como en /etc/shorewall6) se utiliza para definir (ponerles nombre a) las zonas que utilizaremos en las reglas y políticas (que se aplican para tráfico que va de una zona a otra).
Siempre hay que incluir en firewall como fw (ya viene en el archivo default).
Por ahora sólo agregamos una zona que llamamos net en cada uno de los archivos para referirnos a todos los hosts externos (internet). En shorewall el tipo de esta zona es ipv4 y en shorewall6 es ipv6
/etc/shorewall/zones:
############################################################################### #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall net ipv4
/etc/shorewall6/zones:
############################################################################### #ZONE TYPE OPTIONS IN OUT # OPTIONS OPTIONS fw firewall net ipv6
interfaces
Estos archivos se utilizan para definir las interfaces de red del equipo (nosotros tenemos una sola). Los nombres de zona asociados a una interface deben estar definidos en el archivo zones correspondiente. La zona fw no se puede asociar a una interface.
/etc/shorewall/interfaces:
############################################################################### #ZONE INTERFACE BROADCAST OPTIONS net eth0 - tcpflags,logmartians,nosmurfs
/etc/shorewall6/interfaces:
############################################################################### #ZONE INTERFACE ANYCAST OPTIONS net eth0 - tcpflags
policy
En este archivo se definen las políticas de alto nivel para conexiones entre zonas. Es decir, se define qué se hará con las conexiones desde una zona a otra si no hay ninguna regla específica (en el archivo rules).
El orden de las políticas es importante. El archivo se procesa de arriba hacia abajo y la primera política que matchea fuente y destino se aplica.
Si ninguna política se aplica, el resultado es indefinido, por lo que es conveniente poner una política al final de todo el archivo con fuente all y destino all.
/etc/shorewall/policy:
############################################################################### #SOURCE DEST POLICY LOG LIMIT: CONNLIMIT: # LEVEL BURST MASK # Por ahora permitimos todo el trafico saliente. # En el futuro es conveniente restringir esto (se puede poner un REJECT # para que 'conteste' rapido). fw net ACCEPT # Todo trafico entrante que no este explicitamente permitido en una regla # lo descartamos y logueamos (esto loguea mucho, ya que normalmente, hay # bots intentando hacer cualquier cosa). net fw DROP ULOG # ESTA DEBE SER LA ULTIMA POLITICA # Esto es una red de seguridad por si agregamos nuevas zonas y nos olvidamos # de configurar una politica. Todo lo demas se descarta. # ESTA DEBE SER LA ULTIMA POLITICA all all DROP ULOG
/etc/shorewall6/policy:
############################################################################### #SOURCE DEST POLICY LOG LIMIT: CONNLIMIT: # LEVEL BURST MASK # Por ahora permitimos todo el trafico saliente. # En el futuro es conveniente restringir esto (se puede poner un REJECT # para que 'conteste' rapido). fw net ACCEPT # Todo trafico entrante que no este explicitamente permitido en una regla # lo descartamos y logueamos (esto loguea mucho, ya que normalmente, hay # bots intentando hacer cualquier cosa). net fw DROP info # ESTA DEBE SER LA ULTIMA POLITICA # Esto es una red de seguridad por si agregamos nuevas zonas y nos olvidamos # de configurar una politica. Todo lo demas se descarta. # ESTA DEBE SER LA ULTIMA POLITICA all all DROP info
rules
Aquí van las reglas específicas que permiten o prohiben determinado tráfico desde una zona a otra. Las acciones se aplican al inicio de una conexión, los demás paquetes de la conexión siguen adelante.
El orden de las reglas es importante. El archivo se procesa de arriba hacia abajo y la primera regla que matchea fuente y destino se aplica. Todas las acciones salvo LOG y COUNT terminan el procesamiento.
/etc/shorewall/rules y /etc/shorewall6/rules (son iguales):
#################################################################################################################################################################### #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS # PORT PORT(S) DEST LIMIT GROUP #SECTION ESTABLISHED #SECTION RELATED SECTION NEW ################ # DNS ################ # Permitimos consultas DNS salientes DNS(ACCEPT) $FW all ################ # SSH ################ # Permitimos salir via SSH SSH(ACCEPT) $FW all # Permitimos entrar via SSH desde cualquier lado # En el futuro habría que implementar algún doorknob para impedir ataques al SSH SSH(ACCEPT) all $FW ################ # Web (http+https) ################ # Permitimos conexiones salientes a la web (esto despues lo podriamos restringir) Web(ACCEPT) $FW all # Permitimos que se vean nuestros servidores web Web(ACCEPT) all $FW
Habilitar Shorewall
Para habilitar shorewall hay que editar los archivos /etc/default/shorewall y /etc/default/shorewall6 y poner:
startup=1
Para arrancarlos:
sudo invoke-rc.d shorewall start sudo invoke-rc.d shorewall6 start
La instalación dejó configurado el arranque automático al bootear.
Modificar la configuración de syslog para que la salida del firewall no se mezcle con lo demás
Si bien configuramos iptables para que loguee utilizando ulogd, iptables6 no lo puede hacer, con lo cual todo el logging IPv6 del firewall (que puede ser mucho) saldrá mezclado en /var/log/syslog y /var/log/messages.
El logging de iptables usa la facility kernel del syslog (lo cual no se puede modificar), con lo cual se mezclará con cualquier otro mensaje con facility kernel de /var/log/messages y /var/log/syslog.
Para sacar los mensajes con facility kernel tenemos que editar /etc/rsyslog.d/50-default.conf:
- Buscar una línea como la siguiente:
*.*;auth,authpriv.none -/var/log/syslog
esto quiere decir, "enviar todo a /var/log/syslog.conf excepto los mensajes de los facilities auth y authpriv. Para indicarle que tampoco mande los mensajes del facility kernel hay que dejar esa línea así:
*.*;auth,authpriv.none,kern.none -/var/log/syslog
- Buscar otra línea como la siguiente
*.=info;*.=notice;*.=warning;\
auth,authpriv.none;\
cron,daemon.none;\
mail,news.none -/var/log/messagesesto envia algunos mensajes menos a /var/log/messages. Para quitar también de aquí los mensajes del facility kernel hay que dejar la línea así:
*.=info;*.=notice;*.=warn;\
auth,authpriv.none;\
cron,daemon.none;\
kern.none;\
mail,news.none -/var/log/messagesAhora los mensajes del facility kernel sólo aparecerán en el archivo /var/log/kern.log debido a la siguiente línea (que ya está así por defecto):
kern.* -/var/log/kern.log
Ahora, sólo queda reiniciar el rsyslog:
sudo service rsyslog restart