Exemple d'automatisation d'un pare feu via un service pour Linux Debian
Par ericd69

Le , par ericd69, Membre expert
Exemple d'automatisation d'un pare-feu
via un service
pour Linux Debian



Résumé

La mise en place d'un pare-feu est un point clé incontournable de la configuration d'un serveur en ligne qu'il soit virtuel ou réel. Ici je vais donc aborder la mise en place sous forme d'un service pour en faciliter l'utilisation. Je parlerais plus particulièrement du cas de serveurs chez OVH pour la partie monitoring externe.

Prérequis

Les utilitaires suivants sont nécessaires :
  • ifconfig, utilitaire pour la configuration réseau (matériel et logiciels) ;
  • cat, utilitaire de lecture de fichier texte ;
  • grep, utilitaire de recherche d'expressions dans des fichiers ou pipe ;
  • awk, utilitaire de recherche et modification de texte dans des fichiers ou pipe ;
  • iptables, utilitaire de filtrage réseau ;
  • ssh, utilitaire d'administration et de communication.


Notions utilisées

Les notions suivantes seront préférables pour mieux comprendre ce qui est fait :
  • comprendre diverses notions sur les réseaux (protocoles, NAT, IP, DNS, ports, etc.) ;
  • comprendre la notion de pipelines et de redirection des sorties sous Linux ;
  • comprendre la gestion de droit sous Linux ;
  • comprendre les chaînes de caractères heredocs ;
  • comprendre l'écriture de script exécutable dans une console sous Linux ;
  • comprendre la notion de services sous Debian.


Nota

Il y a moult façons de faire des recherches, extractions ou remplacement de texte dans les différentes distributions de Linux et même au sein d'une seule... Celles que je présente ci-dessous ne sont pas forcément les plus optimisées, mais vu que pour leur utilisation dans ce cadre, la vitesse est moins importante que la maintenabilité et la compréhension, j'ai préféré enchaîner des utilitaires que parfois tout faire avec un seul avec une expression plus pénible à trouver ou comprendre...



1. Les services sous Debian

1.1. Un service c'est quoi ?
Un service (ou démon) est un programme qui est lancé de manière automatique au démarrage du système et s'arrête en même temps que l'arrêt de celui-ci. Il sert à gérer des actions en tâche de fond et peut agir seul, comme NTP, le service de recalage de l'heure, ou attendre des actions à traiter comme le service iptables qui traitera toutes les interactions réseau.
Un service est souvent composé de deux parties :
  • un script qui va servir à interagir avec le service ;
  • un exécutable persistant qui réalise les actions correspondant au service.

Le fait de placer un script dans /ect/init.d ne l'active pas.
Pour inscrire en tant que service un script nom_script dans ce répertoire, il faut utiliser :
Code bash : Sélectionner tout
update-rc.d nom_script defaults
Pour le désinscrire :
Code bash : Sélectionner tout
update-rc.d -f nom_script remove
À partir de la version Jessie de Debian, le script d'interaction doit répondre aux principes de LSB (Linux Standard Base) qui l'obligent à :
  • permettre au moins les actions suivantes : start, stop, restart, force-reload et status ;
  • retourner un code de fin d'exécution cohérent (0 ras sinon un problème s'est produit) ;
  • contenir un bloc d'information (un bloc de commentaires spécialement formaté) donnant obligatoirement les dépendances de démarrage et d'arrêt du service.

Un warning est émis à chaque appel à update-rc.d si ces trois conditions ne sont pas remplies.

