Debian11, Serveur, Logcheck pour notifier toute activité inconnue
Installation et configuration de LogCheck, avec réglages. LogCheck parcourt les fichiers journaux du système, retire les motifs légitimes connus et envoie les lignes restantes à l’dministrateur. Il rapporte toute l’activité anormale, aidant à détecter des tentatives d’attaques, éventuellement réussies, qui ne seraient pas stoppées par d’autres outils. Je préfère avoir peu de notifications et les lire toutes que d’en avoir trop et de les ignorer.
- Présentation de LogCheck
- Pré-requis
- Installation
- Configuration et ajustements
- Tests
- Supports et liens
- Notes de bas de page
Présentation de LogCheck
LogCheck fait partie de l’outillage global de la sécurité des serveurs. Il parcourt tous les principaux fichiers journaux jusqu’à la fin, en retire les motifs habituels standard et envoie les lignes restantes à l’administrateur. Il enregistre un curseur par fichier journal pour éviter de parcourir plusieurs fois les mêmes lignes.
Ma politique est de considérer les attaques bloquées par ailleurs comme normales, car elles ont déjà été
bloquées et peuvent l’être encore plus, automatiquement. Je ne suis intéressé que par les motifs inconnus. Il
serait inutile d’avoir tellement de notifications que je ne les lise plus. Je préfère en recevoir moins et les
lire. Sur mes systèmes de test, dans un environnement protégé, mon but est de ne plus avoir de notification du
tout. Si je reçois une notification tous les jours lorsque cron-daily
se déclenche, je ne vais plus les lire
car je les considère comme normales et je ne verrai pas si une attaque survient dans la même tranche horaire.
Pré-requis
Cet article ne dépend que de la série sur la Préparation d’une machine générique.
Variables existantes
Nous avons besoin des variables LAN_*
et WAN_*
qui ont déjà été définies dans le fichier de configuration
par les articles Variables de configuration et Configuration réseau.
Chargement des variables
Assurons-nous que les variables sont bien disponibles dans l’environnement en exécutant le script de configuration :
source /root/config.env
Installation
Installons simplement l’outil à l’aide d’apt-get
. Il est léger et ne pose aucune question.
apt-get install -y logcheck
Configuration et ajustements
Agrégation (groupe/compteur) des lignes
Tout d’abord, je ne souhaite pas reçevoir une liste exhaustive des lignes restantes dans mes courriels de notification, je préfère les avoir groupées, le message est plus compact et utile. L’idée est de recevoir une notification et d’enquêter éventuellement sur le serveur, pas d’historiser les journaux dans ma boite électronique. Ensuite, je configure l’adresse électronique de destination à laquelle envoyer les notifications.
sed -i 's/^#\?SYSLOGSUMMARY=0/SYSLOGSUMMARY=1/' /etc/logcheck/logcheck.conf
sed -i 's/^#\?\(SENDMAILTO=\).*/\1"root"/' /etc/logcheck/logcheck.conf
Motifs RegEx utiles
- Interface
en[op][0-9]s[0-9](p[0-9])?
- IP4
([0-9]{1,3}\.){3}[0-9]{1,3}
- IP6
([[:xdigit:]]{4}:){7}[[:xdigit:]]{4}
- MAC
([[:xdigit:]]{2}:){13}[[:xdigit:]]{2}
Je recommende fortement de toujours encapsuler les expressions régulières entre un accent circonflexe et un dollar pour représenter une ligne complète et éviter de filtrer des lignes utiles.
Ignorer les attaques bloquées par IPTables
IPTables continue à historiser beaucoup de connexions bloquées. Je ne souhaite pas être notifié de toutes ces connexions bloquées, aucune action de ma part n’est requise, elles ont déjà été bloquées. Je veux être notifié de l’activité anormale, non prévue, je filtre donc la plupart des problèmes déjà détectés et gérés. Je ne garde que les tentatives non capturées par des règles spéficiques, celles qui atteignent la règle « attrape-tout ». Les motifs sont très spécifiques et restrictifs sur des cas parfaitements connus, il peut donc subsister beaucoup de lignes, au besoin, j’ajusterai les motifs pour filtrer avec moins de restrictions.
cat << EOF > /etc/logcheck/ignore.d.server/local-kernel
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[STEALTH\] IN=[[:alnum:]]+ OUT= MAC=[[:alnum:]:]+ SRC=[.[:digit:]]{7,15} DST=[.[:digit:]]{7,15} LEN=[[:digit:]]+ TOS=0x[[:digit:]]+ PREC=0x[[:digit:]]+ TTL=[[:digit:]]+ ID=[[:digit:]]+ .*$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[SYNSCAN\] IN=[[:alnum:]]+ OUT= MAC=[[:alnum:]:]+ SRC=[.[:digit:]]{7,15} DST=[.[:digit:]]{7,15} LEN=[[:digit:]]+ TOS=0x[[:digit:]]+ PREC=0x[[:digit:]]+ TTL=[[:digit:]]+ ID=[[:digit:]]+ .*$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[CNSCAN\] IN=[[:alnum:]]+ OUT= MAC=[[:alnum:]:]+ SRC=[.[:digit:]]{7,15} DST=[.[:digit:]]{7,15} LEN=[[:digit:]]+ TOS=0x[[:digit:]]+ PREC=0x[[:digit:]]+ TTL=[[:digit:]]+ ID=[[:digit:]]+ .*$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[GRSCAN\] IN=[[:alnum:]]+ OUT= MAC=[[:alnum:]:]+ SRC=[.[:digit:]]{7,15} DST=[.[:digit:]]{7,15} LEN=[[:digit:]]+ TOS=0x[[:digit:]]+ PREC=0x[[:digit:]]+ TTL=[[:digit:]]+ ID=[[:digit:]]+ .*$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[INPUT\] IN=${WAN_IF} OUT= MAC=([[:xdigit:]]{2}:){13}[[:xdigit:]]{2} SRC=([0-9]{1,3}\.){3}[0-9]{1,3} DST=([0-9]{1,3}\.){3}255 LEN=164 TOS=0x00 PREC=0x00 TTL=64 ID=[[:digit:]]+ DF PROTO=UDP SPT=44752 DPT=6771 LEN=[[:digit:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[INPUT\] IN=${WAN_IF} OUT= MAC=([[:xdigit:]]{2}:){13}[[:xdigit:]]{2} SRC=([0-9]{1,3}\.){3}[0-9]{1,3} DST=([0-9]{1,3}\.){3}255 LEN=44 TOS=0x00 PREC=0x00 TTL=64 ID=[[:digit:]]+ DF PROTO=UDP SPT=8612 DPT=861[02] LEN=24$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[INPUT\] IN=${WAN_IF} OUT= MAC=([[:xdigit:]]{2}:){13}[[:xdigit:]]{2} SRC=([0-9]{1,3}\.){3}[0-9]{1,3} DST=255\.255\.255\.255 LEN=101 TOS=0x00 PREC=0x00 TTL=64 ID=[[:digit:]]+ DF PROTO=UDP SPT=[[:digit:]]+ DPT=161 LEN=81$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[INPUT\] IN=${WAN_IF} OUT= MAC=([[:xdigit:]]{2}:){13}[[:xdigit:]]{2} SRC=([0-9]{1,3}\.){3}[0-9]{1,3} DST=255.255.255.255 LEN=[[:digit:]]+ TOS=0x[01]0 PREC=0x00 TTL=[[:digit:]]+ ID=[[:digit:]]+ (DF )?PROTO=UDP SPT=68 DPT=67 LEN=[[:digit:]]+$
# ff02:0000:0000:0000:0000:0000:0000:0002 = All local routers
# FF02:0000:0000:0000:0000:0000:0000:0001 = All local nodes
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[IP6\] IN= OUT=en[op][0-9]s[0-9](p[0-9])? SRC=([[:xdigit:]]{4}:){7}[[:xdigit:]]{4} DST=ff02:(0000:){6}0002 LEN=56 TC=0 HOPLIMIT=255 FLOWLBL=0 PROTO=ICMPv6 TYPE=133 CODE=0$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[IP6\] IN= OUT=en[op][0-9]s[0-9](p[0-9])? SRC=(0000:){7}0000 DST=ff02:(0000:){6}0016 LEN=76 TC=0 HOPLIMIT=1 FLOWLBL=0 PROTO=ICMPv6 TYPE=143 CODE=0 MARK=0xd4$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] \[IP6\] IN= OUT=lo SRC=(0000:){7}0001 DST=(0000:){7}0001 LEN=[[:digit:]]+ TC=[[:digit:]]+ HOPLIMIT=64 FLOWLBL=[[:digit:]]+ PROTO=UDP SPT=[[:digit:]]+ DPT=[[:digit:]]+ LEN=[[:digit:]]+$
EOF
Ignore les connexions SSH bloquées
Ces lignes sont des échecs de connexion SSH typiques. Elles ont été bloquées, puis le limiteur de débit et les règles Fail2ban vont réagir, si l’attaque persiste. Je n’ai pas besoin d’en être notifié.
cat << EOF > /etc/logcheck/ignore.d.server/local-ssh
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ sshd\[[[:digit:]]+\]: Received disconnect from [[:digit:].]+ port [[:digit:]]+.*\[preauth\]$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ sshd\[[[:digit:]]+\]: Disconnected from [[:digit:].]+ port [[:digit:]]+.*\[preauth\]$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ sshd\[[[:digit:]]+\]: Invalid user [_[:alnum:]]+ from [[:digit:].]+ port [[:digit:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ sshd\[[[:digit:]]+\]: Connection closed by [[:digit:].]+ port [[:digit:]:]+.*\[preauth\]$
EOF
Activité normale de Systemd
Ces actions sont des opérations de maintenance normales automatiquement déclenchées par systemd
, je ne m’en
préoccupe pas, du moment qu’elles fonctionnent ! ;)
cat << EOF > /etc/logcheck/ignore.d.server/local-systemd
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: [-/:. [:alnum:]]+: Succeeded.$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: [-/:. [:alnum:]]+: Succeeded.$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: Started [-/:. [:alnum:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: Created [-/:. [:alnum:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: Starting [-/:. [:alnum:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ systemd\[1\]: Finished [-/:. [:alnum:]]+$
EOF
CronApt
CronApt nous indique qu’il a tenté et réussi à mettre la base des paquetages à jour, ou qu’il a téléchargé des paquetages, ou qu’il…. nous a envoyé un courriel !!! C’est un comportement normal et je suis donc déjà prévenu des informations importantes par rapport à ce qu’il fait.
cat << EOF > /etc/logcheck/ignore.d.server/local-cronapt
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ cron-apt: CRON-APT ACTION: 9-notify$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ cron-apt: CRON-APT LINE: /usr/bin/apt-get -o quiet=2 -q -q --no-act upgrade$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ cron-apt: CRON-APT LINE: /usr/bin/apt-get -o quiet=2 update -o quiet=2$
EOF
Divers
Il y a une procédure d’audit régulier déclenchée dans le noyau linux pour collecter des indicateurs de performance. Cette procédure doit être aussi transparente que possible et sa période de déclenchement est automatiquement ajustée si son appel prend trop de temps. C’est donc un message normal, au moins jusqu’à ce que la période optimale soit trouvée (en fonction de la charge du système). Dans tous les cas, j’aurais bien d’autres problèmes si la fréquence et les valeurs de ce message étaient anormales et qu’il devienne utile. J’ai aussi regroupé dans ce fichier les filtrage des lignes normales concernant le démarrage de fail2ban, dhcp, ntp et rsyslogd. RKHunter envoie déjà ses propres courriels de notification, inutile de dupliquer l’information.
cat << EOF > /etc/logcheck/ignore.d.server/local-misc
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[[ [:digit:]]+\.[[:digit:]]+\] perf: interrupt took too long \([[:digit:]]+ > [[:digit:]]+\), lowering kernel.perf_event_max_sample_rate to [[:digit:]]+$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ fail2ban-server\[[[:digit:]]+\]: Server ready$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ isc-dhcp-server\[[[:digit:]]+\]: Starting ISC DHCPv4 server: dhcpd.$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ ntpd\[[[:digit:]]+\]: configuration OK$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ rsyslogd: \[origin software="rsyslogd" swVersion="8.1901.0" x-pid="[[:digit:]]+" x-info="https://www.rsyslog.com"\] rsyslogd was HUPed$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ rkhunter: Please inspect this machine, because it may be infected.$
EOF
Interface réseau LAN
S’il y a une seconde interface réseau sur le serveur, et s’il est utilisé comme routeur, le réseau interne peut être redémarré, débranché, en panne, … Je ne souhaite pas être prévenu par courriel, ce serait stupide d’envoyer une notification quelquepart où je ne peux pas la consulter ! ;) De plus ces règles sont spécifiques à mon matériel (interface et switch).
cat << EOF > /etc/logcheck/ignore.d.server/local-router
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[\s?[[:digit:]]+\.[[:digit:]]+\] e1000e 0000:03:00.0 enp3s0: 10/100 speed: disabling TSO$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[\s?[[:digit:]]+\.[[:digit:]]+\] e1000e: ${LAN_IF} NIC Link is Down$
^\w{3} [ :[:digit:]]{11} [-._[:alnum:]]+ kernel: \[\s?[[:digit:]]+\.[[:digit:]]+\] e1000e: ${LAN_IF} NIC Link is Up 1000 Mbps Full Duplex, Flow Control: Rx/Tx$
Tests
Logcheck-test
Si vous n’êtes pas certains de vos règles, vous pouvez utiliser l’outil logcheck-test
pour appliquer un
fichier de règles sur un fichier de journal, soit pour afficher les correspondances, soit pour afficher les
anomalies. Cela ne fait pas partie de mon installation standard, mais je voulais noter cette information car
elle peut toujours servir pour déboguer les règles et RegExp.
Test des règles
Ce test va exécuter logcheck avec une configuration réelle, mais ne mettra pas le curseur de lecture à jour, il peut donc être exécuté plusieurs fois. Il n’envoie pas de courriel, non plus.
sudo -u logcheck logcheck -o -t
Test de notification
Celui-ci ne mettre pas le curseur à jour, non plus, il peut donc être rejoué autant que nécessaire, jusqu’à ce que les notifications fonctionnent comme voulu.
sudo -u logcheck logcheck -t