Logs iptables : Configurer votre firewall pour Splunk

Bonjour à tous, aujourd’hui on prépare le 3ème article de la série sur Splunk et je complète celui sur iptables. Et on va regarder comment configurer les logs iptables de manière à pouvoir les exploiter dans Splunk dans le prochain article.

Configurer les logs iptables

La méthode simple

Sur une Debian 9, par défaut iptables ne trace presque rien et le peu qu’il indique se trouve dans le fichier /var/log/messages avec tout le reste d’une partie des journaux système, complètement hétérogène. CE n’est vraiment pas idéal pour intégrer ça simplement dans Splunk. On va donc faire trois choses dans ce TP:

  1. Configurer iptables pour qu’il ajoute un préfixe sur toutes les lignes de log qu’il écrit ;
  2. indiquer à rsyslog que toute les lignes de logs commençant ce préfixe doivent être placée dans un fichier à part ; et
  3. Configurer un politique de log pour iptables sur note machine.

Et on va commencer par le point numéro deux. Créer un fichier /etc/rsyslog.d/iptables.conf avec votre éditeur préféré avec le contenu suivant :

:msg,contains,"ACTION=" /var/log/iptables.log
& stop

Avec cette configuration, toutes les lignes contenant le texte ACTION= seront placé dans le fichier /var/log/iptables.log. Il ne nous reste plus qu’à redémarrer rsyslog.

systemctl restart rsyslog

Pour ceux qui sont pas au point sur iptables je invite à lire attentivement mon article précédent sur le sujet : Configuration avancée du firewall iptables. On va maintenant indiquer à iptables d’ajouter notre préfixe à ses lignes de logs avec les options ci-dessous sur les règles que l’on veut journaliser :

--log-prefix "INPUT-DROP:" -j DROP

Le problème c’est que le -j LOG fait loguer iptables et passer à la règle suivante ne permet pas d’appliquer une autre action de type DROP ou ACCEPT. On doit donc soit dupliquer nos règles et pour chaque règle que l’on veut tracer avoir une copie de notre ligne ACCEPT ou DROP avec un LOG à la place. Exemple pour journaliser les connexions acceptées :

iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j LOG
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j ACCEPT

La méthode des barbus

Ce mode est efficace pour des configuration simple d’iptables (genre accept/drop sur quelque ports TCP), en revanche pour ce que je vous ai montré la dernière fois avec plusieurs dizaine de règles sauvegarder ça va vite être le bazar dans votre configuration iptables. Mais, il existe une astuce dans iptables qui permet de réaliser sur une seule règle les deux actions LOG et ACCEPT (ou DROP). Pour cela on doit créer une chaine personnalisée qui fera ces deux actions, et sauter vers cette chaine au lieu des actions par défaut. Voilà un exemple de configuration simple qui permet de loguer toute les connexions acceptées :

iptables -P INPUT DROP
iptables -t INPUT -N LOG_N_ACCEPT
iptables -t INPUT -A LOG_N_ACCEPT -j LOG --log-level warning --log-prefix "ACTION=INPUT-ACCEPT"
iptables -t INPUT -A LOG_N_ACCEPT -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -j LOG_N_ACCEPT

Voilà pour la théorie, en pratique on je vous propose de reprendre ma configuration de l’article précédent et de l’ajuster pour tracer les paquets refusé et accepté et de loguer dans le champs ACTION= quelle table d’iptables a pris la décision sur le paquet. Exemple, en éditant le fichier de sauvegarde pour y ajouter les logs iptables :

