Serveur WEB / NetFilter

Salut à tous!
J’ai mis en place un petit serveur Web récemment.
Dans l’optique de commencer la sécurisation de ce dernier, j’ai attaqué la mise en place
d’un petit script permettant de réglé les règles iptables.

N’ayant eu qu’un cours relativement light sur iptables, je n’ai pas une grande connaissance de l’outil.
Après avoir parcouru certain forum et document en ligne, mon fichier ressemble à celui ci-dessous.

Vous l’aurez comprit, malgré le fait qu’il soit question d’un simple petit réglage pour un serveur web,
je suis légèrement dans le doute quand à ma configuration. En espérant que vous puissiez m’apporter des
conseilles.

Salutation.

#! /bin/sh
### BEGIN INIT INFO
# Provides:          bla bla
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: bla bla
# Description:       bla bla
#                    placed in /etc/init.d.
### END INIT INFO

# Variables
PORT_SSH=22
PORT_SMTP=25
PORT_DNS=53
PORT_HTTP=80

start()
        {
                # Reset Tables
                iptables -t filter -F

                # Reset Personnal Rules
                iptables -t filter -X

                # Close All
                iptables -t filter -P INPUT DROP
                iptables -t filter -P FORWARD DROP
                iptables -t filter -P OUTPUT DROP

                # Allow loopback
                iptables -t filter -A INPUT -i lo -j ACCEPT
                iptables -t filter -A OUTPUT -o lo -j ACCEPT

                # Allow ICMP (Ping)
                iptables -t filter -A INPUT -p icmp -j ACCEPT
                iptables -t filter -A OUTPUT -p icmp -j ACCEPT

                # Allow SSH Connexion
                iptables -t filter -A INPUT -p tcp --dport $PORT_SSH -j ACCEPT
                iptables -t filter -A OUTPUT -p tcp --sport $PORT_SSH -j ACCEPT

                # Allow to Send E-Mail
                iptables -t filter -A INPUT -p tcp --sport $PORT_SMTP -j ACCEPT
                iptables -t filter -A OUTPUT -p tcp --dport $PORT_SMTP -j ACCEPT

		# Allow DNS Resolv
                iptables -t filter -A INPUT -p tcp --sport $PORT_DNS -j ACCEPT
                iptables -t filter -A INPUT -p udp --sport $PORT_DNS -j ACCEPT
                iptables -t filter -A OUTPUT -p tcp --dport $PORT_DNS -j ACCEPT
                iptables -t filter -A OUTPUT -p udp --dport $PORT_DNS -j ACCEPT

                #Allow HTTP
                iptables -t filter -A INPUT -p tcp --dport $PORT_HTTP -j ACCEPT
                iptables -t filter -A OUTPUT -p tcp --sport $PORT_HTTP -j ACCEPT

                echo "FireWall Started"
        }

stop()
        {
                # Vider les tables actuelles
                iptables -t filter -F

                # Vider les regles personnelles
                iptables -t filter -X

                # Autoriser toutes les connexion entrantes et sortantes
                iptables -t filter -P INPUT ACCEPT
                iptables -t filter -P FORWARD ACCEPT
                iptables -t filter -P OUTPUT ACCEPT
 
                echo "FireWall Stopped."
        }       


case "$1" in
	start)
		start
	;;
	stop)
		stop
	;;
	restart)
		stop
		start
	;;
	*)
		echo "Usage: firewall {start|stop|restart}"
		exit 1
	;;
esac

Le protocole ICMP, c’est bien plus vaste que le seul ping. Ping, c’est le type echo request (–icmp-type echo-request).

Toutes ces règles avec --sport, c’est mauvais. Un vraie passoire dans la mesure où l’émetteur peut choisir le port source. On se croirait revenu au temps d’ipchains il y a 10 ans. Ce n’est pas pour rien que depuis on a inventé le suivi de connexion pour reconnaître les paquets retour. Supprime toutes ces règles et ajoute à la place en début de chaîne

iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -t filter -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Hello.
Concernant les entrées --sport, impossible de fonctionner sans.
A la base je n’avais utiliser quand des dport. Malheureusement impossible d’établir une connexion avec mon serveur par la suite.
Ma seul solution à donc été d’utiliser une entrée --dport et une --sport. Une idée de la provenance d’un tel phénomène ?

iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t filter -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

J’avais également utilisé ceci au début afin de maintenir les connexions existantes.
A chaque utilisation j’ai eu le retour suivant: iptables: No chain/target/match by that name

–sport est nécessaire pour accepter le trafic retour si on n’utilise pas le suivi de connexion, mais c’est un pis-aller. Pour les paquets TCP, ajoute au moins “! --syn”.

Concernant le message d’erreur, comme a priori la chaîne et la cible existent bien, le problème se situe du côté de la correspondance “state”. Quel noyau utilises-tu ? Un noyau Debian standard ?

J’utilise une Debian Squeeze.
Mais avec un Noyau 2.6.24-11-pve.

C’est une machine virtuelle gérée via Proxmox.
viendrait de là?

Donc un noyau particulier.
Je ne connais pas Proxmox, mais si les machines virtuelles partagent le même noyau que la machine hôte, alors ça peut venir de là. Dans ce cas je suppose qu’il faut charger les modules de suivi de connexion depuis le système hôte. Si le noyau a été compilé sans le support du suivi de connexion (conntrack), alors c’est mort.

renvoie quelque chose ?

zgrep renvoie que le fichier n’existe pas.
Que se soit du côté VM ou du côté hôte physique.

Par contre le module existe du côté hôte physique. Il semble possible d’ajouter
ip_conntrack dans le fichier /etc/vz/vz.conf (Au niveau IP V4.)

L’on dirait que cela nécessite un redémarrage de l’hôte physique Glump.
J’ai pas trouvé d’information claire à ce sujet pour le moment.

Et juste charger les modules ip_conntrack/nf_conntrack_ipv4 et ipt_state/xt_state avec modprobe depuis la machine hôte, ça ne suffit pas ?

Non, rien n’y fait.

En effet, d’après le wiki d’OpenVZ, il faut charger les modules nécessaires avant de démarrer le “container” (machine virtuelle).

Hello!
Le service OpenVZ ayant été “rebooté” en début de soirée, j’ai pu réalisés un test ce matin.
L’ajout, dans le fichier /etc/vz/vz.conf (variable IPTABLES pour IPv4) de ip_conntrack et ipt_state est un succès :slightly_smiling:

Voici mon script “FireWall”:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO

####################
# Port Variables
####################
NETWORK="172.20.0.0/23"
PORT_SSH=22
PORT_SMTP=25
PORT_DNS=53
PORT_HTTP=80
PORT_REDMINE=3000
####################

####################
# Functions
####################
start()
	{
		#Clean all existing configuration
		echo "Clean all iptables informations"
		iptables -t filter -F
		iptables -t filter -X

		#Close all
		echo "Close all connection"
		iptables -t filter -P INPUT DROP
                iptables -t filter -P FORWARD DROP
                iptables -t filter -P OUTPUT DROP

		#Keep current connexion
		echo "Keep current connexion"
		iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
		iptables -t filter -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

		#Allow loopback
		echo "Allow loopback"
		iptables -t filter -A INPUT -i li -j ACCEPT
		iptables -t filter -A OUTPUT -o lo -j ACCEPT

		#Allow ICMP IN/OUT
		echo "Allow ICMP"
		iptables -t filter -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
                iptables -t filter -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT

		#Allow DNS OUT
		echo "Allow DNS OUT"
		iptables -t filter -A OUTPUT -p udp --dport $PORT_DNS -j ACCEPT
		iptables -t filter -A OUTPUT -p tcp --dport $PORT_DNS -j ACCEPT

		#Allow SSH Connection IN
		echo "Allow SSH Connection"
		iptables -t filter -A INPUT -p tcp --dport $PORT_SSH -s $NETWORK -j ACCEPT

		#Allow SMTP OUT
		iptables -t filter -A OUTPUT -p tcp --dport $PORT_SMTP -j ACCEPT

		#Allow HTTP IN
		echo "Allow HTTP Server"
		iptables -t filter -A INPUT -p tcp --dport $PORT_HTTP -j ACCEPT
		iptables -t filter -A INPUT -p tcp --dport $PORT_REDMINE -s $NETWORK -j ACCEPT

		#End Message
		echo -n "\033[1;32m FireWall Started \033[0m \n"
	}


stop()
        {
		#Clean all existing configuration
		echo "Clean all iptables informations"
		iptables -t filter -F
		iptables -t filter -X

		#Close all
		echo "open all connection"
		iptables -t filter -P INPUT ACCEPT
                iptables -t filter -P FORWARD ACCEPT
                iptables -t filter -P OUTPUT ACCEPT

		#End Message
		echo -n "\033[1;31m FireWall Stopped  \033[m \n"
        }
####################

####################
# Main Script
####################
case "$1" in
	start)
		start
	;;
	stop)
		stop
	;;
	restart)
		stop
		start
	;;
	*)
		echo "Usage: firewall {start|stop|restart}"
		exit 1
	;;
esac

C’est une bonne base, propre et simple.

Juste une réserve personnelle concernant les runlevels : je démarrerais le script dans le runlevel S afin que les règles soient en place avant le démarrage du réseau (networking), et je ne l’arrêterais que dans les runlevels 0 et 6, le laissant actif en runlevel 1.