1.2. L'utilitaire iptables
C'est donc l'utilitaire qui permet de contrôler les flux réseau, il est une interface en ligne de commande à netfilter. Il permet de générer des filtres sur les paquets en agissant selon leur protocole (TCP, UDP ou ICMP) , leur source ou destination en termes de port et/ou d'URL ou d'IP, le nombre de connexions ou des règles de traduction d'adresse (NAT) par exemple. À chaque invocation de iptables avec une règle, celle-ci s'ajoute à la chaîne de règles qui seront testées dans l'ordre de leur ajout jusqu'à ce qu'une décision sur le flux soit prise (acceptation, rejet avec ou sans notification à l'émetteur). Des modules optionnels sont à installer voire à compiler selon les besoins. iptables tient son nom du fait que les règles sont organisées en tables. Une présentation succincte de iptables est faite ici.
On pourra lister les règles en place avec :
Code bash : Sélectionner tout
iptables -L
On notera qu'il existe un paquet Debian pour rendre persistantes les règles : iptables-persistent. Néanmoins il ne fait que sauvegarder ou restaurer les règles dans un fichier. C'est pour ça que je lui préfère le principe du programme que l'on transforme en service une fois la phase de test finie. En cas d'erreur, tant qu'on n’a pas testé les règles avec succès, un simple redémarrage du système suffit pour revenir à la configuration précédente.

2. Un service de pare-feu

2.1. Stratégie choisie
Dans le cas du pare-feu, il n'y aura que le script d'interaction. L'idée va être de faire un script de génération, dans le répertoire /root, pour le code du script d'interaction qui lui sera dans le répertoire /ect/init.d.

2.2. parefeu.sh
2.2.1. But
Le script sera placé dans le répertoire /root et pour le rendre exécutable, on utilisera :
Code bash : Sélectionner tout
chmod 700 /root/parefeu.sh
Le but de ce script va être de :
  • récupérer la valeur du port SSH ;
  • récupérer les 24 bits supérieurs de l'IP du serveur de monitoring d'OVH ;
  • créer le script du pare-feu.

2.2.2. Récupérer la valeur du port SSH
On va utiliser grep sur /etc/ssh/sshd_config pour récupérer la ligne du port utilisé par le service SSH et awk pour extraire le nombre qui est la 2e valeur de celle-ci.
Code bash : Sélectionner tout
ssh_port=$(cat /etc/ssh/sshd_config | grep Port | awk '{print $2;}')
On peut se passer de cat:
Code bash : Sélectionner tout
ssh_port=$(grep Port /etc/ssh/sshd_config | awk '{print $2;}')
Ou même tout faire avec awk:
Code bash : Sélectionner tout
ssh_port=$(awk '/Port/ {print $2;}' /etc/ssh/sshd_config)
2.2.3. Récupérer les 24 bits supérieurs de l'IP du serveur de monitoring d'OVH
L'utilitaire ifconfig permet de mettre en place ou de récupérer tout ou partie des configurations réseau. Nous avons besoin de l'IP externe du serveur, donc nous allons lire la partie concernant l'interface réseau eth0. On fait un grep pour extraire la ligne qui contient l'IP et enfin on ne garde que l'IP grâce à un appel à awk. On obtient le code suivant :
Code bash : Sélectionner tout
serveur_ip=$(ifconfig eth0 | grep Bcast | awk '{sub(/[a-zA-Z]+\:/,"",$2); print $2;}')
On peut se passer de grep là aussi:
Code bash : Sélectionner tout
serveur_ip=$(ifconfig eth0 | awk '/Bcast/ {sub(/[a-zA-Z]+\:/,"",$2); print $2;}')
Il peut être utile d'avoir l'IP complète pour certains cas ou réglages donc on extrait de celle-ci les codes des 3 premiers octets grâce à une commande awk:
Code bash : Sélectionner tout
serveur_24=$(echo $serveur_ip | awk -F "." '{print $1"."$2"."$3;}')
2.2.4. Désinscription du service du pare-feu si besoin
Pour éviter d'avoir des warnings à propos de la modification du code du service, on teste la présence du fichier dans le répertoire /ect/init.d et, si le fichier /ect/init.d/parefeu, on désinscrit le service parefeu. On utilise pour cela le code suivant :
Code bash : Sélectionner tout
1
2
3
4
5
6
7
if [ -f "/etc/init.d/$parefeu" ]; then 
    echo -e "Suppression du referencement du service du service" 
    update-rc.d -f $parefeu remove 