*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:RAW_LOG_N_DROP - [0:0]
-A PREROUTING -i eth0 -p tcp -m multiport --dports 22,80,443 -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j CT --notrack
-A PREROUTING -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m multiport --dports 22,80,443 -m hashlimit --hashlimit-above 100/sec --hashlimit-burst 1000 --hashlimit-mode srcip --hashlimit-name syn --hashlimit-htable-size 2097152 --hashlimit-srcmask 24 -j RAW_LOG_N_DROP
-A RAW_LOG_N_DROP -j LOG --log-prefix "ACTION=DROP-RAW "
-A RAW_LOG_N_DROP -j DROP
COMMIT
# 
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:PRE_LOG_N_DROP - [0:0]
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,ACK FIN -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags ACK,URG URG -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags PSH,ACK PSH -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,PSH,URG -j PRE_LOG_N_DROP
-A PREROUTING -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK,URG -j PRE_LOG_N_DROP
-A PREROUTING -s 224.0.0.0/8 -j PRE_LOG_N_DROP
-A PREROUTING -s 169.254.0.0/16 -j PRE_LOG_N_DROP
-A PREROUTING -s 172.16.0.0/12 -j PRE_LOG_N_DROP
-A PREROUTING -s 192.0.2.0/24 -j PRE_LOG_N_DROP
-A PREROUTING -s 192.168.0.0/16 -j PRE_LOG_N_DROP
-A PREROUTING -s 10.0.0.0/8 -j PRE_LOG_N_DROP
-A PREROUTING -s 0.0.0.0/8 -j PRE_LOG_N_DROP
-A PREROUTING -s 240.0.0.0/5 -j PRE_LOG_N_DROP
-A PREROUTING -s 127.0.0.0/8 ! -i lo -j PRE_LOG_N_DROP
-A PREROUTING -p icmp -j PRE_LOG_N_DROP
-A PREROUTING -f -j PRE_LOG_N_DROP
-A PRE_LOG_N_DROP -j LOG --log-prefix "ACTION=DROP-PREROUTING "
-A PRE_LOG_N_DROP -j DROP
COMMIT
# 
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:LOG_N_DROP - [0:0]
:LOG_N_IPS-ACCEPT - [0:0]
:fail2ban-ssh - [0:0]
-A INPUT -i eth0 -p tcp -m multiport --dports 22,80,443 -m tcp -m state --state INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
-A INPUT -i eth0 -p tcp -m tcp -m state --state INVALID -j LOG_N_DROP
-A INPUT -p tcp -m multiport --dports 22 -j fail2ban-ssh
-A INPUT -i eth0 -p tcp -m connlimit --connlimit-above 100 --connlimit-mask 32 --connlimit-saddr -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m recent --rcheck --seconds 86400 --name portscan --mask 255.255.255.255 --rsource -j DROP
-A INPUT -m recent --remove --name portscan --mask 255.255.255.255 --rsource
-A INPUT -p tcp -m multiport --dports 25,445,1433,3389 -m recent --set --name portscan --mask 255.255.255.255 --rsource -j LOG_N_DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m multiport --dports 22,80,443 -j LOG_N_ACCEPT
-A LOG_N_ACCEPT -j LOG --log-prefix "ACTION=ACCEPT-INPUT "
-A LOG_N_ACCEPT -j ACCEPT
-A LOG_N_DROP -j LOG --log-prefix "ACTION=DROP-INPUT "
-A LOG_N_DROP -j DROP
-A fail2ban-ssh -j RETURN
-A INPUT -j LOG --log-prefix "ACTION=DROP-POLICY "
COMMIT

N’oubliez pas que si une IP source génère trop de log vous pouvez toujours l’exclure de la règle de log (et uniquement celle-ci) avec les options suivantes :

! -s <NET/MASK> # exclure le subnet
-s <NET/MASK> -m limit --limit 10/min # limiter à 10 lignes identiques par minute et pour le subnet.

Notez qu’activer les logs avec iptables peut générer un peu de volume selon le degré d’exposition de votre serveur. Aussi, je vous conseille de spécifier une politique de logrotate spécifique; sinon ça va piquer un peu au niveau de l’espace disque. Pour cela, créer un fichier /etc/logrotate.d/iptables avec le contenu suivant :

/var/log/iptables.log
{
 rotate 7
 daily
 missingok
 notifempty
 delaycompress
 compress
 postrotate
   invoke-rc.d rsyslog reload > /dev/null
 endscript
}

Bonus : tracer les connexions en sorties

N’oubliez pas que vous pouvez aussi loguer les connexions que votre serveur établis avec l’extérieur. Il n’y a aucune règle dans notre table OUTPUT, donc une seule commande par protocole TCP/UDP suffit :

iptables -I OUTPUT -m state -p tcp --state NEW ! -s 127.0.0.1 ! -d 127.0.0.1 -j LOG --log-prefix "ACTION=OUTPUT-TCP "
iptables -I OUTPUT -m state -p udp -s 127.0.0.1 ! -d 127.0.0.1 -j LOG --log-prefix "ACTION=OUTPUT-UDP "

Encore une fois, selon l’utilisation de votre machine cela peut devenir très verbeux. Donc faite attention à ce que vous faite…

Fin et suite à venir…

Et voilà c’est tout pour aujourd’hui sur les logs iptables, ça devrait compléter les questions que j’ai eu sur l’article précédent sur iptables dans lequel je n’abordais presque pas les logs. Et pour la suite le prochain TP pour voir comment intégrer ces logs dans notre Splunk est en cours de rédaction. Spoiler alert ci-dessous :

Logs iptables

Un commentaire concernant “Logs iptables : Configurer votre firewall pour Splunk

1 Pings/Trackback pour "Logs iptables : Configurer votre firewall pour Splunk"

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.