Ce didacticiel va traiter de la création d'un service de nom "firewall" (pare-feu) sous la raspberry.
Il a été testé et a priori, il fonctionne.
Je vais détailler les différentes étapes à sa création et à son test :
1) ou créer le service ?
Cela se fait dans le répertoire "/etc/init.d".
Il suffit de créer un fichier, par exemple de nom "firewall" dans ce répertoire.
Il est inutile de mettre un suffixe à ce fichier.
2) Que faire quand le fichier "firewall" est créé ?
Se mettre dans le répertoire "/etc/init.d", puis faire :
Code : Tout sélectionner
chmod 755 firewall
chown root:root firewall
Je me suis inspiré d'un service déjà existant (DHCPCD) mais aussi de ce qui a été proposé sous google.
4) Comment supprimer le service "firewall" ?
Code : Tout sélectionner
sudo update-rc.d -f firewall remove
Code : Tout sélectionner
sudo update-rc.d firewall default
6) Si vous avez besoin de changer les valeurs par défaut, de la création d'un service :
Code : Tout sélectionner
sudo update-rc.d firewall start 2 3 4 5 . stop 0 1 6 .
Vous devez vous rendre dans les répertoires "/etc/rc*.d".
L'étoile va correspondre à un nombre.
Si le service existe déjà, il sera présent.
8) Comment démarrer le service "firewall" ?
Se mettre dans le répertoire "/etc/init.d", puis faire :
Code : Tout sélectionner
firewall start
Se mettre dans le répertoire "/etc/init.d", puis faire :
Code : Tout sélectionner
firewall stop
Se mettre dans le répertoire "/etc/init.d", puis faire :
Code : Tout sélectionner
firewall status
Nous avons adopté les règles suivantes :
Au démarrage, nous interdisons tout, sauf.
A l'arrêt, nous autorisons tout, sauf.
11) Comment ajouter un journal au service "firewall" ?
Cela se passe dans le répertoire "/etc/rsyslog.d".
J'ai créé un fichier de nom "firewall.conf" avec ceci comme contenu :
Code : Tout sélectionner
:msg, contains, " IN4: " -/var/log/firewall.log
:msg, contains, " OUT4: " -/var/log/firewall.log
:msg, contains, " FOR4: " -/var/log/firewall.log
:msg, contains, " IN6: " -/var/log/firewall.log
:msg, contains, " OUT6: " -/var/log/firewall.log
:msg, contains, " FOR6: " -/var/log/firewall.log
:msg, contains, " SSH: " -/var/log/firewall.log
:msg, contains, " ERR: " -/var/log/firewall.log
12) Comment remplir le journal "firewall" ?
Cela se fait dans le service "firewall" en précisant dans une règle le journal "LOG" ainsi que le libellé.
Par exemple :
Code : Tout sélectionner
iptables -A INPUT -j LOG --log-prefix 'IN: '
Afin d'orienter le flux vers notre journal "firewall", il faut un identifiant qui est, dans notre cas, la chaîne "IN:".
13) Comment tester ?
Nous avons ajouter après "start" et "stop" le paramètre "test", qui en réalité est un "start" suivie d'une pause de 2 minutes puis enfin un "stop".
Ceci permet, dans une autre console, de tester votre modification dans le service "service" sans perdre la main au cas où elle serait fausse.
Avant d'installer cette astuce, je me suis retrouvé bloqué, et j'ai dû utiliser mon autre raspberry (Rpi2 + carte Micro SD), afin de monter mon disque et de corriger le problème.
Beaucoup de manipulations inutiles qui seront résolus par cette astuce.
14) Que faire durant les tests ?
Voici ce que j'ai testé sur mon ordinateur windows ou dans ma raspberry :
14-a) ping sur les adresses suivantes :
--> 127.0.0.1
--> ::1
--> 192.168.1.20 (ordinateur windows en IPv4).
--> 2a02:8435:342:3001::200 (ordinateur windows en IPv6).
--> www.google.fr (en IPv4).
--> www.google.fr (en IPv6).
14-b) renew sur le dhcpcd.
Code : Tout sélectionner
dhcpcd -k wlan0; dhcpcd -d wlan0
14-d) navigateur chromium (depuis le bureau de la raspberry).
14-e) les accès en SSH.
14-f) les accès aux noms DNS que j'ai mis dans ma box.
14-g) Je n'ai pas encore testé les scans des ports.
15) Voici le script du service "firewall" :
Code : Tout sélectionner
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: firewall rules
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start daemon at boot time
# Description: Firewall for raspberry pi
### END INIT INFO
# ============== #
# Initialisation #
# ============== #
PATH=/usr/sbin:/usr/bin:/sbin:/bin
IPTv4='/sbin/iptables '
IPTv6='/sbin/ip6tables '
. /lib/lsb/init-functions
test -x $IPTv4 || exit 0
test -x $IPTv6 || exit 0
# ============================== #
# Nettoyage de toutes les règles #
# ============================== #
do_clear()
{
# ---------------------------------------- #
# Suppression des règles existantes (IPv4) #
# ---------------------------------------- #
$IPTv4 -F
$IPTv4 -X
$IPTv4 -t nat -F
$IPTv4 -t nat -X
# ---------------------------------------- #
# Suppression des règles existantes (IPv6) #
# ---------------------------------------- #
$IPTv6 -F
$IPTv6 -X
$IPTv6 -t nat -F
$IPTv6 -t nat -X
}
# ============================================ #
# Les Règles de la table 'FILTER' au Démarrage #
# ============================================ #
do_filter_start()
{
# ---------------------------- #
# Les Règles par défaut (IPv4) #
# ---------------------------- #
$IPTv4 -P INPUT DROP
$IPTv4 -P OUTPUT DROP
$IPTv4 -P FORWARD DROP
# ---------------------------- #
# Les Règles par défaut (IPv6) #
# ---------------------------- #
$IPTv6 -P INPUT DROP
$IPTv6 -P OUTPUT DROP
$IPTv6 -P FORWARD DROP
# ---- #
# Scan #
# ---- #
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL URG,PSH,SYN,FIN -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL SYN,FIN -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags ALL FIN -j DROP
# $IPTv4 -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
# -------- #
# Spoofing #
# -------- #
$IPTv4 -A INPUT -d 224.0.0.0/3 -j DROP
$IPTv4 -A OUTPUT -d 224.0.0.0/3 -j DROP
# ---------------------------- #
# Les connexions déjà établies #
# ---------------------------- #
$IPTv4 -A INPUT -m state --state ESTABLISHED -j ACCEPT
$IPTv4 -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
$IPTv4 -A FORWARD -m state --state ESTABLISHED -j ACCEPT
# ------------- #
# Protocole DNS #
# ------------- #
$IPTv4 -A OUTPUT -p udp -m udp --dport 53 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT
$IPTv4 -A INPUT -p udp -m udp --sport 53 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
$IPTv6 -A OUTPUT -p udp --sport 5353 --dport 5353 -j ACCEPT
$IPTv6 -A INPUT -p udp --sport 5353 --dport 5353 -j ACCEPT
# -------------- #
# Protocole DHCP #
# -------------- #
$IPTv4 -A OUTPUT -p udp -m udp --sport 68 --dport 67 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
$IPTv6 -A OUTPUT -p udp -m udp --sport 546 --dport 547 -j ACCEPT
$IPTv6 -A INPUT -p udp -m udp --sport 547 --dport 546 -j ACCEPT
# -------- #
# Loopback #
# -------- #
$IPTv4 -A INPUT -i lo -j ACCEPT
$IPTv4 -A OUTPUT -o lo -j ACCEPT
$IPTv6 -A INPUT -i lo -j ACCEPT
$IPTv6 -A OUTPUT -o lo -j ACCEPT
$IPTv4 -A INPUT -d 127.0.0.0/8 -j REJECT
$IPTv4 -A OUTPUT -s 127.0.0.0/8 -j REJECT
# ------------- #
# Protocole SSH #
# ------------- #
$IPTv4 -N SSH_DROP
$IPTv4 -A SSH_DROP -m limit --limit 1/second -j LOG --log-prefix 'SSH: '
$IPTv4 -A SSH_DROP -j DROP
$IPTv4 -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 3 --name SSH -j SSH_DROP
$IPTv4 -A INPUT -p tcp --dport 22 -m recent --set --name SSH
$IPTv4 -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT
$IPTv4 -A OUTPUT -p tcp --sport 22 -j ACCEPT
# ------------------------------------- #
# Protocole ICMPv6 (Messages d'erreurs) #
# ------------------------------------- #
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type destination-unreachable -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type packet-too-big -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type time-exceeded -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type parameter-problem -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type parameter-problem -j ACCEPT
# ----------------------- #
# Protocole ICMPv4 (Ping) #
# ----------------------- #
$IPTv4 -A OUTPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
$IPTv4 -A INPUT -p icmp --icmp-type echo-reply -m limit --limit 1/second -j ACCEPT
$IPTv4 -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/second -j ACCEPT
$IPTv4 -A OUTPUT -p icmp --icmp-type echo-reply -m limit --limit 1/second -j ACCEPT
# ----------------------- #
# Protocole ICMPv6 (Ping) #
# ----------------------- #
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 1/second -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type echo-reply -m limit --limit 1/second -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type echo-request -m limit --limit 1/second -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type echo-reply -m limit --limit 1/second -j ACCEPT
# ---------------- #
# Protocole ICMPv6 #
# ---------------- #
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type router-solicitation -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type router-solicitation -j DROP
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type router-advertisement -j DROP
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type router-advertisement -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type redirect -j DROP
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type redirect -m hl --hl-eq 255 -j ACCEPT
$IPTv6 -A OUTPUT -p icmpv6 --icmpv6-type 143 -j ACCEPT
$IPTv6 -A INPUT -p icmpv6 --icmpv6-type 143 -j ACCEPT
# ------------------------- #
# Protocole ICMPv6 (Autres) #
# ------------------------- #
$IPTv6 -A OUTPUT -p icmpv6 -j LOG --log-prefix 'ERR: '
$IPTv6 -A INPUT -p icmpv6 -j LOG --log-prefix 'ERR: '
$IPTv6 -A FORWARD -p icmpv6 -j LOG --log-prefix 'ERR: '
$IPTv6 -A OUTPUT -p icmpv6 -j DROP
$IPTv6 -A INPUT -p icmpv6 -j DROP
$IPTv6 -A FORWARD -p icmpv6 -j DROP
# ------------------------------- #
# Protocole HTTP / HTTPS (Client) #
# ------------------------------- #
$IPTv4 -A OUTPUT -p tcp -m multiport --dport 80,443,8080 -j ACCEPT
$IPTv4 -A INPUT -p tcp -m multiport --sport 80,443,8080 -j ACCEPT
$IPTv6 -A OUTPUT -p tcp -m multiport --dport 80,443,8080 -j ACCEPT
$IPTv6 -A INPUT -p tcp -m multiport --sport 80,443,8080 -j ACCEPT
# ---------------------- #
# Network Time Protocole #
# ---------------------- #
$IPTv4 -A OUTPUT -p udp --dport 123 -j ACCEPT
$IPTv4 -A INPUT -p udp --sport 123 -j ACCEPT
$IPTv6 -A OUTPUT -p udp --dport 123 -j ACCEPT
$IPTv6 -A INPUT -p udp --sport 123 -j ACCEPT
# --------------------------------- #
# Virtual Network Connection Viewer #
# --------------------------------- #
$IPTv4 -A INPUT -p tcp --dport 5901:5902 -j ACCEPT
$IPTv4 -A OUTPUT -p tcp --sport 5901:5902 -j ACCEPT
$IPTv6 -A INPUT -p tcp --dport 5901:5902 -j ACCEPT
$IPTv6 -A OUTPUT -p tcp --sport 5901:5902 -j ACCEPT
# -------------- #
# Samba (Server) #
# -------------- #
$IPTv4 -A OUTPUT -p udp --sport 137:138 --dport 137:138 -j ACCEPT
$IPTv4 -A INPUT -p udp --sport 137:138 --dport 137:138 -j ACCEPT
$IPTv4 -A OUTPUT -p tcp -m multiport --sport 139,445 -j ACCEPT
$IPTv4 -A INPUT -p tcp -m multiport --dport 139,445 -j ACCEPT
# ------------------------------- #
# Attaque de type Déni de Service #
# ------------------------------- #
# $IPTv4 -A FORWARD -p tcp --syn -m limit --limit 1/second -j ACCEPT
# $IPTv4 -A FORWARD -p udp -m limit --limit 1/second -j ACCEPT
# ------------------ #
# Les scans de ports #
# ------------------ #
# $IPTv4 -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/second -j ACCEPT
# ------------- #
# Autres (IPv4) #
# ------------- #
$IPTv4 -A INPUT -j LOG --log-prefix 'IN4: '
$IPTv4 -A OUTPUT -j LOG --log-prefix 'OUT4: '
$IPTv4 -A FORWARD -j LOG --log-prefix 'FOR4: '
$IPTv4 -A INPUT -j REJECT
$IPTv4 -A OUTPUT -j REJECT
$IPTv4 -A FORWARD -j REJECT
# ------------- #
# Autres (IPv6) #
# ------------- #
$IPTv6 -A INPUT -j LOG --log-prefix 'IN6: '
$IPTv6 -A OUTPUT -j LOG --log-prefix 'OUT6: '
$IPTv6 -A FORWARD -j LOG --log-prefix 'FOR6: '
$IPTv6 -A OUTPUT -j REJECT
$IPTv6 -A INPUT -j REJECT
$IPTv6 -A FORWARD -j REJECT
}
# ========================================= #
# Les Règles de la table 'NAT' au démarrage #
# ========================================= #
do_nat_start()
{
# --------------------------- #
# Network Address Translation #
# --------------------------- #
$IPTv4 -t nat -A POSTROUTING -o eth0 -j MASQUERADE
$IPTv6 -t nat -A POSTROUTING -o eth0 -j MASQUERADE
}
# ========================================= #
# Les Règles de la table 'FILTER' à l'arrêt #
# ========================================= #
do_filter_stop()
{
# ---------------------------- #
# Les Règles par défaut (IPv4) #
# ---------------------------- #
$IPTv4 -P INPUT ACCEPT
$IPTv4 -P OUTPUT ACCEPT
$IPTv4 -P FORWARD ACCEPT
# ---------------------------- #
# Les Règles par défaut (IPv6) #
# ---------------------------- #
$IPTv6 -P INPUT ACCEPT
$IPTv6 -P OUTPUT ACCEPT
$IPTv6 -P FORWARD ACCEPT
}
# ====================================== #
# Les Règles de la table 'NAT' à l'arrêt #
# ====================================== #
#do_nat_stop()
#{
#}
# ============================== #
# les fonctionnalités du service #
# ============================== #
case "$1" in
start|restart)
do_clear
do_filter_start
do_nat_start
;;
stop)
do_clear
do_filter_stop
# do_nat_stop
;;
test)
$0 start
sleep 120
$0 stop
;;
*)
log_failure_msg "Usage: /etc/init.d/firewall {start|stop|restart|test}" || true
exit 1
esac
Concernant le script, si vous avez des remarques à me faire, je suis preneur.
Je ne suis pas un expert des iptables sous linux (raspbian). J'ai fait quelques recherches sur google et fait beaucoup de tests.
Les parties encore en commentaires n'ont pas été testés.
Si j'ai oublié quelque chose, je compléterais ce message.
@+