else 
    touch /etc/init.d/$parefeu 
    chmod 755 /etc/init.d/$parefeu 
fi
2.2.5. Créer le script du pare-feu
Pour ce faire, on utilise cat à qui on passe un here doc dont le délimiteur est la chaîne de caractères EOF, et on redirige sa sortie vers un fichier en faisant un remplacement complet du contenu. Comme le délimiteur n'a pas de quotes, simples ou doubles, autour de lui, tout ce qui suit un $ est interprété comme une variable et replacé par sa valeur. On obtient le code suivant:
Code bash : Sélectionner tout
1
2
3
cat <<- EOF > /etc/init.d/$parefeu 
#code ici 
EOF
2.2.6. Inscription du service du pare-feu
C'est l'action finale du script, elle est réalisée par :
Code bash : Sélectionner tout
update-rc.d $parefeu defaults
2.2.7. Code complet du script
Le code complet du script /root/parefeu.sh est:
Code bash : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/sh 
reset 
# Emplacement du service 
parefeu='parefeu' 
# Configuration du service 
echo -e "\033[7m INSTALLATION DU PAREFEU \033[0m" 
echo -e "Recuperation de l'IP du serveur sur eth0" 
serveur_ip=$(ifconfig eth0 | awk '/Bcast/ {sub(/[a-zA-Z]+\:/,"",$2); print $2;}') 
echo $serveur_ip 
echo -e "Recuperation de la portion d'IP du serveur pour le SLA" 
serveur_24=$(echo $serveur_ip | awk -F "." '{print $1"."$2"."$3;}') 
echo $serveur_24 
echo -e "Recuperation du port SSH" 
ssh_port=$(awk '/Port/ {print $2;}' /etc/ssh/sshd_config) 
echo $ssh_port 
if [ -f "/etc/init.d/$parefeu" ]; then 
    echo -e "Suppression du referencement du service du service" 
    update-rc.d -f $parefeu remove 
else 
    touch /etc/init.d/$parefeu 
    chmod 755/etc/init.d/$parefeu 
fi 
echo -e "Creation du code du service" 
cat <<- EOF > /etc/init.d/$parefeu 
#!/bin/sh 
### BEGIN INIT INFO 
# Provides:          parefeu 
# Required-Start:    $syslog $network 
# Required-Stop:     $syslog $network 
# Default-Start:     2 3 4 5 
# Default-Stop:      0 1 6 
# Short-Description: Start firewall daemon at boot time 
# Description:       Custom Firewall scrip. 
### END INIT INFO 
  
