Archivo de la categoría: How-To

Debian: Como correr un daemon en el arranque del sistema (Ej. Reglas de iptables)

pacamanfirewallPruebas realizadas desde: GNU/Linux Debian “Wheezy” (7.4)

Objetivo: En este tutorial trataremos de crear un script que se ejecute al arrancar nuestro sistema GNU/Linux, el script consiste en (aunque podemos hacer scripts que hagan otras cosas) reglas de iptables de un firewall stateful que acepta de ENTRADA: ICMP echo-request, peticiones a puerto 80 (servidor web) y de SALIDA: ICMP echo-request, con peticiones a servicios de uso común para poder navegar sin muchas restricciones (puerto 80, 53, 21, 22, 443).

Bueno, habrá veces que queramos ejecutar un script cuando arranca nuestro sistema Linux, por ejemplo, si queremos cargar reglas para nuestro firewall (iptables). El primer programa que corre Linux al arrancar es “init”, su archivo de configuración se encuentra en /etc/inittab, las primeras líneas del archivo serían algo como lo siguiente:

# The default runlevel.
id:2:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

Cada “runlevel” describe un estado de la máquina, por decir 0 es para halt (cuando se detiene), 1 es para single-user, de 2 a 5 es el multiusuario y 6 es cuando se reinicia. Los scripts que se ejecutan por cada runlevel se encuentran ubicados en rutas específicas, por ejemplo para el runlevel 0, en /etc/rc0.d … de manera genérica sería algo como /etc/rc#.d donde # sería el número del runlevel (0 a 6)… si queremos conocer nuestro runlevel podemos ejecutar en la terminal:

root:~# runlevel

Ahora bien, los demonios (daemons) que se ejecutan al inicio se encuentran ubicados en /etc/init.d, si queremos crear un script propio que se ejecute al arranque deberemos crearlo en esa ruta, por decir:

root:~# cd /etc/init.d
root:/etc/init.d# touch fw
root:/etc/init.d# chmod +x fw

Si lo queremos editar desde consola podemos usar nano, vi, etc:

root:/etc/init.d# nano fw

El script propiamente podría ejecutar cualquier cosa, por ejemplo:

#! /bin/bash
echo "Script que se ejecuta al arranque..."

Para habilitar daemons (con configuración default) usaremos el comando “insserv”, ejecutariamos en la terminal algo como:

root:/etc/init.d# insserv fw

Nos manda el siguiente mensaje:

insserv: warning: script 'fw' missing LSB tags and overrides

El problema es que nuestro script debe tener ciertos encabezados “LSB” para que el sistema lo reconozca y sepa que hacer con él. Nuestro script con encabezados quedaría algo como lo siguiente:

#! /bin/bash
### BEGIN INIT INFO
# Provides: fw
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Daemon que carga reglas de fw
# Description: Daemon que carga nuestras reglas de iptables.
### END INIT INFO
echo "Script que se ejecuta al arranque..."

+ Descripción de los encabezados

Ahora si lo volvemos a cargar con insserv:

root:/etc/init.d# insserv fw

Tenemos que si nuestros encabezados están bien ya no marcará error, y la próxima vez que reiniciemos se empezará a ejecutar nuestro demonio (considerando los encabezados LSB).

Para remover un daemon de la ejecución al inicio ejecutamos insserv con -r y el nombre del demonio:

root:/etc/init.d# insserv -r fw

Buscaremos programar nuestro script para que acepte cierto control, por decir, algunos daemons aceptan parámetros, del tipo start|stop|restart … por ejemplo el daemon de apache o del network-manager:

root:~# /etc/init.d/apache2 status
Apache2 is running (pid 2812).
root:~# /etc/init.d/network-manager status
[ ok ] NetworkManager is running.

Volviendo a nuestro script, si lo dejáramos como está se ejecutaría lo mismo independientemente de si se apaga o se inicia la computadora… lo que buscaríamos sería más bien que por decir, al iniciar el ordenador se cargaran las reglas del FW y al apagar se borraran las reglas.

De manera genérica, los pasos ya descritos nos servirán para que se ejecute cualquier script que programemos en el runlevel deseado … sin embargo pongo el código de como quedaría mi firewall gestionando los status de “start, stop y restart”. En otro post explicaré un poco más sobre iptables y firewalls pero por ahora espero con éste código se ejemplifique mejor el concepto de como correr daemons al arranque del sistema:

#! /bin/bash
### BEGIN INIT INFO
# Provides:	fw
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop:	0 1 6
# Short-Description: Carga Reglas de IPTABLES
# Description: Carga reglas de fw
### END INIT INFO

start() {
echo "CONFIGURANDO FIREWALL"

echo "[+] Limpiando reglas"
# Limpiar reglas
iptables -X
iptables -F
iptables -t nat -F

echo "[+] Definiendo politica dura"
# Politica dura
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# Reglas de entrada
echo "[+] Configurando cadenas de ENTRADA"
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
iptables -A INPUT -p tcp --dport 80 --syn -m state --state NEW -j ACCEPT

# Reglas de salida
echo "[+] Configurando cadenas de SALIDA"
iptables -A OUTPUT -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT

iptables -A OUTPUT -p tcp --dport 80 --syn -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 --syn -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 --syn -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 22 --syn -m state --state NEW -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 --syn -m state --state NEW -j ACCEPT
}

stop() {
echo "[+] Borrando reglas de iptables"
iptables -F
iptables -X

echo "[+] Quitando politica dura"
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
}

#Revisamos permisos de root
if [ "$(id -u)" != "0" ]; then
	echo "Necesarios permisos de root..." 1>&2
	exit 1
fi

# En un case gestionamos start|stop|restart
case "$1" in
	start)
		start
		exit 0
	;;
	stop)
		stop
		exit 0
	;;
	restart)
		stop
		start
		exit 0
	;;
	**)
		echo "Uso: $0 {start|stop|restart}" 1>&2
		exit 1
	;;
esac

Espero sea de utilidad, se puede encontrar más información en el wiki de Debian, dejo los enlaces 🙂

Enlaces de interés:
https://wiki.debian.org/Daemon
http://www.debian.org/doc/debian-policy/ch-opersys.html#s-sysvinit
https://wiki.debian.org/LSBInitScripts/DependencyBasedBoot?highlight=%28\bCategoryBootProcess\b%29
https://wiki.debian.org/LSBInitScripts