====== Firewall ======
Un firewall est un logiciel permettant de filtrer les paquets réseau. Le logiciel le plus utiliser sur les systèmes GNU/Linux est **iptables**. Il permet de configurer des filtres en espace kernel grâce aux modules **Netfilter**.
La chose la plus importante avec un firewall est de filtrer les paquets en entrée. Pour attaquer un serveur, un pirate doit établir une connexion avec celui-ci. Filtrer les paquets venant de l'extérieur est une bonne manière d'éviter bon nombre de problèmes.
**iptables** utilise 2 chaînes nommées **INPUT** and **OUTPUT**. INPUT contient les règles pour filtrer les paquets venant de l'extérieur et OUTPUT contient les règles permettant de filtrer les paquets voulant se diriger vers l'extérieur de la machine.
Note : Toutes les fonctions ici sont utilisées dans une script shell et dépendent d'autres éléments. Regardez le script final pour voir comment les utiliser.
Une bonne pratique pour un firewall est de jeter tous les paquets par défaut. Avec **iptables** ceci est relativement simple à faire :
deny_everything() {
print_debug "Denying all connections"
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP
end_debug $?
}
**iptables** est peut-être déjà configuré lorsque l'on souhaite le reconfigurer. Il peut donc être intéressant de vider les tables afin de redémarrer une configuration de 0 :
cleanup_tables() {
print_debug "Cleaning up tables"
iptables -t filter -F
iptables -t filter -X
end_debug $?
}
Si vous utiliser un serveur déjà en production il se peut qu'il est déjà accepté des connexions, les conserver comme actives peut être pratique. Ainsi, vous ne serez pas déconnecté si vous êtes connecté via SSH.
dont_break_connections() {
print_debug "Keeping active connections"
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
end_debug $?
}
La chose suivante à prendre en compte est d'autoriser la boucle locale sinon cela risque de poser des problèmes avec certains logiciels.
allow_loopback() {
print_debug "Allowing loopback"
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A OUTPUT -o lo -j ACCEPT
end_debug $?
}
Accepter des connexions sur un port avec **iptables** est simple. La syntaxe est plutôt claire. Il faut tout d'abord spécifier la chaîne à utiliser, **INPUT** ou **OUTPUT**, avec l'option **-A**, ensuite on donne le protocole de la couche transport (voir [[http://fr.wikipedia.org/wiki/Mod%C3%A8le_OSI|modèle OSI]]) à utiliser, en général soit **TCP** soit **UDP**, avec l'option **-p** et enfin on donne le numéro du port à ouvrir avec **--dport**. Cela nous donne donc une ligne de la forme :
iptables -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 80 -j ACCEPT
Maintenant vous devriez pouvoir comprendre ce script. Il utilise des fonctions pour configurer **iptables**.
### BEGIN INIT INFO
# Provides: firewall
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Configure iptables (IPv4)
# Description: Setup basic rules for iptables (IPv4)
### END INIT INFO
#!/bin/bash
. /lib/lsb/init-functions
# In debug mode there will be more outputs
# 0 to disable
# 1 to enable
DEBUG=0
# Print message only in debug mode
# Usage: print_debug ${message} ${return_code}
# ${return_code} is optional
print_debug() {
[ ${DEBUG} -eq 0 ] && return 0
[ $# -ne 1 ] && return 1
log_action_begin_msg ${1}
}
end_debug() {
[ ${DEBUG} -eq 0 ] && return 0
[ $# -ne 1 ] && return 1
log_action_end_msg ${1}
}
deny_everything() {
print_debug "Denying connections"
iptables -t filter -P INPUT DROP
iptables -t filter -P FORWARD DROP
iptables -t filter -P OUTPUT DROP
end_debug $?
}
accept_everything() {
print_debug "Accepting all connections"
iptables -t filter -P INPUT ACCEPT
iptables -t filter -P FORWARD ACCEPT
iptables -t filter -P OUTPUT ACCEPT
end_debug $?
}
cleanup_tables() {
print_debug "Cleaning up tables"
iptables -t filter -F
iptables -t filter -X
end_debug $?
}
dont_break_connections() {
print_debug "Keeping active connections"
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
end_debug $?
}
allow_loopback() {
print_debug "Allowing loopback"
iptables -t filter -A INPUT -i lo -j ACCEPT
iptables -t filter -A OUTPUT -o lo -j ACCEPT
end_debug $?
}
deny_spoofing() {
print_debug "Denying spoofing"
iptables -N SPOOFED
iptables -A SPOOFED -s 127.0.0.0/8 -j DROP
iptables -A SPOOFED -s 169.254.0.0/12 -j DROP
iptables -A SPOOFED -s 172.16.0.0/12 -j DROP
iptables -A SPOOFED -s 192.168.0.0/16 -j DROP
iptables -A SPOOFED -s 10.0.0.0/8 -j DROP
end_debug $?
}
misc_config() {
print_debug "Misc configurations"
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/ip_always_defrag
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
end_debug $?
}
open_input_port() {
[ $# -ne 2 ] && exit 1
print_debug "Opening input port ${2} in ${1}"
iptables -t filter -A INPUT -p "${1}" --dport "${2}" -j ACCEPT
end_debug $?
}
open_output_port() {
[ $# -ne 2 ] && exit 1
print_debug "Opening output port ${2} in ${1}"
iptables -t filter -A OUTPUT -p "${1}" --dport "${2}" -j ACCEPT
end_debug $?
}
allow_input_protocol() {
[ $# -ne 1 ] && exit 1
print_debug "Allowing input protocol ${1}"
iptables -t filter -A INPUT -p "${1}" -j ACCEPT
end_debug $?
}
allow_output_protocol() {
[ $# -ne 1 ] && exit 1
print_debug "Allowing output protocol ${1}"
iptables -t filter -A OUTPUT -p "${1}" -j ACCEPT
end_debug $?
}
allow_6in4_protocol() {
[ $# -ne 1 ] && exit 1
print_debug "Allowing IPv6 in IPv4 protocol"
iptables -t filter -A INPUT -s ${1} -p 41 -j ACCEPT
iptables -t filter -A OUTPUT -p 41 -j ACCEPT
end_debug $?
}
case ${1} in
start)
# Stop fail to ban before configuring firewall
/etc/init.d/fail2ban stop
log_action_begin_msg "Firewall (IPv4) configuration"
deny_everything
cleanup_tables
dont_break_connections
# Loopback
allow_loopback
# IPv6 in IPv4
allow_6in4_protocol "216.66.84.42"
# SSH
open_input_port tcp 22
open_output_port tcp 22
# DNS, FTP, HTTP, NTP
open_output_port tcp 21
open_output_port tcp 80
open_output_port tcp 53
open_output_port tcp 443
open_output_port udp 53
open_output_port udp 123
# ICMP
allow_input_protocol icmp
allow_output_protocol icmp
# HTTP
open_input_port tcp 80
open_input_port tcp 443
# MySQL
open_input_port tcp 3306
open_output_port tcp 3306
# POP, IMAP
open_input_port tcp 25
open_input_port tcp 110
open_input_port tcp 995
open_input_port tcp 143
open_input_port tcp 993
open_output_port tcp 25
open_output_port tcp 110
open_output_port tcp 995
open_output_port tcp 143
open_output_port tcp 993
# Mumble
open_input_port tcp 64738
open_input_port udp 64738
open_output_port tcp 64738
open_output_port udp 64738
# Bazaar
open_input_port tcp 4155
open_output_port tcp 4155
# Keys server
open_input_port tcp 11371
open_output_port tcp 11371
# OpenVPN
open_input_port tcp 1194
open_output_port tcp 1194
# Transmission
open_input_port tcp 9091
open_input_port tcp 51413
open_output_port tcp 9091
open_output_port tcp 51413
# Irssi
open_input_port tcp 6667
open_input_port udp 6667
open_output_port tcp 6667
open_output_port udp 6667
# Minecraft
for i in 25565 25566; do
open_input_port tcp ${i}
open_input_port udp ${i}
open_output_port tcp ${i}
open_output_port udp ${i}
done
# Steam
for i in 7707 7708 7717 20560 28852; do
open_input_port udp ${i}
open_output_port udp ${i}
done
for i in 8075 20560 28852; do
open_input_port tcp ${i}
open_output_port tcp ${i}
done
for i in 27011 27900; do
open_input_port tcp ${i}
open_input_port udp ${i}
open_output_port tcp ${i}
open_output_port udp ${i}
done
deny_spoofing
misc_config
# Starting fail2ban again
/etc/init.d/fail2ban start
log_action_end_msg 0
;;
stop)
log_action_begin_msg "Remove firewall (IPv4) configuration"
accept_everything
cleanup_tables
log_action_end_msg 0
;;
*)
echo "Usage: /etc/init.d/firewall {start|stop}"
exit 1
;;
esac
exit 0
Ce script peut être placé dans ///etc/init.d/// et doit avoir les droits d'exécution pour être exécuté par **root**. Il est aussi recommandé de d'utiliser ce script lors du démarrage du système.
update-rc.d firewall defaults
L'utilisation manuel s'effectue par "start" pour démarrer le firewall, et par "stop" pour accepter toutes les connexions et vider toutes les règles.