firewall_start() 
{ 
    # --- 
    # Vider les tables actuelles 
    iptables -t filter -F 
    # Vider les règles personnelles 
    iptables -t filter -X 
    # Interdire toute connexion entrante et sortante 
    iptables -t filter -P INPUT DROP 
    iptables -t filter -P FORWARD DROP 
    iptables -t filter -P OUTPUT DROP 
    # --- 
    # Ne pas casser les connexions etablies 
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
    iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
    # Autoriser loopback 
    iptables -t filter -A INPUT -i lo -j ACCEPT 
    iptables -t filter -A OUTPUT -o lo -j ACCEPT 
    # Differentes securites 
    echo 1 > /proc/sys/net/ipv4/tcp_syncookies 
    echo 0 > /proc/sys/net/ipv4/ip_forward 
    echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 
    echo 1 > /proc/sys/net/ipv4/conf/all/log_martians 
    echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 
    echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter 
    echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects 
    echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route 
    # --- 
    # Règle de rejet et log des tentatives de connexion en trop sur SSH 
    iptables -N SSH_DROP 
    iptables -A SSH_DROP -j LOG --log-prefix '[fw drop -> Attack ssh] : ' 
    iptables -A SSH_DROP -j DROP 
    # --- 
    # Autoriser le fonctionnement du DNS en UDP 
    iptables -t filter -A INPUT -i eth0 -p udp --dport 53 -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p udp --dport 53 -m state --state NEW -j ACCEPT 
    # --- 
    # Autoriser ICMP pour les serveur SLA OVH 
    iptables -t filter -A INPUT -i eth0 -p icmp -s 92.222.184.0/24,92.222.185.0/24,92.222.186.0/24,167.114.37.0/24 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s 37.187.231.251/32,151.80.118.100/32,151.80.231.244/32,151.80.231.245/32,151.80.231.246/32,151.80.231.247/32 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s 213.186.33.62/32,213.186.45.4/32,213.251.184.9/32,37.59.0.235/32,8.33.137.2/32,213.186.33.13/32,213.186.50.98/32 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s ${serveur_24}.250/32,${serveur_24}.251/32 -m state --state NEW -j ACCEPT 
    # Autoriser le monitring OVH 
    iptables -t filter -A OUTPUT -o eth0 -p udp -dport 6100:6200 -m state --state NEW -j ACCEPT 
    # --- 
    # Autoriser le ssh avec anti force brute 
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m recent --set --name SSH_BAD 
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m recent --update --seconds 60 --hitcount 4 --name SSH_BAD -j SSH_DROP 
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --dport ${ssh_port} -m state --state NEW -j ACCEPT 
    # --- 
    # Autoriser DNS, HTTP, HTTPS en TCP 
    iptables -t filter -A INPUT -i eth0 -p tcp -m multiport --dports 53,80,443 -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp -m multiport --dports 53,80,443 -m state --state NEW -j ACCEPT 
    # Autoriser le FTP sortant en TCP 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --dport 20:21 -j ACCEPT 
    modprobe ip_conntrack 
    modprobe ip_conntrack_ftp 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 20 -m state --state ESTABLISHED -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p tcp --sport 20 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p tcp -m multiport --sports 21,1024:65535 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT 
    # --- 
    # Autoriser le recalage d'horloge système 
    iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT 
} 
  
firewall_stop() 
{ 
    iptables -F 
    iptables -X 
    iptables -P INPUT ACCEPT 
    iptables -P FORWARD ACCEPT 
    iptables -P OUTPUT ACCEPT 
# 
#    iptables -t nat -F 
#    iptables -t nat -X 
#    iptables -t nat -P PREROUTING ACCEPT 
#    iptables -t nat -P POSTROUTING ACCEPT 
#    iptables -t nat -P OUTPUT ACCEPT 
# 
#    iptables -t mangle -F 
#    iptables -t mangle -X 
#    iptables -t mangle -P PREROUTING ACCEPT 
#    iptables -t mangle -P OUTPUT ACCEPT 
} 
  
# Corps du programme 
case $1 in 
    'force-reload') 
        echo -e "Demarrage du parefeu" 
        firewall_start 
        exit 0 
    ;; 
    'regles' ) 
        echo -e "Regles actuelles du parefeu" 
        iptables -L -v -n 
        exit 0 
    ;; 
    'restart') 
        echo -e "Redemarrage du parefeu" 
        firewall_start 
        exit 0 
    ;; 
    'start') 
        echo -e "Demarrage du parefeu" 
        firewall_start 
        exit 0 
    ;; 
    'status' ) 
        echo -e "Etat du chrgement du parefeu" 
        iptables -L -v -n 
        exit 0 
    ;; 
    'stop') 
        echo -e "Arret du parefeu" 
        firewall_stop 
        exit 0 
    ;; 
    *) 
        echo "usage: parefeu {regles|start|stop|restart|status}" 
        exit 1 
    ;; 
esac 
EOF 
echo -e "Activation du service" 
update-rc.d $parefeu defaults 
exit 0

2.3. Comment est écrit le service pare-feu
2.3.1. Utiliser des fonctions en bash
Pour faciliter la maintenance et permettre la réutilisation, on va placer le code des fonctionnalités du service dans des fonctions. Une fonction s'écrit de la sorte:
Code bash : Sélectionner tout
1
2
3
4
nom_fonction() 
{ 
#code du corps de la fonction 
}
L'invocation d'une fonction est vue comme un appel à un utilitaire ou un script, dans la fonction on utilise donc $1 pour désigner le premier paramètre, $2 le second, etc. On peut utiliser exit pour fixer un code d'erreur ou non lors de la sortie de celle-ci. Si on prend l'exemple d'une fonction de décompression générique:
Code bash : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
decompression () 
{ 
    if [ -f $1 ]; then 
        case $1 in 
            (*.7z) 7z x $1 ;; 
            (*.lzma) unlzma $1 ;; 
            (*.rar) unrar x $1 ;; 
            (*.tar) tar xvf $1 ;; 
            (*.tar.bz2) tar xvjf $1 ;; 
            (*.bz2) bunzip2 $1 ;; 
            (*.tar.gz) tar xvzf $1 ;; 
            (*.gz) gunzip $1 ;; 
            (*.tar.xz) tar Jxvf $1 ;; 
            (*.xz) xz -d $1 ;; 
            (*.tbz2) tar xvjf $1 ;; 
            (*.tgz) tar xvzf $1 ;; 
            (*.zip) unzip $1 ;; 
            (*.Z) uncompress ;; 
            (*) echo -e "'$1' est impossible à décompresser..." ;; 
        esac 
    else 
        echo -e "Erreur: '$1' n'est pas un fichier valide!" 
        exit 1 
    fi 
}
Dans le contexte où elle est définie, si on prend l'exemple de la fonction de décompression, on peut l'invoquer comme suit:
Code bash : Sélectionner tout
decompression fichier
2.3.2. Les fonctions du script du service
On va donc utiliser les fonctions suivantes dans le script:
  • firewall_start() qui sert à mettre en place les règles choisies.
  • firewall_stop() qui va supprimer tous les filtrages.

2.3.3. Le corps du script du service
Le premier paramètre est l'action que le service doit réaliser, un case va lui être appliqué pour déterminer sa valeur:
  • start, obligatoire, appelle firewall_start().
  • stop, obligatoire, appelle firewall_stop().
  • restart, obligatoire, appelle firewall_start().
  • force-reload, obligatoire, appelle firewall_start().
  • status, obligatoire, donne l'activité du service (indépendamment de ce qu'on met dedans) et son historique de chargement.
  • règles, particulières à ce service, liste les règles actives et la répartition de chacune d'elles de ce qu'elles ont traité comme octets et paquets.


3. Les règles du pare-feu utilisées dans cet exemple

3.1. Initialisation
3.1.1. Non crypté
On commence par supprimer toutes les règles:
Code bash : Sélectionner tout
1
2
3
4
    # Vider les tables actuelles 
    iptables -t filter -F 
    # Vider les règles personnelles 
    iptables -t filter -X
3.1.2. Règles par défaut
On bloque tout en entrée et sortie:
Code bash : Sélectionner tout
1
2
3
    iptables -t filter -P INPUT DROP 
    iptables -t filter -P FORWARD DROP 
    iptables -t filter -P OUTPUT DROP
3.1.3. Non crypté
On maintient toutes les connexions sont déja établies ou les nouvelles qui découle de celles-ci:
Code bash : Sélectionner tout
1
2
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
    iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
On a donc toutes les règles suivantes qui ne concerneront que le droit ou non d'ouvrir un flux, on aura donc dans celles-ci:
Code bash : Sélectionner tout
-m state --state NEW
3.1.4. On ouvre la boucle locale
On ouvre tout en entrée et sortie sur la boucle locale:
Code bash : Sélectionner tout
1
2
    iptables -t filter -A INPUT -i lo -j ACCEPT 
    iptables -t filter -A OUTPUT -o lo -j ACCEPT
3.1.5. Quelques petits réglages de sécurité
On va mettre en place de réglages pour augmenter la sécurité, mais comme ils sont dépendant du noyau, certains peuvent ne pas fonctionner:
Code bash : Sélectionner tout
1
2
3
4
5
6
7
8
    echo 1 > /proc/sys/net/ipv4/tcp_syncookies 
    echo 0 > /proc/sys/net/ipv4/ip_forward 
    echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 
    echo 1 > /proc/sys/net/ipv4/conf/all/log_martians 
    echo 1 > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 
    echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter 
    echo 0 > /proc/sys/net/ipv4/conf/all/send_redirects 
    echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route

3.2. Le service ssh
On va commencer par créer une chaîne de règles, nommée SSH_DROP, pour mettre dans le log les tentatives de connexion avant de les jeter sans notification aux émetteurs des paquets:
Code bash : Sélectionner tout
1
2
3
4
    # Règle de rejet et log des tentatives de connexion en trop sur SSH 
    iptables -N SSH_DROP 
    iptables -A SSH_DROP -j LOG --log-prefix '[fw drop -> Attack ssh] : ' 
    iptables -A SSH_DROP -j DROP
On ouvre en entrée et sortie le port qu'on a mis dans la variable [COLOR="#00FF00"]$ssh_port[,/COLOR], mais on impose une limite de 4 connexions par minute pour limiter les tentatives d'attaques par force brute.
Code bash : Sélectionner tout
1
2
3
4
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m recent --set --name SSH_BAD 
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m recent --update --seconds 60 --hitcount 4 --name SSH_BAD -j SSH_DROP 
    iptables -t filter -A INPUT -i eth0 -p tcp --dport ${ssh_port} -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --dport ${ssh_port} -m state --state NEW -j ACCEPT

3.3. Les principaux services
3.3.1. En TCP
On fait une déclaration multiport pour les services TCP courants (DNS, HTTP, HTTPS):
Code bash : Sélectionner tout
1
2
    iptables -t filter -A INPUT -i eth0 -p tcp -m multiport --dports 53,80,443 -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp -m multiport --dports 53,80,443 -m state --state NEW -j ACCEPT
On notera que le procédé de création de certificats SSL Let's encrypt, maintenant bien supporté, ainsi que les utilitaires apt-get, aptitude et wget utilisent les ports 80 et 443 en entrée et sortie.
3.3.2. En UDP
On ouvre pour le DNS pour son fonctionnement en UDP:
Code bash : Sélectionner tout
1
2
    iptables -t filter -A INPUT -i eth0 -p udp --dport 53 -m state --state NEW -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p udp --dport 53 -m state --state NEW -j ACCEPT
On ouvre le port du service de mise à jour de l'horloge du serveur:
Code bash : Sélectionner tout
    iptables -t filter -A OUTPUT -p udp --dport 123 -j ACCEPT
3.3.3. Les autres services TCP et UDP
Ma volonté a été de faire un serveur minimaliste donc les services tels que les serveurs de mails ou FTP ne seront pas abordés ici et seront à rajouter au script si on veut les prendre en compte.

3.4. Le FTP sortant en passif
L'utilitaire wget utilise parfois le protocole FTP. Si en FTP actif, ouvrir les ports 20 et 21 suffit, en mode passif les choses sont plus compliquées, ce qui explique un échec de téléchargement alors que la connexion à l'hôte se passe bien. Cela est dû à une connexion supplémentaire qui se négocie via l'un des ports 20 ou 21. Du coup, les états ESTABLISHED et RELATED ne permettent pas de gérer cette nouvelle connexion. Pour se faire, deux modules optionnels de IPTABLES, ip_conntrack et ip_conntrack_ftp, doivent être activés grâce à modprobe:
Code bash : Sélectionner tout
1
2
    modprobe ip_conntrack 
    modprobe ip_conntrack_ftp
Il reste à ouvrir les ports disponibles à partir de 1024 pour la connexion supplémentaire en cas de connexion sur les ports 20 et 21:
Code bash : Sélectionner tout
1
2
3
4
5
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 20 -m state --state ESTABLISHED -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT 
    iptables -t filter -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p tcp --sport 20 --dport 1024:65535 -m state --state ESTABLISHED,RELATED -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p tcp -m multiport --sports 21,1024:65535 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

3.5. Le monitoring de l'hébergeur
3.5.1. En TCP
Dans le cas d'OVH, on a tout un tas de serveurs qui servent pour voir la présence sur le réseau des serveurs dédiés et VPS. Ils utilisent le protocole ICPM, on le leur permet donc avec leurs IP comme source:
Code bash : Sélectionner tout
1
2
3
4
    iptables -t filter -A INPUT -i eth0 -p icmp -s 92.222.184.0/24,92.222.185.0/24,92.222.186.0/24,167.114.37.0/24 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s 37.187.231.251/32,151.80.118.100/32,151.80.231.244/32,151.80.231.245/32,151.80.231.246/32,151.80.231.247/32 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s 213.186.33.62/32,213.186.45.4/32,213.251.184.9/32,37.59.0.235/32,8.33.137.2/32,213.186.33.13/32,213.186.50.98/32 -m state --state NEW -j ACCEPT 
    iptables -t filter -A INPUT -i eth0 -p icmp -s ${serveur_24}.250/32,${serveur_24}.251/32 -m state --state NEW -j ACCEPT
3.5.2. Le service RTM
C'est un script qui envoie à intervalle régulier préprogrammé tout ou partie d'un ensemble d'informations sur l'état du matériel, pour OVH:
Code bash : Sélectionner tout
    iptables -t filter -A OUTPUT -o eth0 -p udp -dport 6100:6200 -m state --state NEW -j ACCEPT

4. Conclusion

On a ainsi un petit exemple de script facilement personnalisable pour la situation de chacun en rajoutant les services nécessaires. On pourra se baser sur le sujet du site bien connu de alsacreation sur le sujet: ici. On y trouvera des réglages supplémentaires notamment pour OVH
Pour un serveur de mail, on utilisera certaines de ces actions:
Code bash : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Mail SMTP:25 
iptables -t filter -A INPUT -p tcp --dport 25 -j ACCEPT 
iptables -t filter -A OUTPUT -p tcp --dport 25 -j ACCEPT 
  
# Mail POP3:110 
iptables -t filter -A INPUT -p tcp --dport 110 -j ACCEPT 
iptables -t filter -A OUTPUT -p tcp --dport 110 -j ACCEPT 
  
# Mail IMAP:143 
iptables -t filter -A INPUT -p tcp --dport 143 -j ACCEPT 
iptables -t filter -A OUTPUT -p tcp --dport 143 -j ACCEPT 
  
# Mail POP3S:995 
iptables -t filter -A INPUT -p tcp --dport 995 -j ACCEPT 
iptables -t filter -A OUTPUT -p tcp --dport 995 -j ACCEPT
Pour un serveur FTP dynamique:
Code bash : Sélectionner tout
1
2
3
4
5
6
7
# FTP Out 
iptables -t filter -A OUTPUT -p tcp --dport 20:21 -j ACCEPT 
  
# FTP In 
modprobe ip_conntrack_ftp # ligne facultative avec les serveurs OVH 
iptables -t filter -A INPUT -p tcp --dport 20:21 -j ACCEPT 
iptables -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Pour un serveur FTP passif, une plage supplémentaire de ports à partir de 1024 sera nécessaire.


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :
Offres d'emploi IT
Architecte / concepteur électronique analogique H/F
Safran - Ile de France - Éragny (95610)
Ingénieur développement électronique H/F
Safran - Ile de France - 100 rue de Paris 91300 MASSY
Responsable de projets - actionneurs H/F
SAFRAN - Ile de France - MASSY / MANTES

Voir plus d'offres Voir la carte des offres IT
Contacter le responsable de la rubrique Linux