[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [firewall] iptables, le script parfait?



Salut,

Gaëtan PERRIER a écrit :

J'utilise le script en pièce jointe. Si vous pouviez donner votre avis dessus, ça m'intéresse...

$ grep -c -- -N iptables-final-1-adsl.sh
0

Ça commence mal. Un jeu de règles sans chaînes utilisateur ne peut pas être un bon jeu de règles. ;-)

# Paramètrage du réseau local (LAN = Local Area Network)
LAN_INTERFACE=lan             ; # Interface réseau interne
LAN_IP=192.168.10.1           ; # Adresse réseau interne
LAN_NETWORK=192.168.10.0/24   ; # Réseau interne
LAN_BROADCAST=192.168.10.255  ; # Adresse de broadcast interne

# Paramètrage de la connexion Internet (WAN = Wild Area Network = Réseau Large)
WAN_INTERFACE=adsl            ; # Interface réseau externe (Internet)
if [ -z "$@" ]; then
	WAN_IP=`/sbin/ifconfig $WAN_INTERFACE | grep "inet adr" | sed "s/^[: a-z]*\([.0-9]*\).*/\1/g"`  ; # Récupère l'adresse réseau externe (Internet)
elif [ "$@" == "boot" ]; then
	WAN_IP=$new_ip_address
fi

Où la variable $new_ip_address est-elle définie ? Que contient-elle ?

[...]
###############################################################################
# Règles de conexion au reseau local

"connexion".

# Tout est autorisé
###############################################################################

echo "+ Règles du réseau local ($LAN_INTERFACE - $LAN_IP - $LAN_NETWORK)"
# Connexions firewall <-> réseau
iptables -t filter -A OUTPUT -o $LAN_INTERFACE -s $LAN_IP -d $LAN_NETWORK -p all -j ACCEPT
iptables -t filter -A INPUT  -i $LAN_INTERFACE -s $LAN_NETWORK -d $LAN_IP -p all -j ACCEPT

Ces règles oublient de prendre en compte les paquets émis (resp. reçus) sur $LAN_INTERFACE avec l'adresse source (resp. destination) $WAN_IP, qui sont pourtant parfaitement légitimes. Ne pas oublier qu'une adresse IP appartient à une machine au moins autant qu'à une interface.

# Connexions firewall <-> broadcast réseau
iptables -t filter -A OUTPUT -o $LAN_INTERFACE -s $LAN_IP -d $LAN_BROADCAST -p all -j ACCEPT

Cette règle est redondante puisque l'adresse de broadcast dirigé $LAN_BROADCAST est incluse dans le sous-réseau $LAN_NETWORK. Par contre l'adresse de broadcast limité 255.255.255.255 n'est pas prise en compte.

iptables -t filter -A INPUT  -i $LAN_INTERFACE -s $LAN_BROADCAST -d $LAN_IP -p all -j ACCEPT

Surtout pas ! L'adresse source ne peut être une adresse de broadcast. Les réponses à un broadcast IP se font avec une adresse source d'hôte (unicast).

###############################################################################
# Règles de connexion à Internet
# Seul les connexions initialisés par la machine sont autorisées
# C'est le suivit de connexion
###############################################################################

"suivi", sans "t".

# Chargement des modules pour le suivit de connexion
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ip_conntrack_irc

echo "+ Règles pour Internet ($WAN_INTERFACE - $WAN_IP - $WAN_NETWORK)"
iptables -t filter -A OUTPUT -o $WAN_INTERFACE -s $WAN_IP -d $WAN_NETWORK -p all -m state --state ! INVALID           -j ACCEPT
iptables -t filter -A INPUT  -i $WAN_INTERFACE -s $WAN_NETWORK -d $WAN_IP -p tcp --tcp-flags ! ALL SYN -m state --state NEW,RELATED -j DROP #06/05/2006
iptables -t filter -A INPUT  -i $WAN_INTERFACE -s $WAN_NETWORK -d $WAN_IP -p all -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A INPUT  -i $WAN_INTERFACE -s $WAN_NETWORK -d $WAN_IP -p tcp --destination-port auth -j REJECT --reject-with tcp-reset #06/05/2006

