Bash script para configurar el muro de fuego (firewall)
guivaloz
2009-06-29 13:15
Bash script, Firewall, Gentoo, Kernel

Introducción
Un muro de fuego o cortafuegos (o firewall en inglés) es un parte de un sistema o una red que está diseñado para bloquear el acceso no autorizado, permitiendo al mismo tiempo el paso autorizado de ciertas comunicaciones. ( Fuente: Wikipedia )
GNU/Linux es el mejor sistema operativo. Es confiable, estable y seguro. El simple hecho de usar GNU/Linux y NO Windows nos da una protección mayor que este segundo.
Podemos incrementar la seguridad de nuestro GNU/Linux levantando un muro de fuego. Esto lo recomiendo para equipos portátiles que se conecten a redes públicas. Dicho de otro modo, cuando estés fuera de tu hogar o lugar de trabajo levanta el muro de fuego. Siempre ten presente que pudiera haber algún otro equipo, en la red local o desde internet, buscando vulnerabilidades en nuestra portátil.
El muro de fuego en GNU/Linux está en el mismo kernel, el Linux. Para configurarlo se usa el comando iptables.
Por ejemplo, abre una terminal y ejecuta el siguiente comando:
$ sudo iptables -t filter -L -n
Si tu muro de fuego no está levantado, recibirás un texto parecido al siguiente:
Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
Aquí se muestra que no hay filtros en esas cadenas (chains), lo que significa que todas las comunicaciones pasarán sin reestricciones entre tu equipo y la red a la que estés conectado.
A continuación les mostraré el Bash Script que ejecuto para habilitar o deshabiltar el muro de fuego en mi computadora portátil.
Objetivos
Cada quien puede tener sus necesidades particulares. El manejo completo de muros de fuego es un tema muy extenso y hay muchos libros que tratan de ello. Para su servidor, he hecho un script que me resulve tres situaciones:
- Que cuando necesite trabajar sin muro de fuego pueda limpiar todas las reglas del mismo.
- Que cuando me encuentre en una red confiable pueda tener abiertos los puertos para ssh, http, samba, rsync y todos los mayores e igual a 1024.
- Que cuando me encuentre en una red insegura cierre todos los puertos para las peticiones desde afuera hacia mi equipo.
Requerimientos
- Este script ha sido usado en Gentoo Linux. Teóricamente debería funcionar en cualquier otra distribución GNU/Linux, aunque tal vez necesite algunas modificaciones.
- Kernel Linux 2.6 con soporte para iptables. Si usa un kernel genérico, como el de Debian o Ubuntu, seguramente tendrá esta opción lista. Si no, vea la configuración de mi kernel 2.6.29
- Por defecto, el comando iptables sólo lo puede ejecutar root. Si desea ejecutar este script como un usuario normal, deberá poder ejecutar sudo iptables sin que le pida contraseña, de lo contrario se la solicitará muchas veces. Configure sudo si es necesario.
El script firewall.sh
Puede descargar el script aquí o también seleccionar el texto siguiente, copiar y pegar.
#!/bin/bash
#
# firewall.sh - Script para configurar el muro de fuego
# 28 de julio de 2009
# Copyright (C) 2009 Guillermo Valdes Lozano
# http://www.movimientolibre.com/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Este script ha sido probado en Gentoo Linux. Requiere:
#
# 1) Kernel con soporte para IPTables
#
# 2) Que este instalado "net-firewall/iptables".
#
# 3) Que el comando /sbin/iptables pueda ejecutarse por el usuario.
# Por defecto, sólo root puede hacerlo. Para ello, instale "app-admin/sudo",
# luego ejecute "visudo" como root y agregue la siguiente linea:
#
# %wheel ALL=(ALL) NOPASSWD: /sbin/iptables
#
# Nombre de este script
SOY="[Firewall]"
# Comando a ejecutar
CMD="sudo /sbin/iptables"
# Constantes que definen los tipos de errores
EXITO=0
E_NOARGS=65
E_DUPLICADO=98
E_FATAL=99
# Mensaje para mostrar por falta de argumentos
function ayuda() {
echo "$SOY Ayuda"
echo
echo "Objetivo:"
echo " Configurar el muro de fuego"
echo
echo "Sintaxis:"
echo " firewall.sh <DISPOSITIVO> <CONFIANZA>"
echo " firewall.sh limpio"
echo
echo "Parametros:"
echo " <DISPOSITIVO> eth0, eth1 o wlan0,"
echo " <CONFIANZA> insegura o confiable"
echo
echo "Ejemplos:"
echo " firewall.sh limpio"
echo " firewall.sh eth0 confiable"
echo " firewall.sh eth1 inseguro"
echo
}
# Si el primer parametro es "limpio"
# Vaciamos las cadenas del muro de fuego y
# aceptamos todas las conexiones y terminamos
if [ "$1" = "limpio" ]; then
echo "$SOY Limpiando las cadenas."
$CMD -t filter -F
$CMD -t nat -F
echo "$SOY ADVERTENCIA: SE ACEPTARAN TODAS LAS CONEXIONES."
$CMD -P INPUT ACCEPT
$CMD -P OUTPUT ACCEPT
$CMD -P FORWARD ACCEPT
echo "$SOY Script terminado."
exit $EXITO
fi
#
# Parametros
#
# Primer parámetro: dispositivo de red
case "$1" in
"eth0")
INTERFAZ="eth0"
;;
"eth1")
INTERFAZ="eth1"
;;
"wlan0")
INTERFAZ="wlan0"
;;
*)
echo "$SOY ERROR: Dispositivo de red incorrecto."
ayuda
exit $E_FATAL
;;
esac
# Segundo parámetro: confiabilidad de la red
case "$2" in
"confiable")
CONFIABILIDAD="confiable"
;;
"insegura" | "inseguro")
CONFIABILIDAD="insegura"
;;
*)
echo "$SOY Por defecto la red se considera INSEGURA."
CONFIABILIDAD="insegura"
;;
esac
#
# Proceso
#
# Vaciar las reglas
echo "$SOY Vaciando las reglas actuales."
$CMD -t filter -F
$CMD -t nat -F
if [ $CONFIABILIDAD = "confiable" ]; then
echo "$SOY La red es CONFIABLE."
$CMD -P INPUT DROP
$CMD -P OUTPUT ACCEPT
$CMD -P FORWARD ACCEPT
fi
if [ $CONFIABILIDAD = "insegura" ]; then
echo "$SOY La red es INSEGURA."
$CMD -P INPUT DROP
$CMD -P OUTPUT DROP
$CMD -P FORWARD DROP
fi
echo "$SOY Aceptar toda entrada y salida por loopback."
$CMD -A INPUT -i lo -j ACCEPT
$CMD -A OUTPUT -o lo -j ACCEPT
echo "$SOY Aceptar las comunicaciones establecidas."
$CMD -A INPUT -m state --state ESTABLISHED -j ACCEPT
$CMD -A INPUT -m state --state RELATED -j ACCEPT
if [ $CONFIABILIDAD = "insegura" ]; then
echo "$SOY SOLO PERMITIR la salida de paquetes nuevos y establecidos."
$CMD -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
fi
if [ $CONFIABILIDAD = "confiable" ]; then
echo "$SOY Aceptar SSH (TCP 22) en $INTERFAZ"
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 22 -j ACCEPT
echo "$SOY Aceptar HTTP (TCP 80) en $INTERFAZ"
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 80 -j ACCEPT
echo "$SOY Aceptar Samba (TCP y UDP 137, 138, 139, 445) en $INTERFAZ"
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 137:139 -j ACCEPT
$CMD -A INPUT -i $INTERFAZ -p udp --dport 137:139 -j ACCEPT
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 445 -j ACCEPT
$CMD -A INPUT -i $INTERFAZ -p udp --dport 445 -j ACCEPT
echo "$SOY Aceptar rsync (TCP 873) en $INTERFAZ"
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 873 -j ACCEPT
echo "$SOY ACEPTAR TODO por puertos del 1024 al 65535 en $INTERFAZ"
$CMD -A INPUT -i $INTERFAZ -p tcp --dport 1024:65535 -j ACCEPT
$CMD -A INPUT -i $INTERFAZ -p udp --dport 1024:65535 -j ACCEPT
echo "$SOY Aceptar pings."
$CMD -A INPUT -p icmp -j ACCEPT
fi
# Para depurar quite los comentarios a los siguientes comandos
# echo "$SOY Configuración lista:"
# $CMD -L -n -v -t filter
# echo
# Mensaje final
echo "$SOY Script terminado."
Haga el script ejecutable
No olvide hacer ejecutable el archivo firewall.sh con el siguiente comando:
# chmod a+x firewall.sh
Probando el script
Con el parámetro limpio vacío las cadenas y deshabilito el muro de fuego.
$ ./firewall.sh limpio [Firewall] Limpiando las cadenas. [Firewall] ADVERTENCIA: SE ACEPTARAN TODAS LAS CONEXIONES. [Firewall] Script terminado.
Indicando el dispositivo de red (en mi caso es eth1) y la opción confiable.
$ ./firewall.sh eth1 confiable [Firewall] Vaciando las reglas actuales. [Firewall] La red es CONFIABLE. [Firewall] Aceptar toda entrada y salida por loopback. [Firewall] Aceptar las comunicaciones establecidas. [Firewall] Aceptar SSH (TCP 22) en eth1 [Firewall] Aceptar HTTP (TCP 80) en eth1 [Firewall] Aceptar Samba (TCP y UDP 137, 138, 139, 445) en eth1 [Firewall] Aceptar rsync (TCP 873) en eth1 [Firewall] ACEPTAR TODO por puertos del 1024 al 65535 en eth1 [Firewall] Aceptar pings. [Firewall] Script terminado.
Podemos ver el resultado de la ejecución anterior con el comando:
$ sudo iptables -t filter -L -n -v
El cual me entrega lo siguiente:
Chain INPUT (policy DROP 12 packets, 2496 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
572 601K ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpts:137:139
3 405 ACCEPT udp -- eth1 * 0.0.0.0/0 0.0.0.0/0 udp dpts:137:139
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:445
0 0 ACCEPT udp -- eth1 * 0.0.0.0/0 0.0.0.0/0 udp dpt:445
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:873
0 0 ACCEPT tcp -- eth1 * 0.0.0.0/0 0.0.0.0/0 tcp dpts:1024:65535
0 0 ACCEPT udp -- eth1 * 0.0.0.0/0 0.0.0.0/0 udp dpts:1024:65535
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 514 packets, 37799 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
Por último, pruebo la opción insegura.
$ ./firewall.sh eth1 insegura [Firewall] Vaciando las reglas actuales. [Firewall] La red es INSEGURA. [Firewall] Aceptar toda entrada y salida por loopback. [Firewall] Aceptar las comunicaciones establecidas. [Firewall] SOLO PERMITIR la salida de paquetes nuevos y establecidos. [Firewall] Script terminado.
Personalízelo
Por ejemplo, si ejecuta un servidor FTP, agregue las siguientes líneas en la parte confiable del programa:
echo "$SOY Aceptar conexiones por FTP." $CMD -A INPUT -i $INTERFAZ -p tcp --dport 20 -j ACCEPT $CMD -A INPUT -i $INTERFAZ -p tcp --dport 21 -j ACCEPT
Si tiene un servidor apache y páginas por https, agregue:
echo "$SOY Aceptar HTTPS (TCP 443) en $INTERFAZ" $CMD -A INPUT -i $INTERFAZ -p tcp --dport 443 -j ACCEPT
Accesos directos para ejecutarlo
Yo he depositado el script firewall.sh en un directorio llamado bin en mi HOME. Los siguientes archivos desktop ejecutarán el script con los parámetros que llevan. Este es para limpiar el muro de fuego:
[Desktop Entry] Encoding=UTF-8 Name=Firewall Limpio Comment=Sin firewall, todo permitido Type=Application Exec=$HOME/bin/firewall.sh limpio StartupNotify=false Terminal=true TerminalOptions= --noclose Icon=decrypted
Este para ponerlo en confiable:
[Desktop Entry] Encoding=UTF-8 Name=Firewall eth1 Confiable Comment=Firewall eth1 Confiable Type=Application Exec=$HOME/bin/firewall.sh eth1 confiable StartupNotify=false Terminal=true TerminalOptions= --noclose Icon=halfencrypted
Y este es para una red insegura:
[Desktop Entry] Encoding=UTF-8 Name=Firewall eth1 Insegura Comment=Firewall eth1 Insegura Type=Application Exec=$HOME/bin/firewall.sh eth1 insegura StartupNotify=false Terminal=true TerminalOptions= --noclose Icon=encrypted
Estos tres archivos desktop los coloco dentro del directorio kde-launcher que está en $HOME/bin. Luego, en KDE agrego un navegador de archivos que apunta a ese directorio para ejecutarlos fácilmente. Así se ven:





