« Iptables pare-feu » : différence entre les versions
(conversion de la documentation originale de Léa par HTML::WikiConverter) |
Aucun résumé des modifications |
||
(9 versions intermédiaires par 6 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
= Mur pare feu pas à pas = | = Mur pare feu pas à pas = | ||
par [[Utilisateur:Fred|Fred]] | |||
Ce document explique comment constuire un mur pare feu, pas à pas, sans théorie, sans blabla. | |||
== Introduction == | == Introduction == | ||
Il n'est pas question d'expliquer ici le fonctionnement d'< | Il n'est pas question d'expliquer ici le fonctionnement d'<b>iptables</b>, il existe pour cela de très bons articles dont celui de [[iptables|Léa]]. Le mur pare feu que je vous propose de construire sera adapté à vos besoins. Il ne comportera aucun gadget, aucune optimisation du réseau. Ce sera un mur pare feu rien qu'un mur pare feu. | ||
== On commence == | == On commence == | ||
Vous devrez mettre dans le fichier < | Vous devrez mettre dans le fichier <b>/usr/bin/startfirewall</b> tout ce qui va suivre. | ||
Comme tout script, le script de notre mur pare feu doit commencer par : | Comme tout script, le script de notre mur pare feu doit commencer par : | ||
Ligne 31 : | Ligne 31 : | ||
== Politique par défaut == | == Politique par défaut == | ||
Un mur pare feu correctement configuré se doit de rejeter tout ce qui n'a pas été explicitement autorisé. C'est le rôle de la politique par défaut (< | Un mur pare feu correctement configuré se doit de rejeter tout ce qui n'a pas été explicitement autorisé. C'est le rôle de la politique par défaut (<b>default policy</b>). Pour fixer celle-ci, nous utilisons les 3 règles suivantes : | ||
<div class="code"> # (suite du script...)<br /> $IPTABLES -P INPUT DROP<br /> $IPTABLES -P OUTPUT DROP<br /> $IPTABLES -P FORWARD DROP </div> | <div class="code"> # (suite du script...)<br /> $IPTABLES -P INPUT DROP<br /> $IPTABLES -P OUTPUT DROP<br /> $IPTABLES -P FORWARD DROP </div> | ||
Ligne 39 : | Ligne 39 : | ||
== Les règles locales == | == Les règles locales == | ||
Pour ne pas être ennuyé, il faut tout autoriser pour ce qui est du traffic réseau local (sur '< | Pour ne pas être ennuyé, il faut tout autoriser pour ce qui est du traffic réseau local (sur '<b>lo</b>' et '<b>$INTERNAL_IF</b>' aka: '<b>eth0</b>') : | ||
<div class="code"> # (suite du script...)<br /> # "On accepte le traffic sur 'lo'"<br /> $IPTABLES -A INPUT -i lo -j ACCEPT<br /> $IPTABLES -A OUTPUT -o lo -j ACCEPT<br /> $IPTABLES -A FORWARD -i lo -j ACCEPT<br /> $IPTABLES -A FORWARD -o lo -j ACCEPT<br /><br /> # "On accepte le traffic sur le réseau local"<br /> $IPTABLES -A INPUT -i $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A FORWARD -i $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A FORWARD -o $INTERNAL_IF -j ACCEPT</div> | <div class="code"> # (suite du script...)<br /> # "On accepte le traffic sur 'lo'"<br /> $IPTABLES -A INPUT -i lo -j ACCEPT<br /> $IPTABLES -A OUTPUT -o lo -j ACCEPT<br /> $IPTABLES -A FORWARD -i lo -j ACCEPT<br /> $IPTABLES -A FORWARD -o lo -j ACCEPT<br /><br /> # "On accepte le traffic sur le réseau local"<br /> $IPTABLES -A INPUT -i $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A FORWARD -i $INTERNAL_IF -j ACCEPT<br /> $IPTABLES -A FORWARD -o $INTERNAL_IF -j ACCEPT</div> | ||
Ligne 49 : | Ligne 49 : | ||
Si vous ne regardez pas régulièrement les logs de votre mur pare feu, celui-ci a toutes les chances de devenir inefficace. Nous allons donc 'logguer' une partie des connexions que nous refuserons : | Si vous ne regardez pas régulièrement les logs de votre mur pare feu, celui-ci a toutes les chances de devenir inefficace. Nous allons donc 'logguer' une partie des connexions que nous refuserons : | ||
<div class="code"> # (suite du script...)<br /> # On loggue les packets DROPés<br /> $IPTABLES -A LOG_DROP -j LOG --log-prefix "[IPT] "<br /> $IPTABLES -A LOG_DROP -j DROP</div> | <div class="code"> # (suite du script...)<br /> # On loggue les packets DROPés<br /> $IPTABLES -N LOG_DROP<br /> $IPTABLES -A LOG_DROP -j LOG --log-prefix "[IPT] "<br /> $IPTABLES -A LOG_DROP -j DROP</div> | ||
Le texte < | Le texte <b>[IPT]</b> peut être remplacé par n'importe quel texte de votre choix. Vous pouvez, de la même façon, créer plusieurs cibles '<b>DROP</b>' pour les logguer différemment. | ||
== Partager la connexion == | == Partager la connexion == | ||
Ligne 64 : | Ligne 64 : | ||
A partir de maintenant je vais vous donner des recettes de cuisine. | A partir de maintenant je vais vous donner des recettes de cuisine. | ||
Tout d'abord, il faut savoir que vous pouvez au choix utiliser un numéro de port ou son nom dans le fichier < | Tout d'abord, il faut savoir que vous pouvez au choix utiliser un numéro de port ou son nom dans le fichier <b>[file://etc/services /etc/services]</b>. J'utiliserais, dans la mesure du possible, cette dernière solution. Je ne détaillerais pas tous les ports, si vous souhaitez utiliser un port que j'aurais omis, consultez <b>/etc/services</b>. Dans ce fichier, vous constaterez que certains ports sont indiqués comme utilisant le protocol <b>tcp</b>, <b>udp</b> ou autre. Pour autoriser ces protocols vous devrez changer le "<b>-p tcp</b>" par "<b>-p udp</b>" ou autre dans les exemples qui vont suivre. | ||
=== Cas général : réseau local vers internet === | === Cas général : réseau local vers internet === | ||
Ligne 70 : | Ligne 70 : | ||
Pour la plupart des connexions, tout ce que je vais dire ici s'applique (exceptions notables : l'irc/dcc, le ftp/actif). | Pour la plupart des connexions, tout ce que je vais dire ici s'applique (exceptions notables : l'irc/dcc, le ftp/actif). | ||
Pour autoriser les machines de votre réseau local (si le masquerading est activé) ainsi que votre serveur mur pare feu à se connecter à un port sur internet, il faut procéder de la maniére suivante (dans l'exemple j'autorise la connexion au WEB : < | Pour autoriser les machines de votre réseau local (si le masquerading est activé) ainsi que votre serveur mur pare feu à se connecter à un port sur internet, il faut procéder de la maniére suivante (dans l'exemple j'autorise la connexion au WEB : <b>www</b>): | ||
<div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport <span style="font-weight:bold">www</span> -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --dport <span style="font-weight:bold">www</span> -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT </div><div class="note">Chaque commande < | <div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport <span style="font-weight:bold">www</span> -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --dport <span style="font-weight:bold">www</span> -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT </div><div class="note">Chaque commande <b>$IPTABLES</b> doit être tapée sur une seule ligne depuis le <b>$IPTABLES</b> jusqu'au <b>-j ACCEPT</b> ou <b>-j DENY</b> (dans la suite...).</div> | ||
Une petite explication, la règle < | Une petite explication, la règle <b>$IPTABLES -A INPUT</b> s'applique au traffic entrant (tous les paquets IP entrant seront soumis à cette règle). Comme on a précisé <b>-p tcp</b>, la règle s'applique aux paquets utilisants le protocol <b>tcp</b>. On a aussi préciser <b>--sport www</b>, donc la règle s'applique au paquet qui proviennent (<b>sport</b> est mis pour <b>source port</b>, le port d'entrée) du port <b>www</b> (le web quoi !). Puis on a mis <b>-m state --state ESTABLISHED,RELATED</b> pour préciser que cette règle ne s'applique qu'aux paquets IP qui proviennent soit d'une liaison "établie" (<b>ESTABLISHED</b>), soit d'une liaison en relation (<b>RELATED</b>) avec une liaison déjà établie. Enfin on précise <b>-j ACCEPT</b> pour dire qu'on accepte tous les paquets qui vérifient toutes ces conditions : les paquets venant d'une liaison WEB déja établie. | ||
La seconde règle est symétrique de la première : elle autorise la paquets IP à sortir (< | La seconde règle est symétrique de la première : elle autorise la paquets IP à sortir (<b>-A OUTPUT</b>), sauf qu'elle précise en plus que les paquets sortants ont le droit d'initier une nouvelle connexion (<b>--state NEW</b>). Sinon la premiére règle aurait trés peu de chance de fonctionner : aucune liaison ne serait jamais 'établie'. | ||
Pour autoriser plusieurs ports en même temps, on peut soit taper plusieurs règles comme la précédente (une par port) ou alors utiliser la syntaxe (exemple pour le http et le https): | Pour autoriser plusieurs ports en même temps, on peut soit taper plusieurs règles comme la précédente (une par port) ou alors utiliser la syntaxe (exemple pour le http et le https): | ||
Ligne 84 : | Ligne 84 : | ||
=== Cas général : internet vers réseau local === | === Cas général : internet vers réseau local === | ||
Pour autoriser les machines d'internet à se connecter à votre serveur local (dans l'exemple j'autorise la connexion à votre serveur WEB : < | Pour autoriser les machines d'internet à se connecter à votre serveur local (dans l'exemple j'autorise la connexion à votre serveur WEB : <b>www</b>): | ||
<div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport <span style="font-weight:bold">www</span> -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --dport <span style="font-weight:bold">www</span> -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT </div><div class="note">Si vous voulez autoriser une connexion d'internet vers l'un des serveurs de votre réseau local à la place du serveur qui joue le rôle de mur pare feu, alors il faut faire du < | <div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport <span style="font-weight:bold">www</span> -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --dport <span style="font-weight:bold">www</span> -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT </div><div class="note">Si vous voulez autoriser une connexion d'internet vers l'un des serveurs de votre réseau local à la place du serveur qui joue le rôle de mur pare feu, alors il faut faire du <b>port forwarding</b> en utilisant les cibles <b>SNAT</b> et <b>DNAT</b> en plus d'<b>ACCEPT</b>, mais cela dépasse le cadre de cet article.</div> | ||
=== Cas particuliers === | === Cas particuliers === | ||
Il existe des cas particuliers, ce sont les protocoles qui ouvrent plusieurs liaisons en même temps : le DCC(pour irc), le ftp passif, les protocole vidéo (comme le h323). Ils fonctionnent souvent (mais pas tous) sur le principe suivant : le client (vous) réclame quelque chose (un fichier) au serveur (le serveur ftp) ; celui-ci répond à la demande en ouvrant une nouvelle connexion (aléatoire en général : c'est ce qui nous pose problème, on ne sait pas quel port ouvrir) réseau sur le client (vous). Pour ne pas ouvrir n'importe quel port (plus précisément, pour ne pas ouvrir TOUS les ports) pour être en mesure de répondre à la demande du serveur, il faut que nous soyons capable de "tracer" (to track en anglais) la provenance de la demande de connexion pour être sur que la demande de connexion provient d'une liaison que nous avons nous méme initié. C'est le rôle du module "< | Il existe des cas particuliers, ce sont les protocoles qui ouvrent plusieurs liaisons en même temps : le DCC(pour irc), le ftp passif, les protocole vidéo (comme le h323). Ils fonctionnent souvent (mais pas tous) sur le principe suivant : le client (vous) réclame quelque chose (un fichier) au serveur (le serveur ftp) ; celui-ci répond à la demande en ouvrant une nouvelle connexion (aléatoire en général : c'est ce qui nous pose problème, on ne sait pas quel port ouvrir) réseau sur le client (vous). Pour ne pas ouvrir n'importe quel port (plus précisément, pour ne pas ouvrir TOUS les ports) pour être en mesure de répondre à la demande du serveur, il faut que nous soyons capable de "tracer" (to track en anglais) la provenance de la demande de connexion pour être sur que la demande de connexion provient d'une liaison que nous avons nous méme initié. C'est le rôle du module "<b>ip_conntrack</b>" et de ses acolytes : "<b>ip_conntrack_ftp</b>" (pour le ftp) et "<b>ip_conntrack_irc</b>" pour l'irc. Pour que cela (ce qui va suivre) fonctionne, il faut donc que ces modules soient chargés. C'est ce que nous faisons au début du script, donc plus besoin de nous en occuper, si ce n'est pour autoriser les connexions qui sont en relation avec celles déja établies sur les ports qui sont utilisés par irc et ftp : | ||
<div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT </div> | <div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT<br /> $IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT </div> | ||
Ligne 110 : | Ligne 110 : | ||
<div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -p icmp -m state --state RELATED,ESTABLISHED -j ACCEPT<br /> $IPTABLES -A INPUT -p icmp -m state --state NEW -m limit --limit 10/min -j ACCEPT </div> | <div class="code"><nowiki># (suite du script...)</nowiki><br /> $IPTABLES -A INPUT -p icmp -m state --state RELATED,ESTABLISHED -j ACCEPT<br /> $IPTABLES -A INPUT -p icmp -m state --state NEW -m limit --limit 10/min -j ACCEPT </div> | ||
Vous pouvez remplacer < | Vous pouvez remplacer <b>10/min</b> par <b>1/s</b> etc... | ||
=== Envoyer une requête entrante vers un autre PC === | === Envoyer une requête entrante vers un autre PC === | ||
Ligne 126 : | Ligne 126 : | ||
=== Quels ports autoriser ? === | === Quels ports autoriser ? === | ||
Il est un port que vous êtes obligé d'autoriser dans le sens 'réseau local' vers 'internet' : le port "< | Il est un port que vous êtes obligé d'autoriser dans le sens 'réseau local' vers 'internet' : le port "<b>domain</b>" (aka: 53) en <b>udp</b> ET <b>tcp</b>. Sinon vous serez dans l'impossibilité d'utiliser la résolution de nom (aka: l'identification d'un nom de domaine avec son IP). | ||
Sinon, moi j'autorise, dans le sens [murdefeu.php3#murdefeu_casgfrom 'reseau local' vers 'internet'] en < | Sinon, moi j'autorise, dans le sens [murdefeu.php3#murdefeu_casgfrom 'reseau local' vers 'internet'] en <b>tcp</b> : | ||
* domain (obligatoire), | * domain (obligatoire), | ||
Ligne 147 : | Ligne 147 : | ||
* 1441 (flux ogg de radio france) | * 1441 (flux ogg de radio france) | ||
Et en < | Et en <b>udp</b> : | ||
* domain (obligatoire), | * domain (obligatoire), | ||
* 6970 et 7170 (realaudio) | * 6970 et 7170 (realaudio) | ||
Et dans le sens : [murdefeu.php3#murdefeu_casgto 'internet' vers 'reseau local'] en < | Et dans le sens : [murdefeu.php3#murdefeu_casgto 'internet' vers 'reseau local'] en <b>tcp</b> : | ||
* auth (accélère l'établissement de la connexion à plein de serveurs irc) | * auth (accélère l'établissement de la connexion à plein de serveurs irc) | ||
<div class="note"> Rappel : tous ces noms de 'ports' se trouvent dans le fichier < | <div class="note"> Rappel : tous ces noms de 'ports' se trouvent dans le fichier <b>/etc/services</b> </div> | ||
== Fin de script == | == Fin de script == | ||
Pour finir, on loggue tout via < | Pour finir, on loggue tout via <b>syslogd</b> : | ||
<div class="code"> $IPTABLES -A FORWARD -j LOG_DROP<br /> $IPTABLES -A INPUT -j LOG_DROP<br /> $IPTABLES -A OUTPUT -j LOG_DROP</div> | <div class="code"> $IPTABLES -A FORWARD -j LOG_DROP<br /> $IPTABLES -A INPUT -j LOG_DROP<br /> $IPTABLES -A OUTPUT -j LOG_DROP</div> | ||
Ligne 173 : | Ligne 173 : | ||
Ce mur pare feu n'est certainement pas parfait, mais j'espere qu'il vous permettra de mieux comprendre comment sont fabriqués les murs de feu que vous trouvez dans des scripts tous faits. | Ce mur pare feu n'est certainement pas parfait, mais j'espere qu'il vous permettra de mieux comprendre comment sont fabriqués les murs de feu que vous trouvez dans des scripts tous faits. | ||
<br/> | |||
<br/> | |||
'''<b>[[Sécurité et vie privée|@ Retour à la rubrique Sécurité et vie privée]]</b>''' | |||
<br/> | |||
<div class="merci">Cette page est issue de la documentation 'pré-wiki' de Léa a été convertie avec HTML::WikiConverter. Elle fut créée par Frédéric Bonnaud le 25/03/2003.</div> | <div class="merci">Cette page est issue de la documentation 'pré-wiki' de Léa a été convertie avec HTML::WikiConverter. Elle fut créée par Frédéric Bonnaud le 25/03/2003.</div> | ||
= Copyright = | |||
Copyright © 25/03/2003, Frédéric Bonnaud | |||
{{CC-BY-SA}} | |||
[[Category:Sécurité et vie privée]] |
Dernière version du 19 décembre 2023 à 23:30
Mur pare feu pas à pas
par Fred
Ce document explique comment constuire un mur pare feu, pas à pas, sans théorie, sans blabla.
Introduction
Il n'est pas question d'expliquer ici le fonctionnement d'iptables, il existe pour cela de très bons articles dont celui de Léa. Le mur pare feu que je vous propose de construire sera adapté à vos besoins. Il ne comportera aucun gadget, aucune optimisation du réseau. Ce sera un mur pare feu rien qu'un mur pare feu.
On commence
Vous devrez mettre dans le fichier /usr/bin/startfirewall tout ce qui va suivre.
Comme tout script, le script de notre mur pare feu doit commencer par :
Mais, pour être facilement modifiable, nous allons définir en plus quelques variables :
# mettez ici l'emplacement d'iptables :
IPTABLES=/sbin/iptables
# mettez ici le nom de l'interface réseau vers internet :
EXTERNAL_IF="ppp0"
# mettez ici le nom de l'interface réseau vers votre lan :
INTERNAL_IF="eth0"
Ensuite, il nous faut charger les modules dont nous aurons besoin :
# si vous voulez pouvoir autoriser les connexions ftp :
modprobe ip_conntrack_ftp
# si vous voulez pouvoir autoriser le DCC sous IRC :
modprobe ip_conntrack_irc
Suivant votre configuration, il peut être nécessaire de charger un autre module, pour en avoir la liste :
Politique par défaut
Un mur pare feu correctement configuré se doit de rejeter tout ce qui n'a pas été explicitement autorisé. C'est le rôle de la politique par défaut (default policy). Pour fixer celle-ci, nous utilisons les 3 règles suivantes :
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
La dernière règle peut être omise si vous souhaitez tout transmettre [aux]/[depuis les] machines de votre réseau local.
Les règles locales
Pour ne pas être ennuyé, il faut tout autoriser pour ce qui est du traffic réseau local (sur 'lo' et '$INTERNAL_IF' aka: 'eth0') :
# "On accepte le traffic sur 'lo'"
$IPTABLES -A INPUT -i lo -j ACCEPT
$IPTABLES -A OUTPUT -o lo -j ACCEPT
$IPTABLES -A FORWARD -i lo -j ACCEPT
$IPTABLES -A FORWARD -o lo -j ACCEPT
# "On accepte le traffic sur le réseau local"
$IPTABLES -A INPUT -i $INTERNAL_IF -j ACCEPT
$IPTABLES -A OUTPUT -o $INTERNAL_IF -j ACCEPT
$IPTABLES -A FORWARD -i $INTERNAL_IF -j ACCEPT
$IPTABLES -A FORWARD -o $INTERNAL_IF -j ACCEPT
Suivre son mur pare feu
Ceci n'est pas vraiment obligatoire.
Si vous ne regardez pas régulièrement les logs de votre mur pare feu, celui-ci a toutes les chances de devenir inefficace. Nous allons donc 'logguer' une partie des connexions que nous refuserons :
# On loggue les packets DROPés
$IPTABLES -N LOG_DROP
$IPTABLES -A LOG_DROP -j LOG --log-prefix "[IPT] "
$IPTABLES -A LOG_DROP -j DROP
Le texte [IPT] peut être remplacé par n'importe quel texte de votre choix. Vous pouvez, de la même façon, créer plusieurs cibles 'DROP' pour les logguer différemment.
Partager la connexion
Le mur pare feu peut aussi servir à partager la connexion, pour cela il faut faire deux choses :
- l'autoriser au niveau du noyau : # (suite du script...)
echo 1 > /proc/sys/net/ipv4/ip_forward - cacher les autres machines du réseau local derriére le mur pare feu : # (suite du script...)
$IPTABLES -A POSTROUTING -t nat -o $EXTERNAL_IF -j MASQUERADE
Autoriser des connexions
A partir de maintenant je vais vous donner des recettes de cuisine.
Tout d'abord, il faut savoir que vous pouvez au choix utiliser un numéro de port ou son nom dans le fichier [file://etc/services /etc/services]. J'utiliserais, dans la mesure du possible, cette dernière solution. Je ne détaillerais pas tous les ports, si vous souhaitez utiliser un port que j'aurais omis, consultez /etc/services. Dans ce fichier, vous constaterez que certains ports sont indiqués comme utilisant le protocol tcp, udp ou autre. Pour autoriser ces protocols vous devrez changer le "-p tcp" par "-p udp" ou autre dans les exemples qui vont suivre.
Cas général : réseau local vers internet
Pour la plupart des connexions, tout ce que je vais dire ici s'applique (exceptions notables : l'irc/dcc, le ftp/actif).
Pour autoriser les machines de votre réseau local (si le masquerading est activé) ainsi que votre serveur mur pare feu à se connecter à un port sur internet, il faut procéder de la maniére suivante (dans l'exemple j'autorise la connexion au WEB : www):
$IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport www -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --dport www -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Une petite explication, la règle $IPTABLES -A INPUT s'applique au traffic entrant (tous les paquets IP entrant seront soumis à cette règle). Comme on a précisé -p tcp, la règle s'applique aux paquets utilisants le protocol tcp. On a aussi préciser --sport www, donc la règle s'applique au paquet qui proviennent (sport est mis pour source port, le port d'entrée) du port www (le web quoi !). Puis on a mis -m state --state ESTABLISHED,RELATED pour préciser que cette règle ne s'applique qu'aux paquets IP qui proviennent soit d'une liaison "établie" (ESTABLISHED), soit d'une liaison en relation (RELATED) avec une liaison déjà établie. Enfin on précise -j ACCEPT pour dire qu'on accepte tous les paquets qui vérifient toutes ces conditions : les paquets venant d'une liaison WEB déja établie.
La seconde règle est symétrique de la première : elle autorise la paquets IP à sortir (-A OUTPUT), sauf qu'elle précise en plus que les paquets sortants ont le droit d'initier une nouvelle connexion (--state NEW). Sinon la premiére règle aurait trés peu de chance de fonctionner : aucune liaison ne serait jamais 'établie'.
Pour autoriser plusieurs ports en même temps, on peut soit taper plusieurs règles comme la précédente (une par port) ou alors utiliser la syntaxe (exemple pour le http et le https):
$IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp -m multiport --sports www,https -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp -m multiport --dports www,https -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Cas général : internet vers réseau local
Pour autoriser les machines d'internet à se connecter à votre serveur local (dans l'exemple j'autorise la connexion à votre serveur WEB : www):
$IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport www -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --dport www -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Cas particuliers
Il existe des cas particuliers, ce sont les protocoles qui ouvrent plusieurs liaisons en même temps : le DCC(pour irc), le ftp passif, les protocole vidéo (comme le h323). Ils fonctionnent souvent (mais pas tous) sur le principe suivant : le client (vous) réclame quelque chose (un fichier) au serveur (le serveur ftp) ; celui-ci répond à la demande en ouvrant une nouvelle connexion (aléatoire en général : c'est ce qui nous pose problème, on ne sait pas quel port ouvrir) réseau sur le client (vous). Pour ne pas ouvrir n'importe quel port (plus précisément, pour ne pas ouvrir TOUS les ports) pour être en mesure de répondre à la demande du serveur, il faut que nous soyons capable de "tracer" (to track en anglais) la provenance de la demande de connexion pour être sur que la demande de connexion provient d'une liaison que nous avons nous méme initié. C'est le rôle du module "ip_conntrack" et de ses acolytes : "ip_conntrack_ftp" (pour le ftp) et "ip_conntrack_irc" pour l'irc. Pour que cela (ce qui va suivre) fonctionne, il faut donc que ces modules soient chargés. C'est ce que nous faisons au début du script, donc plus besoin de nous en occuper, si ce n'est pour autoriser les connexions qui sont en relation avec celles déja établies sur les ports qui sont utilisés par irc et ftp :
$IPTABLES -A INPUT -i $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT
Voilà, c'est tout, le ftp passif doit maintenant pouvoir bien passer votre mur pare feu.
Par contre pour le DCC, il faut encore ajouter une règle, autoriser les liaisons sortantes à initier une connexion. Je ne vois pas pourquoi, mais chez moi c'est nécessaire ;-) :
$IPTABLES -A OUTPUT -o $EXTERNAL_IF -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state NEW -j ACCEPT
Le ping !
Pour l'instant, si vous avez ouvert quelques port, vous avez du remarquer que vous n'avez plus accès au ping. Nous allons remédier à cela :
$IPTABLES -A OUTPUT -p icmp -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT -p icmp -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
ou alors, vous pouvez vouloir limiter les ping entrant (pour éviter d'être floodé) et vous remplacez la seconde règle par les deux suivantes :
$IPTABLES -A INPUT -p icmp -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -A INPUT -p icmp -m state --state NEW -m limit --limit 10/min -j ACCEPT
Vous pouvez remplacer 10/min par 1/s etc...
Envoyer une requête entrante vers un autre PC
Cette pratique s'appelle le 'port forwarding'.
Vous aurez besoin du port forwarding si vous avez un serveur qui ne fonctionne pas sur le poste qui partage la connexion. Par exemple, si le poste qui a un serveur http a pour IP 192.168.0.3, on utilisera cette commande pour que les requetes reçues lui soient automatiquement transmises :
Cela vous sera aussi utile si vous voulez héberger un serveur de jeu (crack-attack, freeciv, etc) sur une autre machine que le mur de feu qui peut, de la sorte, rester une machine de faibles capacités.
Si ça ne vous suffit pas réalisation d'une zone démilitarisée (DMZ) sera sans doute nécessaire (mais cela sort du cadre de cet article).
Quels ports autoriser ?
Il est un port que vous êtes obligé d'autoriser dans le sens 'réseau local' vers 'internet' : le port "domain" (aka: 53) en udp ET tcp. Sinon vous serez dans l'impossibilité d'utiliser la résolution de nom (aka: l'identification d'un nom de domaine avec son IP).
Sinon, moi j'autorise, dans le sens [murdefeu.php3#murdefeu_casgfrom 'reseau local' vers 'internet'] en tcp :
- domain (obligatoire),
- ftp,
- ftp-data,
- www,
- https,
- pop-3,
- imap2,
- imap3,
- smtp,
- ircd,
- cvspserver,
- rsync,
- 7070 (realaudio),
- 11371 (keyserver),
- ssh,
- 1441 (flux ogg de radio france)
Et en udp :
- domain (obligatoire),
- 6970 et 7170 (realaudio)
Et dans le sens : [murdefeu.php3#murdefeu_casgto 'internet' vers 'reseau local'] en tcp :
- auth (accélère l'établissement de la connexion à plein de serveurs irc)
Fin de script
Pour finir, on loggue tout via syslogd :
$IPTABLES -A INPUT -j LOG_DROP
$IPTABLES -A OUTPUT -j LOG_DROP
Arrêter le mur pare feu
Il n'est en général pas nécessaire d'arrêter le mur pare feu, mais, sait-on jamais ? Pour faire les tests, il est nécessaire de l'arrêter et de le redémarrer (parce que l'ordre des règles est important). Voici un petit script pour arrêter le mur pare feu (celui qui est proposé ici, il ne fonctionnera pas avec tous les murs de feu) :
# Script d'arrêt du mur pare feu
# mettez ici l'emplacement d'iptables :
IPTABLES=/sbin/iptables
echo "On vide toutes les régles."
$IPTABLES -F INPUT
$IPTABLES -F OUTPUT
$IPTABLES -F FORWARD
$IPTABLES -t nat -F POSTROUTING
$IPTABLES -F LOG_DROP
$IPTABLES -X
$IPTABLES -P INPUT ACCEPT
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -P FORWARD ACCEPT
echo "On décharge les modules."
rmmod `lsmod | grep -E "^ip" | cut -d" " -f 1`
Conclusion
Ce mur pare feu n'est certainement pas parfait, mais j'espere qu'il vous permettra de mieux comprendre comment sont fabriqués les murs de feu que vous trouvez dans des scripts tous faits.
@ Retour à la rubrique Sécurité et vie privée
Copyright
Copyright © 25/03/2003, Frédéric Bonnaud
Ce document est publié sous licence Creative Commons Attribution, Partage à l'identique 4.0 : https://creativecommons.org/licenses/by-sa/4.0/ |