La dernière règle ne serait pas nécessaire si toutes les connexions indésirables étaient traitées par REJECT au lieu de DROP.

###############################################################################
# Règles pour le port forwarding
# Pour que le port forwarding soit activé, il faut la variable "$PF" soit à "1"
###############################################################################

if [ "$PF" == "1" ]; then
  # Chargement des modules pour le port forwarding
  modprobe iptable_nat

  echo "+ Autorise le port forwardong de $WAN_IP:$PF_PORT -> $PF_IP:$PF_PORT"
  iptables -t filter -A FORWARD -i $WAN_INTERFACE -o $LAN_INTERFACE -s $WAN_NETWORK -d $LAN_NETWORK -p $PF_PROTO --dport $PF_PORT -m state --state ! INVALID           -j ACCEPT
  iptables -t filter -A FORWARD -i $LAN_INTERFACE -o $WAN_INTERFACE -s $LAN_NETWORK -d $WAN_NETWORK -p $PF_PROTO --sport $PF_PORT -m state --state ESTABLISHED,RELATED -j ACCEPT

Il serait plus sûr de limiter l'adresse de destination à $PF_IP au lieu de $LAN_NETWORK.

  iptables -t nat    -A PREROUTING                -i $WAN_INTERFACE -s $WAN_NETWORK -d $WAN_IP      -p $PF_PROTO --dport $PF_PORT -j DNAT --to-destination $PF_IP
  iptables -t nat    -A POSTROUTING               -o $LAN_INTERFACE -s $WAN_NETWORK -d $PF_IP       -p $PF_PROTO --dport $PF_PORT -j SNAT --to-source $LAN_IP

Quel est l'intérêt de cette règle SNAT dans nat/POSTROUTING ? Masquer l'adresse source réelle de la connexion à la machine vers laquelle le port est redirigé me paraît plutôt contre-productif.

  echo 1 > /proc/sys/net/ipv4/ip_forward

else
  echo "+ Le port forwarding N'est PAS autorisé"
  if [ "$NAT" == "0" ]; then
    echo 0 > /proc/sys/net/ipv4/ip_forward
  fi
fi

Le test de la valeur de $NAT ne sert à rien puisque de toute façon ip_forward est déjà à 0. Voir mon commentaire sur l'IP masquerading.

###############################################################################
# Règles pour l'IP masquerading
# Pour que le IP masquerading soit activé, il faut la variable "$NAT" soit à "1"
###############################################################################

if [ "$NAT" == "1" ]; then
  # Chargement des modules pour l'IP masquerading
  modprobe iptable_nat
  modprobe ip_nat_ftp
  modprobe ip_nat_irc

  echo "+ Autorise l'IP masquerading de $LAN_NETWORK -> $WAN_NETWORK"
  iptables -t filter -A FORWARD -i $LAN_INTERFACE -o $WAN_INTERFACE -s $LAN_NETWORK -d $WAN_NETWORK -p all -m state --state ! INVALID           -j ACCEPT

Si on veut être puriste, "! INVALID" n'est pas approprié ici. En effet cela équivaut à NEW,RELATED,ESTABLISHED,UNTRACKED. Or les paquets dans l'état UNTRACKED, comme ceux dans l'état INVALID, sont ignorés par les chaînes de la table 'nat'. Par conséquent un tel paquet serait retransmis sur l'interface WAN avec son adresse source privée originale, ce qui n'est pas souhaitable. Certes en l'absence de règles NOTRACK, aucun paquet ne peut se retrouver dans l'état UNTRACKED.

  iptables -t filter -A FORWARD -i $WAN_INTERFACE -o $LAN_INTERFACE -s $WAN_NETWORK -d $LAN_NETWORK -p all -m state --state ESTABLISHED,RELATED -j ACCEPT

  iptables -t nat    -A POSTROUTING               -o $WAN_INTERFACE -s $LAN_NETWORK -d $WAN_NETWORK -p all -j MASQUERADE

  echo 1 > /proc/sys/net/ipv4/ip_forward

else
  echo "+ L'IP masquerading N'est PAS autorisé"
  echo 0 > /proc/sys/net/ipv4/ip_forward
fi

Je crois qu'ici il y a un bug : si l'ip_forward avait était activé pour le port forwarding ($PF=1), $NAT=0 le désactive ! Ne serait-il pas plus simple de l'activer à un seul endroit si ($NAT=1 ou $PF=1) ?

[...]
###############################################################################
# Règles pour MSN
###############################################################################

Ces règles sont pour un client MSN Messenger ou un serveur hébergé sur la machine ?

if [ "$MSN" == "1" ]; then
echo "+ Règles pour MSN"
iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p tcp --dport $MSN_TCP_PORT -m state --state ! INVALID           -j ACCEPT

Cette règle est inutile pour un client MSN Messenger car il émet une connexion sortante vers le port destination 1863.

iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p tcp --sport $MSN_TCP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT

Je soupçonne un oubli de modification de -d en -s après un copier/coller.
Même sans cette erreur, cette règle est redondante car une règle précédente autorise déjà tout le trafic sortant non INVALID. D'autre part, un paquet de réponse TCP ou UDP (--sport) ne peut pas avoir l'état RELATED. Seul le premier paquet d'une connexion liée peut avoir cet état. Ces remarques sont aussi valables pour les autres règles OUTPUT et pour les autres applications. J'ai pris le cas de MSN Messenger parce que je le connais plus que les autres.

iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p udp --dport $MSN_UDP_PORT -m state --state ! INVALID           -j ACCEPT
iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p udp --sport $MSN_UDP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT

Je ne crois pas que le port 1863 soit utilisé en UDP.

iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p tcp --dport $MSN_TRANSFERT_TCP_PORT -m state --state ! INVALID           -j ACCEPT
iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p tcp --sport $MSN_TRANSFERT_TCP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p udp --dport $MSN_TRANSFERT_UDP_PORT -m state --state ! INVALID           -j ACCEPT
iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p udp --sport $MSN_TRANSFERT_UDP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT

Je ne crois pas que le transfert de fichier utilise UDP.

iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p tcp --dport $MSN_VOIX_TCP_PORT -m state --state ! INVALID           -j ACCEPT
iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p tcp --sport $MSN_VOIX_TCP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT  -i $WAN_INTERFACE -d $WAN_IP -p udp --dport $MSN_VOIX_UDP_PORT -m state --state ! INVALID           -j ACCEPT
iptables -A OUTPUT -o $WAN_INTERFACE -d $WAN_IP -p udp --sport $MSN_VOIX_UDP_PORT -m state --state RELATED,ESTABLISHED -j ACCEPT
fi

Je voudrais faire une remarque générale au sujet des nombreuses règles acceptant des paquets dans l'état RELATED ou ESTABLISHED. Si le suivi de connexion a classé un paquet dans un de ces états, c'est que le trafic précédent auquel il est lié a déjà été vu et accepté (à l'exception des paquets RST ou ICMP émis localement en réponse à un paquet rejeté). Par conséquent il n'est pas utile de recréer ces règles pour chaque interface, application, protocole, port... On peut se contenter d'une unique règle acceptant tous les paquets dans l'état RELATED ou ESTABLISHED en début de chaîne (pour l'efficacité, l'immense majorité des paquets étant dans l'état ESTABLISHED) suivie de règles traitant les paquets dans l'état NEW au cas par cas. Ça allège et simplifie sensiblement le jeu de règles sans sacrifier à la sécurité. Beaucoup de jeux de règles sont construits ainsi.

[...]
###############################################################################
# Règles pour le log
###############################################################################

Il n'y a rien de prévu pour le log des paquets dans FORWARD ?



Reply to: