Sécurité

Sécurité jpp

La sécurité sera ici abordée essentiellement coté réseau avec IPS/IDS et instruments de contrôle des flux réseaux. 
En effet la plupart des "ennuis" et autres "malwares" arrivent par le réseau, sans parler de virus permettant d'installer des portes dérobées et autres joyeusetés, phishing ....
Il import donc de limiter au maximum les possibilités "d'entrée" dans votre réseau. Si vous disposez de plusieurs machines connectées sur un réseau interne vous utilisez probablement une machine W... il faut donc impérativement interdire l'accès à tous les ports relatifs aux partages depuis "l'extérieur", un bon Firewall, si possible placé sur une machine agissant en tant que pont vers Internet permet d"éviter d'ouvrir ce genre de portes aux méchants qui se cachent lâchement ... derrière des FAI laxistes. 
Un bon contrôle supplémentaire n'est pas inutile et certains outils permettent de "jeter un oeil" sur ce qui passe dans les tuyaux et/ou de bloquer de vilaines choses.

​Pour plus de détails vous pouvez consulter la page "Mesures; monitoring" qui présente plus en détails cette problématique.

AbuseIPDB Contributor Badge 

Sécurité Apache : modsec

Sécurité Apache : modsec jpp

Un serveur Apache est, en lui même, assez sécurisé, mais les applications qu'il héberge peuvent présenter des défauts de sécurité. 
Certains IDS/IPS, par exemple Suricata, peuvent utiliser des règles améliorant la sécurité des applications. Mais, car il y a un "mais", le passage en HTTPS empêche pratiquement l'utilisation de ces règles car le contenu des flux HTTPS ne peut être analysé dans le flux des données réseau. Il faut donc se tourner vers une méthode qui agisse après le traitement HTTPS, il faut donc opérer entre le traitement HTTPS et l'application. 
C'est ainsi que "Modsecurity" (de son petit nom "modsec"), module spécialisé pour Apache, permet d'utiliser des règles sur les données "décodées" et donc d'avoir une analyse fine, comme le fait par exemple Suricata pour le HTTP simple ou les autres protocoles non TLSisés.

Remarques au passage : 
Si vous utilisez "Phpmyadmin" veillez à bien le configurer, à nettoyer les scripts de démarrage et filtrer au maximum l'accès à ses fonctions. Le filtrage par IP en limitant à une IP utilisée pour l'administration est une bonne méthode. En effet une grande partie des "pirates" cherchent un accès par des URL comportant "/phpmyadmin" (éventuellement avec quelques majuscules ou raccourcis), ou d'autres chemins connus "/pma", "/myadmin" .... en ciblant souvent les modules "setup...." ou d'autres réputés présenter une faille. 
De toutes façons il ne me semble pas "sain" d'installer de tels outils sur des machines de production en contact avec Internet afin de limiter au maximum la surface d'attaque. 
Il y a d'autre part intérêt, on ne le répète jamais assez, à mettre rapidement en place les mises à jour de sécurité de tous les logiciels.

Apache modsec : installation

Apache modsec : installation jpp

Afin de me familiariser avec Modsec j'ai commencé par réaliser l'installation dans une VM abritant une copie des sites en exploitation. 
Une petite photo des lieux : 
VM avec Debian 9 un processeur et 1,2Go de mémoire.

Pré-requis : mod_unique_id contenu dans le paquet : libapache-session-perl qui installe en plus les 4 paquets suivants : 
libcgi-fast-perl libcgi-pm-perl libfcgi-perl

Ensuite j'ai juste ajouté le paquet libapache2-mod-security2 qui m'installe le paquet modsecurity-crs. Les premiers test sont OK et les temps de réponse semblent corrects, c'est à dire sans altération preceptible.
Lorsque j'ai tenté d'utiliser "git" pour effectuer la mise à jour des règles Owasp j'ai essuyé un échec. Le paquet est modsecurity-crs est "incorrect" car il ne permet pas la mise à jour par git du contenu du répertoire directement depuis le site OWASP ? 
J'ai donc renommé par sécurité le répertoire "incorrect" /usr/share/modsecutity-crs puis chargé le "bon" par git : 
cd /usr/share 
git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git 
Ceci m'a créé un répertoire owasp-modsecurity-crs ce qui m'a obligé à :

  • - corriger le fichier /etc/apache2/mods-available/security2.conf en remplaçant  
    "IncludeOptional /usr/share/modsecurity-crs/owasp-crs.load"  
    par  
    "IncludeOptional /usr/share/owasp-modsecurity-crs/crs-setup.conf"
  • - dans ce même fichier ajouter : 
    "Include /usr/share/owasp-modsecurity-crs/rules/*.conf"
  • - dans le répertoire "/usr/share/owasp-modsecurity-crs" faire : 
    cp crs-setup.conf.example crs-setup.conf
  • - Pour la mise à jour des règles il suffira ensuite de lancer la commande : 
    /usr/share/owasp-modsecurity-crs/util/upgrade.py --crs 
    ou, pour la mise à jour des informations "geoip" : 
    /usr/share/owasp-modsecurity-crs/util/upgrade.py --geoip 
    Attention il m'a fallu modifier le script "upgrade.py" pour remplacer : 
    "https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz' 
    par : 
    "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz"


Avant activation du module :

  • - vérifier que dans /etc/apache2/mods-enabled les liens existent bien, cette action a du être réalisée lors de l'installation initiale :
    •     security2.conf -> ../mods-available/security2.conf
    •     security2.load -> ../mods-available/security2.load
  • Si cela n'est pas fait --> "a2enmod security2"
  • - dans /etc/modsecurity
    • - copier modsecurity.conf-recommended sur modsecurity.conf
    • - activer le module dans "modsecurity.conf" : vérifier que "SecStatusEngine" est bien "on".
  • - relancer apache

Le "error.log" de Apache devrait montrer l'activation de modsecurity. 
Pour mieux "voir" ce qui se passe il est intéressant de mettre la valeur de "SecDebugLogLevel" à 1. 
Par défaut seul le mode "DETECTIONONLY" est activé, il faut donc mettre "SecRuleEngine" à "On" pour activer le mode normal (celui qui bloque les vilaines requêtes ...). 
Je n'ai pas fait d'autres modifications dans ce fichier.

Pour obtenir un log en "JSON" j'ai modifié quelques lignes du fichier "/etc/modsecurity/modsecurity.conf" : 
# DEBUT 
# définitif pour ne voir que "Relevant" 
SecAuditEngine RelevantOnly 
# provisoire pour tout voir 
SecAuditEngine on 
# SecAuditLogRelevantStatus "^(?:5|4(?))" 
SecAuditLogRelevantStatus "^(?:5|4(?!04))" 
# Log everything we know about a transaction. 
# SecAuditLogParts ABDEFHIJZ 
SecAuditLogParts ABFHZ 
SecAuditLogFormat JSON 
SecAuditLogType Serial 
# FIN

Après un "systemctl restart apache2" tout semble fonctionner correctement ... mais l'analyse des fichiers de log de Modsec est assez ardue et je vais essayer de construire quelques outils facilitant la récupération, le stockage, le traitement et l'archivage de ces données. 
Depuis ce test j'ai installé Modsec sur la machine en exploitation et cela repère quelques malins qui tentent des accès douteux réalisés en HTTPS, pour le HTTP Suricata assisté de quelques règles "perso" bloque ou au moins repère la plupart des attaques. 
Le logiciel de gestion des événements générés par Modsec est en cours de réalisation commence à bien fonctionner. 
Ce petit logiciel est constitué d'un module Python qui analyse le fichier d'audit réalisé par modsecurity et inscrit les données dans une base Mysql/MariaDB. 
Quelques progammes en PHP permettent d'afficher et de classifier les événements "repérés" par notre ami modsecurity et de bloquer immédiatement les méchants" à l'aide du pare-feu. 
On peut aussi les "dénoncer", par exemple sur Abuseipdb (AbuseIPDB), pour limiter leur nuisance et intégrer ces IP dans un firewall pour leur bloquer l'accès aux applications maison.

Premières statistiques

Premières statistiques jpp

Après quelques semaines beaucoup d'anomalies ont été interceptées par Modsec, voici un petit tableau statistique des résultats sur le port 443 : 
 
On voit que la majorité des détections sont dues à des "scanners de sites" ou à des "bad bots" qui cherchent inlassablement de nouveaux sites. Un certain nombre de ces "Bad bots" réalisent probablement des actions de reconnaissances pour action ultérieure. 
Remarque : la partie "pirates" ne concerne que le HTTPS, la plupart des attaques exécutées en HTTP sont stoppées par Suricata dans lequel j'ai ajouté un fichier de règles lorsque je rencontre des tentatives non détectées, par exemple il existe des "tests" non détectés au milieu d'une attaque plus vaste. Il est bon d'ajouter la description de ces événements dans une règle Suricata. Ces règles sont souvent plus faciles à écrire que les règles de Modsecurity mais ne peuvent détecter des attaques en HTTPS.

Surveillance : Suricata

Surveillance : Suricata jpp

Petites mises à jour pour la version 3.0,  notamment le fichier de paramètres "suricata.yaml".
En 2020 on est passé en 4.1, en 2023 en 6.0 et en 2024 en 7.0. 

 
La surveillance d'un réseau est une condition indispensable de la sécurité. Après le Firewall qui assure une sécurité "passive" il peut être intéressant d'installer un système d'analyse des flux réseau. Le plus connu de ces logiciels dans le domaine OpenSource est Snort et son cochon mascotte
J'ai déjà installé Snort (paquet Debian standard) avec l'option stockage dans une base Mysql et affichage des résultats à l'aide du logiciel "Base" fourni par le paquet Debian Acidbase. 
J'ai découvert dans un magazine (MISC pour ne pas le citer) un nouveau (enfin presque) logiciel effectuant ce type de travail et j'ai décidé de le tester. Petit problème il n'existe pas de paquet Debian et il faut donc charger, compiler et installer tout ce petit monde. 
Je n'entrerais pas dans les discussions (vous avez dit troll ?) au sujet d'une lutte (d'influence) entre Snort et Suricata au sujet des performances et de la compatibilité des règles.

Pour mémoire il s'agit de :

Note : Snorby est obsolète et impossible à mettre à jour (utilisation d'une version très ancienne de Ruby) et je prépare une application équivalente baptisée "Snorbis "(note 2024 : qui fonctionne correctement depuis des années).

Les opérations seront donc séparées en trois parties principales, on installe Snorby avant Barnyard car Snorby initialise la base de données. Cette base est très semblable à celle de Snort ... avec quelques bricoles en plus.

Après un premier test "à blanc" sur un portable (Debian 6.0), le test suivant a été réalisé sur une machine virtuelle "vierge" afin de bien faire ressortir toutes les dépendances.

La MV (avec KVM bien sûr!) a été installée sur une Debian (6.0) a été utilisée pour initialiser cette machine avec le minimum et "gcc4.7" sans oublier "ln -s /usr/bin/gcc4.7 /usr/bin/gcc" et "g++4.7" avec son petit lien en "g++". 
En ce qui concerne la gestion des règles je présenterai, peut-être, plus tard quelque chose couvrant ce sujet.

Suricata : installation

Suricata : installation jpp

Mise à jour juillet 2016 pour la version 3 (3.0.1 pour être précis). 
Il faut maintenant installer des choses sérieuses : "make", "wget" et "git" si ce n'est déjà fait ainsi que la triplette "mysql-client","mysql-server" ainsi que "libmysqld-dev" , je fonctionne actuellement avec MariaDB. 
J'ai créé un utilisateur "suricata" avec un mot de passe du même métal pour faire tourner le tout sans droits "root". 
Ensuite télécharger le tar.gz (1.4.1 lors des premiers tests 3.0.1 à ce jour) dans un répertoire tranquille : 
wget http://www.openinfosecfoundation.org/download/suricata-3.0.1.tar.gz ou plus récent visible sur https://oisf.net/ 
suivi d'un : tar -xvf suricata-3.0.1.tar.gz 
Il faut charger quelques dépendances spécifiques :

  • pkg-config
  • libpcap-dev
  • libpcre3-dev
  • libyaml-dev
  • libnet1-dev
  • libcap-ng-dev
  • libmagic-dev
  • libhtp-dev
  • zlib1g-dev
  • libjansson4  libjansson-dev
  • libnfnetlink0 libnfnetlink-dev
  • libnetfilter-queue-1 libnetfilter-queue-dev

Un apt-get install de toute la liste suffit. 
Ensuite le "./configure" magique permet de commencer le travail et le récap en fin d'exécution permet de vérifier si toutes les options nous conviennent :

Suricata Configuration: 
  AF_PACKET support:                       yes 
  PF_RING support:                         no 
  NFQueue support:                         no 
  IPFW support:                            no 
  DAG enabled:                             no 
  Napatech enabled:                        no 
  Unix socket enabled:                     no 
  libnss support:                          no 
  libnspr support:                         no 
  libjansson support:                      no 
  Prelude support:                         no 
  PCRE jit:                                no 
  libluajit:                               no 
  libgeoip:                                no 
  Non-bundled htp:                         no 
  Old barnyard2 support:                   no 
  CUDA enabled:                            no 
  Suricatasc install:                      yes 
  Unit tests enabled:                      no 
  Debug output enabled:                    no 
  Debug validation enabled:                no 
  Profiling enabled:                       no 
  Profiling locks enabled:                 no 
Generic build parameters: 
  Installation prefix (--prefix):          /usr/local 
  Configuration directory (--sysconfdir):  /usr/local/etc/suricata/ 
  Log directory (--localstatedir) :        /usr/local/var/log/suricata/ 
  Host:                                    i686-pc-linux-gnu 
  GCC binary:                              gcc 
  GCC Protect enabled:                     no 
  GCC march native enabled:                yes 
  GCC Profile enabled:                     no 
To build and install run 'make' and 'make install'. 
You can run 'make install-conf' if you want to install initial configuration 
files to /usr/local/etc/suricata/. Running 'make install-full' will install configuration 
and rules and provide you a ready-to-run suricata. 
To install Suricata into /usr/bin/suricata, have the config in 
/etc/suricata and use /var/log/suricata as log dir, use: 
./configure --prefix=/usr/ --sysconfdir=/etc/ --localstatedir=/var/

Pour plus de sécurité (isolation dans un répertoire spécifique) je vais lancer la configuration avec les options suivantes : 
./configure --prefix=/opt/suricata \ 
            --sysconfdir=/opt/suricata/ \ 
            --localstatedir=/opt/suricata/ 
Le log final contient :

Generic build parameters: 
  Installation prefix (--prefix):          /opt/suricata 
  Configuration directory (--sysconfdir):  /opt/suricata/suricata/ 
  Log directory (--localstatedir) :        /opt/suricata/log/suricata/

Ce n'est pas tout à fait ce que je voulais et je corrige "un peu" le Makefile (aux environs de la ligne 245) pour obtenir un "arbre" de répertoires sous /opt/suricata :

e_localstatedir = /opt/suricata/run 
e_logdir = /opt/suricata/log 
e_logfilesdir = /opt/suricata/log/files 
e_magic_file = /usr/share/file/magic 
e_rundir = /opt/suricata/run/ 
e_sysconfdir = /opt/suricata/etc 
e_sysconfrulesdir = /opt/suricata/etc/rules

Je lance enfin le "make" qui se déroule sans ennuis ... de même pour le "make install" ... qui m'installe un arbre de répertoires "convenable", enfin qui me convient, "make install-conf" installe la config de base puis "make install-full"  télécharge et installe un jeu de règles standard. 
Image de mon arbre de répertoires :

drwxrwsr-x  9 root suricata 4096 2013-05-06 14:39 . 
drwxrwsr-x 18 root staff    4096 2013-05-06 13:40 .. 
drwxr-xr-x  2 root suricata 4096 2013-05-07 16:29 bin 
drwxr-xr-x  3 root suricata 4096 2013-05-07 17:09 etc 
drwxr-xr-x  3 root suricata 4096 2013-05-06 14:37 include 
drwxr-xr-x  4 root suricata 4096 2013-05-06 15:10 lib 
drwxrwxr-x  3 root suricata 4096 2013-05-07 17:14 log 
drwxrwxr-x  2 root suricata 4096 2013-05-07 16:07 run 
drwxr-sr-x  3 root suricata 4096 2013-05-06 14:37 share

J'ai donné au user "suricata" les droits "group" sur l'ensemble des répertoires de /opt/suricata et les droits d'écriture sur les répertoires "log" et "run". 
Il faut ensuite réaliser un script de démarrage car je n'en ai pas trouvé de disponible (mon exemplaire est disponible par le lien en bas de page). 
Il faut ensuite légèrement modifier le fichier "etc/suricata.yaml" pour l'adapter à la structure de mes répertoires. J'ai désactivé l'option "fast log" qui consomme trop d'espace pour mes besoins de test sur un portable. J'ai aussi réduit la fréquence de stockage des statistiques à 30 minutes. 
Après le lancement du produit on peut constater l'arrivée de quelques alertes ... mais elles sont au format "Unified2" et donc illisibles il faut utiliser un interface pour les rendre compréhensibles. Le projet conseille "Barnyard2" qui les enregistre dans une base de données (ici Mysql) et que je vais essayer au prochain épisode. 
Le paramétrage du fichier de configuration est très bien expliqué (au moins pour les options "courantes") dans le fichier suricata.yaml. 
Vous trouverez ces fichiers en attachement, mes quelques modifications du fichier YAML sont précédées d'un commentaire #JPP.

Suricata : statistiques

Suricata : statistiques jpp

Une petite statistique (sur 30 jours 26/11/2018 au 26/12/2018) sur les événements "bloqués" par Suricata : 
Tableau statistique 
La grande majorité des rejets (j'utilise "drop" pour la plupart des événements) sont dus à des attaques sur le site WEB, Ces attaques sont, en général, le fait de "script-kiddies" utilisant des outils en kit, en effet on retrouve très souvent les mêmes motifs dans les URL testées. Il y a aussi des attaques ciblées visant un défaut qui vient d'être divulgué, il en existe un actuellement sur /wp-login.php qui revient très souvent depuis début décembre. 
Note 2021 : les accès sur /wp-login.php existent toujours, j'en voit passer plusieurs par jour, tant en HTTPS qu'en HTTP.

Ceci semble prouver qu'une mise à jour régulière des logiciels est importante, je trouve régulièrement référence à des "exploits" adaptés à des versions antérieures à celles installées dans mes systèmes. 
Les attaques sur SMTP sont le plus souvent le fait de spammeurs recherchant des serveurs "open relay", en existe-t-il encore ?

Suricata version 2.0

Suricata version 2.0 jpp

Une nouvelle version (2.0) de Suricata "chauffait" depuis quelques temps et je l'ai chargée et compilée sans aucune nouvelle dépendance. 
Le 25 juin 2014 sortie de la version 2.0.2 : téléchargeable ici. (obsolete en 2017) 
Le 23 septembre 2014 sortie de la version 2.0.4 : téléchargeable ici. (obsolete en 2017) 
La version 2.0.4 se compile et s'exécute comme la version 2.0.2 (même paramétrage). 
A titre indicatif je "configure" avec le script suivant avant de lancer le "make" fatidique : 
#!/bin/bash 
PFX='--prefix=/opt/suricata/ ' 
CFG='--sysconfdir /opt/suricata/etc/ ' 
LOC='--localstatedir=/opt/suricata/var ' 
OPTIONS='--enable-gccprotect --enable-geoip --enable-nfqueue --enable-unix-socket' 
./configure $PFX $CFG $LOC $OPTIONS 2>&1 | tee LOG_CONFIGURE

Les options permettent d'utiliser des filtres "géographiques" et d'utiliser le mode IPS (utilisation de NFQUEUE). 

A première vue le paramétrage existant en 1.4 est parfaitement fonctionnel et le système tourne normalement. Il semble qu'une légère amélioration de performance soit présente, mais cela n'est pas transcendant et de toutes façons je suis limité par la liaison internet sur laquelle le maximum théorique #8Mo/s est atteint régulièrement.

Le fonctionnement en IPS est parfait et la mise en place de quelques "drop" permet de se débarrasser de quelques accès intempestifs. Le seul "manque" est que les "drops" ne laissent pas une trace spécifique dans l'interface de visualisation. De même le fichier "drop.log" ne contient aucune référence à la règle ayant provoqué le rejet et n'est pas affecté à un niveau de danger particulier ce qui est un peu dommage.

Il faut maintenant étudier la doc pour profiter des nouvelles fonctionnalités.

Suricata version 3.0

Suricata version 3.0 jpp

La version 3.0 est, au point de vue de la compilation de de l'utilisation peu différente de la version 2, j'ai mis à jour la page correspondant à l'installation. 
Actuellement Suricata est "en exploitation" chez moi et tourne sur la machine servant de pont vers Internet. 
Le fonctionnement est effectué en mode IPS et permet de bloquer quelques empêcheurs de surfer en rond et de repérer les tentatives d'accès du style "phpmyadmin" ... et d'autres. Au moment de Heartbleed un grand nombre de tentatives d'exploitation étaient visibles. 
La machine dispose de deux interfaces "BR0" (vers le modem) "BR1" vers le réseau interne, les autres machines du réseau accèdent toutes à Internet à travers un switch raccordé à "BR1". Suricata est utilisé en entrée et en sortie, tout est filtré ! 
Snorby permet de consulter l'historique des alertes et permet

  • d'éliminer les  faux positifs,
  • de repérer les tentatives d'accès frauduleux.

Il est intéressant de "marquer" dans l'interface les noms DNS des serveurs "sûrs" afin de passer rapidement des alertes en "faux positif" ou de les détruire quand le responsable est "banni" par le pare-feu.

Suricata 3.0 : quelques tests

Suricata 3.0 : quelques tests jpp

La dernière version de Suricata (3.1.1) à ce jour m'a semblé nettement plus performante que les précédentes et j'ai vu passer quelques téléchargements à très grande vitesse depuis une machine située "derrière" le portail internet. Cette machine a parfois téléchargé à #40Mo/seconde, les sources du noyau en à peine plus de deux secondes ... vive la fibre. Quand je me rappelle le premier chargement de noyau Linux sur mon vieil Amiga 2000 avec un modem 33.6 qui durait des heures pour des sources beaucoup plus petites. La compilation durait 11/12 heures ... aujourd'hui elle passe en moins de 10 minutes environ avec un corei7 !!! 
Un premier test entre deux machines munies de Suricata 3.1.1, un corei3 à 3.3Ghz et un corei5 à 3.5Ghz donnent une vitesse de presque 64Mo/seconde (63.9,63.7,63.8 sur trois essais. Le corei3 utilise 100% de cpu, le corei5 moins de 80%. 
 

A = corei5 5675 3,1GHz    
B = corei3 3220 3,3GHz    
RUNMODE : WORKERS
  Suricata %CPU  
  A B A B Moy MO/s
A → B         113,0
B → A         113,0
A → B oui   101   58,0
B → A oui   102   59,3
A → B   oui   102 60,1
B → A   oui   101 57,3
A → B oui oui 100 100 56,1
B → A oui oui 97 101 56,8
           
           
RUNMODE : AUTOFP
  Suricata %CPU  
  A B A B Moy MO/s
A → B         113,0
B → A         113,0
A → B oui   160   54,1
B → A oui   150   54,3
A → B   oui   155 57,0
B → A   oui   162 53,0
A → B oui oui 150 160 45,8
B → A oui oui 150 160 46,1
           
           
ECARTS % : Workers / AUTOFP
  Suricata %CPU % ecart
  A B A B  
A → B         100,00%
B → A         100,00%
A → B oui       107,34%
B → A oui       109,28%
A → B   oui     105,38%
B → A   oui     108,11%
A → B oui oui     122,40%
B → A oui oui     123,05%

Les valeurs "moyennes" sont la moyenne de trois essais.

On arrive quand même à des résultats intéressants en réel, par exemple le chargement des sources du kernel (sur la machine A reliée directement au routeur Internet) se passe en :

Saving to: ‘linux-4.7.5.tar.xz’ 
linux-4.7.5.tar.xz                  100%[====================================================================>]  86,23M  51,4MB/s   in 1,7s 
Ce qui est très correct, 86Mo en moins de 2 secondes ! Et le même quelques jours après : 
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.7.6.tar.xz

--2016-09-30 23:01:48--  https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.7.6.tar.xz
Resolving cdn.kernel.org (cdn.kernel.org)... 151.101.60.69
Connecting to cdn.kernel.org (cdn.kernel.org)|151.101.60.69|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 90432088 (86M) [application/x-xz]
Saving to: ‘linux-4.7.6.tar.xz’
linux-4.7.6.tar.xz  100%[=====================>]  86,24M  54,0MB/s   in 1,6s   
2016-09-30 23:01:49 (54,0 MB/s) - ‘linux-4.7.6.tar.xz’ saved [90432088/90432088]

Et le 17/10/2016 :

Resolving cdn.kernel.org (cdn.kernel.org)... 151.101.120.69 
Connecting to cdn.kernel.org (cdn.kernel.org)|151.101.120.69|:443... connected. 
HTTP request sent, awaiting response... 200 OK 
Length: 90413036 (86M) [application/x-xz] 
Saving to: ‘linux-4.7.8.tar.xz’

linux-4.7.8.tar.xz  100%[=====================>]  86,22M  57,1MB/s   in 1,5s   2016-10-17 21:31:20 (57,1 MB/s) - ‘linux-4.7.8.tar.xz’ saved [90413036/90413036]

On continue le 13/12/2016 : une version plus loin (3.1.3) la vitesse depuis une machine de "deuxième niveau" (toujours derrière le frontal Internet) :

Saving to: ‘linux-4.9.tar.xz’linux-4.9.tar.xz   100%[==================================>]  88,88M  87,3MB/s    in 1,0s    
2016-12-13 21:05:15 (87,3 MB/s) - ‘linux-4.9.tar.xz’ saved [93192404/93192404] 
J'attends la suite ... que voici

Octobre 2017 :

wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.13.7.tar.xz 
--2017-10-15 13:55:36--  https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.13.7.tar.xz 
Resolving cdn.kernel.org (cdn.kernel.org)... 151.101.121.176, 2a04:4e42:1d::432 
Connecting to cdn.kernel.org (cdn.kernel.org)|151.101.121.176|:443... connected. 
HTTP request sent, awaiting response... 200 OK 
Length: 100594128 (96M) [application/x-xz] 
Saving to: ‘linux-4.13.7.tar.xz’

linux-4.13.7.tar.xz      100%[==================================>]  95,93M   102MB/s    in 0,9s    

2017-10-15 13:55:37 (102 MB/s) - ‘linux-4.13.7.tar.xz’ saved [100594128/100594128]

Saving to: ‘linux-4.13.8.tar.xz’

linux-4.13.8.tar.xz      100%[==================================>]  95,92M   107MB/s    in 0,9s

Ces deux derniers résultats depuis une machine de mon réseau "interne" sur une machine "SSD" only.

Suricata version 4.0

Suricata version 4.0 jpp

La dernière version de Suricata est la 4.0.0 parue au début du quatrième trimestre 2017. J'ai attendu quelque peu avant de l'installer et la 4.0.1 était sortie, c'est donc celle que j'ai installée. 
La compilation et l'installation sont identiques à celles des versions 3.x. Je n'ai pas non plus eu besoin de modifier les fichiers de paramétrage et tout a fonctionné au premier lancement.

J'ai aussi installé la version 4.0.4 de février 2018 sans plus de problèmes. 
 

Snorby Gui alertes

Snorby Gui alertes jpp

Le couple Suricata/Barnyard2 détecte les événements réseau notables et les insère dans une base Mysql/MariaDB. 
C'est bien, mais pour visualiser ces alertes un outil sympa est "Snorby" : c'est une interface WEB très complète et assez agréable à utiliser. Son développement n'étant plus assuré cela risque de poser problème.

Je l'utilise depuis un bon moment et j'ai presque toujours eu des problèmes lors de son installation ou lors de changement de version de système, même en changeant de machine j'ai rencontré des difficultés. 
Quelques articles résument des années d'utilisation. 
Juillet 2018, ce logiciel est toujours en cours d'utilisation ... 
Janvier 2019, Snorby n'a pas supporté les dernières mises à jour du système et je ne suis pas arrivé à le faire refonctionner ... 
J'ai donc réalisé un nouveau logiciel permettant de le remplacer, ainsi est né Snorbis.  qui utilise les mêmes tables alimentées par Barnyard2 que Snorby.
 

Suricata version 4.1

Suricata version 4.1 jpp

Décembre 2018 : Je suis en train de tester la version 4.1 de Suricata. 
La compilation et les premiers tests se sont fort bien passés, la suite bientôt, j'ai profité de ces tests pour valider l'installation de "Snorbis" destiné à remplacer Snorby qui, malheureusement, n'est plus maintenu. 
J'ai perdu pas mal de temps sur ce sujet car je me suis aussi occupé d'un outil destiné à gérer les résultats de Modsec dont je reparlerais plus tard.

Note mars 2019 : cette version fonctionne depuis quelques mois sans encombre.

Snorbis : remplacer Snorby

Snorbis : remplacer Snorby jpp

Cette application sans prétentions présentera :

  1. La même base de données que Snorby en y ajoutant une historisation dans des tables séparées des tables courantes, ainsi seules les anomalies non expliquées sont visibles dans les écrans de contrôle.
  2. Quelques statistiques
  3. Quelques fonctions d'automatisation destinées à simplifier en l'automatisant le traitement des "faux positifs" et des "anomalies normales" telles que les messages causés par une machine Debian effectuant sa mise à jour.

Le principe adopté est de ne pas utiliser de Framework pour limiter les dépendances, seul PHP7 et quelques librairies "de base" sont utilisées dans mes différents traitements. 
Cela avance bien, mais sans aucun framework c'est un peu un travail de fourmi ... Publication prévue pour avril 2020 le temps de peaufiner la doc et d'éradiquer les derniers bugs. 
NOTE février 2021 : Suricata ayant supprimé la sortie "unified2" la base de données "snorby" ne sera donc plus alimentée, je suis en train de mettre au point un petit logiciel (Programme Python) pour alimenter une base équivalente et utiliser cette application légèrement modifiée. 
Voir quelques écrans

OSSEC

OSSEC jpp

 
OSSEC installation et usage. 
Ossec est un HID qui semble très complet, de conception assez récente il est actuellement détenu par une société privée (Trend Micro) qui propose une version libre et une version professionnelle. 
OSSEC n'est pas un logiciel très compliqué (au moins extérieurement) mais l'installation est un peu complexe car le produit n'est pas intégré dans une distribution et il faut résoudre soi même les problèmes de compatibilité (voir plus loin le problème posé lors d'un upgrade de version Debian). 
Mais les fonctionnalités sont engageantes et j'ai eu envie de le voir à l'oeuvre.

Note 2016 : le produit est toujours actif en version 2.8 et l'interface "Analogi" fonctionne toujours bien qu'il génère des messages d'erreur PHP dans les logs Apache. 

Note 2018 : Le passage de OSSEC en version 2.9.3 s'accompagne d'une modification du schéma de la base de données Mysql et Analogi devient impossible à utiliser (multiples erreur SQL). 
J'ai trouvé une version "compatible" utilisant Analogi comme fondation mais entièrement "revampée". Malheureusement cette version téléchargeable sur https://github.com/NunesGodinho/OSSEC-WUI n'est pas non plus adaptée aux versions >= 2.9.2. 
Je suis en train de reprendre cette version comme base et de l'adapter au schéma de la base de OSSEC 2.9.3 en y ajoutant quelques fonctionnalités : statistiques, mise à jour du mapping des signatures / catégories, authentification ... 
Cette version est aujourd'hui prête (voir ici un groupe d'articles avec copies d'écrans) et est diffusée sur github elle a été testée sur OSSEC V3.0.0 stable dont la structure de base de données est compatible.

Note 2021 : Fonctionnement en version 3.2 
Depuis la panne du serveur réparée en septembre je n'ai pas eu le loisir de réinstaller OSSEC ... 
Mais j'y pense.

Note 2023 : Je pense réinstaller la version 3.6 dès que possible et présenter les nouvelles fonctionnalités, notamment OSSEC+.

OSSEC : la vie avec OSSEC

OSSEC : la vie avec OSSEC jpp

La vie avec OSSEC est assez facile, le produit est, d'origine, très bien paramétré. Les options fournies par défaut permettent déjà une analyse très fine des événements qui se passent dans vos machines. 
J'ai fait les tests avec : 
- un ossec serveur sur une Centos 5.5 
- un agent Windows sur une machine XP 
- un agent Linux sur une machine Debian. 
L'installation étant détaillée par ailleurs je n'y reviendrais pas, la bonne chose est que pour un petit réseau (moins de 10 machines) il n'y a pas besoin de retoucher le paramétrage. Le système est parfois un peu bavard (pas mal de mails) mais toutes les informations sont là : 
- les "login", on s'intéressera surtout aux login refusés ... 
- les fichiers modifiés (attributs, taille ....), certains fichiers sont peut-être superflus, mais on s'y habitue. 
- l'installation de logiciels est parfaitement repérée, que ce soit pas "yum update" ou "apt-get upgrade". 

Pour la partie interface Web, qui paraît un peu "spartiate au début", on peut faire rapidement un grand nombre d'interrogations ciblées : 
- y-a-t-il eu des tentatives de connexion multiples 
- Quels comptes ont été modifiés 
Les principaux critères de sélection sont (d'autres sont disponibles tels que le numéro de la règle ayant repéré l'erreur) : 
- fourchette date/heure

OSSEC : installation

OSSEC : installation jpp

Note : cet article est ancien (historique presque) voir la dernière version ici. 
L'installation pour tests a été faite sur une machine Centos 5.5 virtualisée avec XEN. 
Après récupération des sources (pour moi version 2.4.1) et détarage dans un répertoire d'installation il suffit de lancer le script "install.sh" 
Après le choix de la langue (fr pour moi) un récapitulatif de votre système s'affiche 
=====================================================================

OSSEC HIDS v2.4.1 Script d'installation - http://www.ossec.net 
  
 Vous êtes sur le point d'installer OSSEC HIDS. 
 Vous devez avoir une compilateur C préinstallé sur votre système. 
 Si vous avez des questions ou des commentaires, envoyez un email 
 à dcid@ossec.net (ou daniel.cid@gmail.com). 
  
  - Système: Linux machine.domaine 2.6.18-194.3.1.el5 
  - Utilisateur: root 
  - Hôte: machine.domaine 


  -- Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler. --

====================================================================== 
On appuye bien sûr sur entrée ... et l'on doit alors choisir l'option d'installation entre : 
serveur    serveur d'analyse OSSEC 
agent    agent transmettant à un serveur     
local    machine indépendante 
Pour cette première approche je choisis "local" 
Pour le répertoire d'installation je garde "/var/ossec". Je configure les alertes par Email et saisis une adresse mail valide en précisant le serveur de mail à utiliser (localhost) puisque j'ai un serveur Postfix local. 
Je précise ensuite que je veux démarrer le démon de controle d'intégrité et le moteur de détection de rootkit. 
=======================================================================

1- Quel type d'installation voulez-vous (serveur, agent, local ou aide) ? local 

  - Installation en local choisie. 

2- Définition de l'environnement d'installation. 

 - Choisissez votre répertoire d'installation de OSSEC HIDS [/var/ossec]: 

    - L'installation sera faite sur  /var/ossec . 

3- Configuration de OSSEC HIDS. 

  3.1- Voulez-vous une alerte par email ? (o/n) [o]: o 
   - Quel est votre adresse email ? xxxxxx@xxxxxx 
   - Quel est l'adresse IP ou le nom d'hôte de votre serveur SMTP ? localhost 

  3.2- Voulez-vous démarrer le démon de vérification d'intégrité ? (o/n) [o]: o 

   - Lancement de syscheck (démon de vérification d'intégrité). 

  3.3- Voulez-vous démarrer le moteur de détection de rootkit ? (o/n) [o]: o 
  3.4- La réponse active vous permet d'éxécuter des commandes 
       spécifiques en fonction d'évènement. Par exemple, 
       vous pouvez bloquer une adresse IP ou interdire 
       l'accès à un utilisateur spécifique. 
       Plus d'information sur : 
       http://www.ossec.net/en/manual.html#active-response 
        
   - voulez-vous démarrer la réponse active ? (o/n) [o]: o 
   - Par défaut, nous pouvons activer le contrôle d'hôte 
     et le pare-feu (firewall-drop). Le premier ajoute 
     un hôte dans /etc/hosts.deny et le second bloquera 
     l'hôte dans iptables (sous linux) ou dans ipfilter 
     (sous Solaris, FreeBSD ou NetSBD). 
   - Ils peuvent aussi être utilisés pour arrêter les scans 
     en force brute de SSHD, les scans de ports ou d'autres 
     formes d'attaques. Vous pouvez aussi les bloquer par 
     rapport à des évènements snort, par exemple. 

   - Voulez-vous activer la réponse pare-feu (firewall-drop) ? (o/n) [o]: o 
     - pare-feu (firewall-drop) activé (local) pour les levels >= 6 

   - liste blanche (white list) par défaut pour la réponse active : 
      - 192.168.1.x 
      - 192.168.1.y 

   - Voulez-vous d'autres adresses IP dans votre liste (white list) ? (o/n)? [n] o

============================================================================= 
J'ajoute ici les adresses IP que je ne veux pas voir bannir lors des tests ... 
=============================================================================

3.6- Mise en place de la configuration pour analyser les logs suivants : 
    -- /var/log/messages 
    -- /var/log/secure 
    -- /var/log/maillog 

 - Si vous voulez surveiller d'autres fichiers, changez 
   le fichier ossec.conf en ajoutant une nouvelle valeur 
   de nom de fichier local. 
   Pour toutes vos questions sur la configuration, 
   consultez notre site web http://www.ossec.net . 
    
    
   --- Appuyez sur Entrée pour continuer ---

============================================================================= 
Ensuite la compilation commence et est très courte . 
=============================================================================

- Configuration correctement terminée. 

 - Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 

 - Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 

 - La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 


    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 

    Plus d'information peut être trouver sur http://www.ossec.net 

    ---  Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). ---

============================================================================= 
Un script de démarrage "/etc/init.d/ossec" a été ajouté et activé correctement dans la machine. 
Un petit reboot pour valider le tout et ça repart, on peut au passage voir le démarrage de OSSEC. Un premier mail de lancement est aussitôt envoyé, c'est une alerte de niveau 3 (les niveaux vont de 1 à 15, 15 étant l'alerte maxi) me signalant le démarrage du démon : 
OSSEC HIDS Notification. 
2010 Jun 29 14:06:13 
Received From:machine.domaine->ossec-monitord 
Rule: 502 fired (level 3) -> "Ossec server started." 
Portion of the log(s): 
ossec: Ossec started. 
--END OF NOTIFICATION 

Je me connecte en "root" sur la machine, nouvelle alerte de niveau 4 cette fois. 
Je me connecte avec un autre utilisateur cela déclenche un nouveau mail de "first time user logged in". Une autre connexion avec le même utilisateur ne déclenche aucun mail. Tout cela semble bel et bon. 
 

OSSEC : Mysql

OSSEC : Mysql jpp

Après l'installation qui se passe très simplement et la vérification de l'installation (cf article précédent) il va falloir tester ce logiciel, ce qui peut prendre un certain temps ! 
J'avais malheureusement oublié d'installer le support MYSQL, j'ai du réaliser une petite manipulation pour activer le support Mysql et relancer l'installation. 
Activation du support Mysql :

  • Charger la bibliothèque de développement ((mysql-devel.i386 sur Centos)
  • aller dans le répertoire "src" de l'installateur et lancer la commande 
    make setdb

Qui réponds gentiment : 
============================================================ 
Error: PostgreSQL client libraries not installed. 
Info: Compiled with MySQL support. 
============================================================ 
Il faut ensuite relancer le script "install.sh", 
Après avoir choisi le français, je choisis de mettre à jour mon installation ainsi que les règles. La compilation démarre  ... et se termine par l'installation.

 ........ 
OSSEC HIDS v2.4.1 Stopped 
Starting OSSEC HIDS v2.4.1 (by Trend Micro Inc.)... 
Started ossec-maild... 
Started ossec-execd... 
Started ossec-analysisd... 
Started ossec-logcollector... 
Started ossec-syscheckd... 
Started ossec-monitord... 
Completed. 
 - Configuration correctement terminée. 
 - Pour démarrer OSSEC HIDS: 
                /var/ossec/bin/ossec-control start 
 - Pour arrêter OSSEC HIDS: 
                /var/ossec/bin/ossec-control stop 
 - La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 
    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 

    Plus d'information peut être trouver sur http://www.ossec.net 
    ---  Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). --- 
 - Mise à jour complète.

Il faut ensuite s'occuper de la base de données :

  • Créer la base
  • Créer l'utilisateur
  • Donner les droits adéquats à l'utilisateur sur la base
  • Créer le schéma en allant dans le répertoire d'installation puis dans "src/os_dbd" où un fichier "mysql.schema" n'attends que votre bon vouloir et la commande :

mysql --user=le_user --password=le_password -D la_base <mysql.schema

Après contrôle 8 tables sont créées dans le schéma. 
Il est temps d'aller ajouter le paramétrage qui va bien dans le fichier (xml) de configuration de OSSEC. Il suffit d'ajouter en tête du fichier /var/ossec/etc/ossec.conf le petit bout de XML suivant :

<ossec_config> 
  <database_output> 
    <hostname>le_host</hostname> 
    <port>3306</port> 
    <username>ossec_user</username> 
<password>ossec_password</password> 
    <database>ossec_database</database> 
    <type>mysql</type> 
  </database_output> 
</ossec_config>

Exécuter avec ferveur l'incantation suivante :

  1. /var/ossec/bin/ossec-control enable database
  2.  Stopper et relancer le service.

L'enregistrement est alors effectué dans la base Mysql (Postgresql est aussi admis). 
Petite remarque : l'installation crée de nouveaux utilisateurs et un groupe "ossec" et la plupart des process ne tournent pas avec les privilèges de "root" ce qui est un gage de stabilité/sécurité. 
  
Tests en cours .... la suite au prochain article.

OSSEC : Interface WEB

OSSEC : Interface WEB jpp

Note 2019, il est possible d'utiliser la version décrite ici comme interface avec OSSEC.

Récupérer l'archive "ossec-wui....", pour moi la version 0.3, la détarer dans un répertoire tranquille. Il suffit ensuite de recopier le nouveau répertoire ossew-wui-0.3 dans l'arborescence WEB, pour moi /var/www/ossec-wui-0.3. 
Il faut ensuite ajouter le groupe "ossec" à l'utilisateur sous lequel Apache est lancé (apache pour Centos, www-data pour Debian). 
Il faut ensuite se rendre dans le répertoire /var/www/ossec... et y lancer le script de configuration "setup.sh" :

[root@xxxxxxx ossec-wui-0.3]# ./setup.sh 
Setting up ossec ui... 
Username: xxxxxx 
New password:  
Re-type new password:  
Adding password for user xxxxxx 
Setup completed successfuly.

Dans /var/www j'ai ensuite fait un lien ossec-wui-0.3 --> ossec puis dans le répertoire /etc/httpd/conf.d j'ai ajouté le fichier suivant :

<Directory "/var/www/ossec"> 
    Options Indexes 
    AllowOverride None 
    Order allow,deny 
    Allow from all 
</Directory>

On relance Apache et l'accès est ensuite direct par http://localhost/ossec. 
Quelques images de l'interface Web (un peu "rude") mais qui semble assez commode pour les recherches. 
Image 1 : vue lors de l'accès 
 

Image 2 : critères de recherche : 
 

Cette interface se révèle assez commode pour les recherches.

OSSEC : Installation serveur

OSSEC : Installation serveur jpp

Si comme moi vous trouvez OSSEC "pas mal" vous pouvez installer des agents sur d'autres machines, pour cela il vous suffira de modifier votre machine originale en mode "serveur". 
Note juillet 2018 : cette version est aujourd'hui obsolete, voir l'article sur la version 3.0.0 stable. 
Il faut malheureusement détruire son installation existante et refaire une installation. 
Détruire les éléments suivants : 
/var/ossec 
/etc/ossec-init.conf 
/etc/init.d/ossec 
et 
./rc.d/rc2.d/S99ossec 
./rc.d/rc0.d/K15ossec 
./rc.d/rc4.d/S99ossec 
./rc.d/rc1.d/K15ossec 
./rc.d/rc5.d/S99ossec 
./rc.d/rc6.d/K15ossec 
./rc.d/rc3.d/S99ossec 
Il suffit alors comme d'habitude de se rendre dans le répertoire d'installation et de lancer l'inévitable "install.sh". 
Si vous désirez utiliser le stockage dans une base Mysql, n'oubliez pas d'activer la fonctionnaité "Mysql" (voir article). 
On choisit la langue, et on frappe "Entrée" sur l'invite ... 
======================================================================

... /... 
 -- Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler. -- 
1- Quel type d'installation voulez-vous (serveur, agent, local ou aide) ? serveur 
  - Installation du serveur choisie. 
2- Définition de l'environnement d'installation. 
  - Choisissez votre répertoire d'installation de OSSEC HIDS [/var/ossec]: 
    - L'installation sera faite sur  /var/ossec . 
3- Configuration de OSSEC HIDS. 
  3.1- Voulez-vous une alerte par email ? (o/n) [o]: o 
   - Quel est votre adresse email ? toto@monserveur 
   - Quel est l'adresse IP ou le nom d'hôte de votre serveur SMTP ? 192.168.1.xxx 
  3.2- Voulez-vous démarrer le démon de vérification d'intégrité ? (o/n) [o]: O 
   - Lancement de syscheck (démon de vérification d'int&grité). 
  3.3- Voulez-vous démarrer le moteur de détection de rootkit ? (o/n) [o]: O 
   - Lancement de rootcheck (détection de rootkit). 
  3.4- La réponse active vous permet d'éxécuter des commandes 
       spécifiques en fonction d'événement. Par exemple, 
       vous pouvez bloquer une adresse IP ou interdire 
       l'accès à un utilisateur spécifique. 
       Plus d'information sur : 
       http://www.ossec.net/en/manual.html#active-response 
   - voulez-vous démarrer la réponse active ? (o/n) [o]: O 
     - Réponse active activée. 
     - Par défaut, nous pouvons activer le contrôle d'hôte 
     et le pare-feu (firewall-drop). Le premier ajoute 
     un hôte dans /etc/hosts.deny et le second bloquera 
     l'hôte dans iptables (sous linux) ou dans ipfilter 
     (sous Solaris, FreeBSD ou NetSBD). 
   - Ils peuvent aussi être utilisés pour arrêter les scans 
     en force brute de SSHD, les scans de ports ou d'autres 
     formes d'attaques. Vous pouvez aussi les bloquer par 
     rapport à des événements snort, par exemple. 
   - Voulez-vous activer la réponse pare-feu (firewall-drop) ? (o/n) [o]: o 
    - liste blanche (white list) par défaut pour la réponse active : 
      - 192.168.2.xxx 
      - 192.168.2.xxx 
   - Voulez-vous d'autres adresses IP dans votre liste (white list) ? (o/n)? [n]: o 
   - IPs (séparées par des espaces) : 192.168.1.xxx 
  3.5- Voulez-vous activer fonctionnalités syslog (port udp 514) ? (o/n) [o]: n 
   --- Fonctionnalité syslog désactivée. 
  3.6- Mise en place de la configuration pour analyser les logs suivants : 
    -- /var/log/messages 
    -- /var/log/secure 
    -- /var/log/maillog 
    -- /var/log/httpd/error_log (apache log) 
    -- /var/log/httpd/access_log (apache log) 
 - Si vous voulez surveiller d'autres fichiers, changez 
   le fichier ossec.conf en ajoutant une nouvelle valeur 
   de nom de fichier local. 
   Pour toutes vos questions sur la configuration, 
   consultez notre site web http://www.ossec.net . 
   
... ... ... la compil se passe ... ... ... 
  
 - Le Système est Redhat Linux. 
 - Script d'initialisation modifié pour démarrer OSSEC HIDS pendant le boot. 
 - Configuration correctement terminée. 
 - Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 
 - Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 
 - La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 
    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 
    Plus d'information peut être trouver sur http://www.ossec.net 
    ---  Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). --- 
 - Vous devez ajouter le(s) agent(s) avant qu'ils aient un accès autorisé. 
   Lancez 'manage_agent' pour les ajouter ou les supprimer: 
   /var/ossec/bin/manage_agents 
   Plus d'information sur: 
   http://www.ossec.net/en/manual.html#ma

==================================================================== 
Dès le service lancé on constate l'ouverture d'un port en écoute : 
lsof -Pn | grep UDP | grep oss 
ossec-rem 5859    ossecr    4u     IPv4     152930                 UDP *:1514  
après avoir démarré un poste muni d'un agent on peut voir dans le log de celui-ci la trace de la connection au serveur OSSEC (/var/ossec/logs/ossec.log) : 
2010/06/30 14:24:03 ossec-agentd(4102): INFO: Connected to the server (192.168.1.124:1514). 
2010/06/30 14:29:37 ossec-syscheckd: INFO: Finished creating syscheck database (pre-scan completed). 

Pour le reste du fonctionnement il est identique à celui de la version locale.

OSSEC : installation agent Linux

OSSEC : installation agent Linux jpp

Installation d'un agent sur une machine Linux, ici une distribution Debian, l'installation se fait à  partir des sources car il n'existe pas de paquet(s) Debian pour OSSEC. Les sources sont les mêmes que pour toute version Linux/Unix. 
Après détarage de l'archive on se rends dans le répertoire "ossec-hids-2.4.1" et on lance le script "install.sh". 
Je viens d'intégrer une nouvelle machine dans le système en version 2.7.1 sans aucun problème, les srcipts de comportent de manière identique. 
Après le choix de la langue (fr pour moi) un récap du système s'affiche, Entrée pour continuer : 
===================================================================

1- Quel type d'installation voulez-vous (serveur, agent, local ou aide) ? agent 
   - Installation de l'agent (client) choisie. 
  2- Définition de l'environnement d'installation. 
  - Choisissez votre répertoire d'installation de OSSEC HIDS [/var/ossec]: 
    - L'installation sera faite sur  /var/ossec . 
  3- Configuration de OSSEC HIDS. 
  3.1- Quelle est l'adresse IP de votre serveur OSSEC HIDS ?: 192.168.1.xxx 
   - Ajout de l'IP du Serveur 192.168.1.xxx 
  3.2- Voulez-vous démarrer le démon de vérification d'intégrité ? (o/n) [o]: o 
   - Lancement de syscheck (démon de vérification d'intégrité). 
  3.3- Voulez-vous démarrer le moteur de détection de rootkit ? (o/n) [o]: o 
   - Lancement de rootcheck (détection de rootkit). 
  3.4 - voulez-vous démarrer la réponse active ? (o/n) [o]: o 
  3.5- Mise en place de la configuration pour analyser les logs suivants : 
    -- /var/log/messages 
    -- /var/log/auth.log 
    -- /var/log/syslog 
    -- /var/log/xferlog 
    -- /var/log/mail.info 
    -- /var/log/squid/access.log 
    -- /var/log/dpkg.log 
    -- /var/log/snort/alert (snort-full file) 

 - Si vous voulez surveiller d'autres fichiers, changez 
   le fichier ossec.conf en ajoutant une nouvelle valeur 
   de nom de fichier local. 
   Pour toutes vos questions sur la configuration, 
   consultez notre site web http://www.ossec.net . 
   --- Appuyez sur Entrée pour continuer --- 
====================================================================== 
La compilation démarre et l'installation s'enchaîne pour se terminer en beauté ... 
====================================================================== 
 - Le Système est Debian (Ubuntu or derivative). 
 - Script d'initialisation modifié pour démarrer OSSEC HIDS pendant le boot. 
 - Configuration correctement terminée. 
 - Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 
 - Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 
  - La configuration peut ếtre visualisée ou modifiée dans /var/ossec/etc/ossec.conf 
    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 

    Plus d'information peut ếtre trouver sur http://www.ossec.net 
    ---  Appuyez sur Entrée pour finir (peut-être plus d'info plus bas). --- 
... ... ... 
 - Vous devez d'abord ajouter cet agent sur le serveur pour 
   qu'ils communiquent entre eux. Quand cela sera fait, 
   vous pourrez lancer l'outil 'manage_agents' pour 
   importer la clef d'authentification depuis le serveur. 
   /var/ossec/bin/manage_agents 
   Plus d'information sur: 
   http://www.ossec.net/en/manual.html#ma

======================================================================= 
Il faut ensuite se rendre sur le serveur pour "ajouter" l'agent à  l'aide de la commande "/var/ossec/bin/manage_agents" : 
=======================================================================

 /var/ossec/bin/manage_agents 
**************************************** 
* OSSEC HIDS v2.4.1 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: A 
- Adding a new agent (use '\q' to return to the main menu). 
  Please provide the following: 
   * A name for the new agent: com-k400 
   * The IP Address of the new agent: 192.168.1.xxx 
   * An ID for the new agent[001]: 001 
Agent information: 
   ID:001 
   Name:xxxxxxxxx 
   IP Address:192.168.1.xxx 
Confirm adding it?(y/n): y 
Agent added. 
**************************************** 
* OSSEC HIDS v2.4.1 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: q 
** You must restart the server for your changes to have effect. 
manage_agents: Exiting ..

=================================================================== 
On redémarre le service OSSEC sur le serveur et ... pas de message. 
Les échanges étant authentifiés il faut ensuite procéder à  l'échange de clefs qui se fait par le même outil, sur le serveur : 
=====================================================================

 /var/ossec/bin/manage_agents 
**************************************** 
* OSSEC HIDS v2.4.1 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: E 
Available agents: 
   ID: 001, Name: com-k400, IP: 192.168.1.60 
Provide the ID of the agent to extract the key (or '\q' to quit): 001 
Agent key information for '001' is: 
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
** Press ENTER to return to the main menu.

===================================================================== 
Sur l'agent on lance l'outil de management et on copiera la clef : 
=====================================================================

/var/ossec/bin/manage_agents 
**************************************** 
* OSSEC HIDS v2.4.1 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (I)mport key from the server (I). 
   (Q)uit. 
Choose your action: I or Q: I 
* Provide the Key generated by the server. 
* The best approach is to cut and paste it. 
*** OBS: Do not include spaces or new lines. 
Paste it here (or '\q' to quit): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Agent information: 
   ID:001 
   Name:xxxxxxxxx 
   IP Address:192.168.2.xxx 
Confirm adding it?(y/n): y 
Added. 
** Press ENTER to return to the main menu.

======================================================================= 
on peut alors démarrer le service sur la machine dont on vient d'installer l'agent. 
======================================================================= 
./ossec start 
Starting OSSEC HIDS v2.4.1 (by Trend Micro Inc.)... 
Started ossec-execd... 
Started ossec-agentd... 
Started ossec-logcollector... 
Started ossec-syscheckd... 
Completed. 
==========================================================================

OSSEC : sur un "vrai" serveur

OSSEC : sur un "vrai" serveur jpp

Je n'ai pas pu tenir et disposant de quelques temps j'ai décidé de tenter l'installation de OSSEC sur mon serveur de mail. 
C'est un serveur permanent (basse consommation cf ) qui supporte déjà plein de trucs, mais c'est la seule machine en fonctionnement continu et donc apte à gérer les agents à déposer dans les autres machines. Comme c'est aussi la passerelle vers Internet, elle doit être particulièrement surveillée. 
Installer le logiciel serveur. 
Installer le support MYSQL : 
cd ..../ossec.../src 
make setdb 
Error: PostgreSQL client libraries not installed. 
Info: Compiled with MySQL support. 
Installer "libz et libz-devel" par un petit coup de "apt-get install zlib1g zlig1g-dev ". 
Il ne reste plus alors qu'à lancer la procédure d'installation. 
./install.sh 
Qui se déroule avec un petit problème car gcc me dit méchamment qu'il ne reconnait pas le switch "-R". 
Sur cette machine est installé "ZIMBRA" (Serveur mail et webmail) et ,je ne sais pas pourquoi, toutes les définitions de répertoires de librairies (par exemple : -L/usr/lib) étaient préfixés -R/usr/lib, ce qui m'a obligé à mettre un "front end" bidon pour "gcc" dont voici le script (facile !) : 
========================================================= 
#!/bin/bash 
PARAM=`echo $* |  sed 's\ /-R/\ -L/g'`  
/usr/bin/gcc $PARAM 
========================================================== 
C'est tout et la compilation se termine bien. On passe alors à la partie Mysql :

  • Créer un utilisateur dans la base MySql, c'est facile avec mysql-admin.
  • Créer le schéma de base de données,
  • Donner les droits adéquats au user
  • Lancer le script de création des tables : 
    cd .../ossec..../src/dbd_os 
    mysql --user=osssec_user --password=ossec_mot_de_passe -D nom_de_la_base <mysql.schema
  • Ajouter dans /var/ossec/etc/ossec.conf le morceau (choisi) juste après "<ossec_config>" et avant <global> : 
     <database_output> 
       <hostname>localhost</hostname> 
       <port>3306</port> 
       <username>ossec_user</username> 
       <password>ossec_mot_de_passe</password> 
       <database>ossec_base</database> 
       <type>mysql</type> 
    </database_output>
  • Surtout ne pas oublier l'incantation à "/var/ossec/bin/ossec-control enable database"   avant de lancer le service.


Installer l'interface WEB

  • Décompresser l'archive dans "/var/www"
  • Aller dans le répertoire "/var/www/ossec_......"  pour exécuter le script "setup.sh"
  • Ne pas oublier (comme moi la première fois), d'affecter le user de lancement de Apache (www-data pour Debian) dans le groupe "ossec" (et redémarrer Apache), sinon vous n'obtiendrez que des messages d'insulte de type "access denied" ou au mieux un message "No agent available" dans l'interface alors même que le mails sont émis normalement et que tout semble baigner.
  • Mettre en place le petit fichier de déclaration pour Apache (/etc/apache2/conf.d pour Debian, /etc/httpd/conf.d pour les redhat like) :

# 
# This configuration file allows the manual to be accessed at  
# http://localhost/ossec/ 
# 
AliasMatch ^/ossec(?:/(?:de|en|fr|ja|ko|ru))?(/.*)?$ "/var/www/ossec$1" 
<Directory "/var/www/ossec"> 
    Options Indexes 
    AllowOverride None 
    Order allow,deny 
    Allow from all 
</Directory> 

Tester le résultat. 
Premier lancement. 
C'est horrible ! Tous les messages inscrits par ZIMBRA dans "/var/log/syslog ou /var/log/messages" déclenchent un mail d'anomalie de quoi saturer rapidement une boite mail. Je stoppe donc rapidement le service OSSEC. 
Après une petite réflexion un plan d'action se dessine : 
Actions à réaliser : 
1) modifier les paramètres de rsyslog dasn "/etc/rsyslog.conf" (utilisé par défaut sur ce serveur)

  • la ligne  : *.*;auth,authpriv.none        -/var/log/syslog 
    devient  :  *.*;auth,authpriv.none,mail,local0,local1    -/var/log/syslog
  • la ligne  : mail,news.none        -/var/log/message  
    devient  :      mail,news.none;\ 
    local0,local1;            -/var/log/messages

Ainsi les traces de ZIMBRA devraient être supprimées des logs "standard" et ne plus polluer les détections d'anomalies. Mais en contrepartie les actions de ZIMBRA ne seront plus analysées. 
2) Chercher un moyen d'analyser les logs de ZIMBRA. Il faut pour cela créer un nouveau "parser" capable d'analyser les logs de Zimbra. 
Heureusement Internet est là (http://www.zimbra.com/forums/administrators/39764-ossec-rules.html) et on y trouve exactement ce qu'il nous faut. 
Le gars qui a écrit ces règles a l'air de savoir de quoi il parle, je lui fait donc confiance et intègre ces règles là ou il est dit de le faire. 
Deuxième lancement. 
C'est le pied ... les messages de Zimbra ne polluent plus les détections ... si, il reste une source de mails intempestifs, c'est l'analyse du fichier "auth.log" où les "sudo .... " de Zimbra génèrent encore une palanquée d'anomalies (deux ou trois toutes les deux minutes) il faut donc faire quelque chose car je veux pas traiter plus de 1000 messages par jour ! 
Là aussi un peu de réflexion et beaucoup de lecture de la doc (RTFM) permettent d'entrevoir une solution : 
Modifier le comportement d'une règle standard. Cette possibilité est géniale et permet de traiter sans problème, et avec élégance,  des cas particuliers. C'est un gros plus de OSSEC par rapport à d'autres outils. 
Il suffit de créer une règle (avec la plage de numérotation qui va bien (100000 à 110000) ). Je crée donc une règle "101001" qui référence la règle 5402 (if_sid) qui me cause des ennuis et ajoute une contrainte spécifique (match), si cette règle "matche" alors le niveau de l'erreur est ramené à zéro (pas d'erreur). Et ceci s'écrit : 
 <rule id="101001" level="0"> 
    <if_sid>5402</if_sid> 
    <match>COMMAND=/opt/zimbra/libexec/zmm</match> 
    <description>Kill ZIMBRA SUDO </description> 
 </rule>

Traduction : Si la règle 5402 est levée (les messages indiquent toujours le numéro de la règle qui les a déclenchés) et si la ligne "offensante" de log comporte la chaine "COMMAND=/opt/zimbra/libexec/zmm" alors le niveau d'erreur sera zéro. 
A ajouter dans le groupe de règles dans lequel on a déjà intégré les règles "zimbra" du site mentionné au dessus. 
Je ne suis pas un grand amateur de XML, mais à ce niveau là j'arrive à suivre. 
On redémarre le service et on attend un peu pour voir si la modification est efficace. Après plusieurs minutes pas un seul mail à ce sujet, c'est gagné. Vite un petit test avec un autre "sudo" et ... il apparait dans la liste, c'est donc vraiment gagné. 
Quelques messages générés par AMAVIS attirent mon attention, mais il ne s'agit "que" du traitement d'un mail dont l'adresse mail comporte le mot "error" ! 
Le stockage des données dans la base Mysql est réalisé avec un modèle de données simple qui promet une grande facilité de réalisation de requêtes ciblées. Ces requêtes sont surtout intéressantes dans un réseau important, mais ici on doit pouvoir effectuer quelques tests facilement. 
L'interrogation avec "Mysql-browser" est facile car on accède immédiatement aux messages, obtenir la liste des connexions par machine et/ou par utilisateur sera super simple. 
Quelques messages du firewall apparaissent, d'autres de "SNORT" : avec quelques " Destination Unreachable Communication with Destination Host is Administratively Prohibited [**][Classification: Misc activity] [Priority: 3] ". 
En bref, après mes tests sur des machines virtuelles, cela marche assez bien dans le monde réel (a quelques adaptations faciles près) en promettant de pas noyer un pauvre administrateur sous un tas de fausses alertes.

OSSEC : la vie en vrai

OSSEC : la vie en vrai jpp

J'ai donc installé OSSEC sur un serveur "réel" et je l'ai laissé fonctionner quelques temps sans toucher au paramétrage. 
Sur ce même serveur tournent quelques outils de sécurité (AIDE et TIGER), Je vais pouvoir comparer les résultats. 
Le plus de OSSEC est le signalement rapide par mail des problèmes. Une détection par l'IDS (Snort) est signalée rapidement. 
Après un ou deux jours j'ai constaté que la surveillance de certains répertoires n'était pas installée par défaut, seuls les répertoires "etc" et la gamme des "bin" étaient surveillés, j'y ai donc ajouté (fichier /var/ossec/etc/ossec.conf) les répertoires "/lib" et "/usr/lib". 
Les lignes considérées sont actuellement les suivantes : 
   <directories check_all="yes">/etc,/usr/bin,/usr/sbin</directories> 
   <directories check_all="yes">/bin,/sbin,/lib,/usr/lib</directories> 
J'attends les résultats des prochains passages. 
J'ai aussi essayé de mettre sous surveillance le serveur FTP (proftpd) car il existe des éléments de configuration prévus pour lui mais mis en commentaires. Je les ai donc activés et, là aussi, j'attends les résultats, il suffit qu'un petit malin vienne "titiller" ce FTP pour que je puisse vérifier si la détection est correcte. 
On pourra alors voir si la "réponse active" bloque bien les IP de ces offenseurs. 
 

OSSEC : après quelques semaines

OSSEC : après quelques semaines jpp

Après quelques semaines la vie avec OSSEC se passe très bien. Le nombre de messages n'est pas très élevé, sauf lors de mises à jour logicielles sur l'une des machines. Celle-ci déclenche en effet un certain nombre de messages pour : 
- la mise à jour elle-même (détection sur dpkg.log) 
- la modification des programmes (changement de l'empreinte) 
Les messages surviennent très rapidement après la mise à jour et, très souvent, les messages groupent un certain nombre de modifications ce qui réduit fortement leur nombre. 
On voit rapidement les tentatives d'accès indues, tous les "rigolos" qui essayent de forcer votre mot de passe SSH... ils essayent en général les users "Administrator" ou parfois "Administrateur", C'est bizarre celà me dit quelque chose ce genre de user... 
Toutes les erreurs de connexion, avec les mots de passe à la gomme qu'on est obligé d'utiliser il est vite fait de se mélanger les doigts et de frapper un mot de passe erroné. 
De même les tentatives d'accès sur le serveur FTP sont signalées et, en prime, OSSEC bloque l'IP correspondante pendant un temps paramétrable (600 secondes par défaut). 
La machine OSSEC étant aussi ma passerelle Internet il faut soigneusement mettre en "White list" les machines du réseau interne car si elles font des choses non prévues (ou "vilaines") leur IP est bloquée assez rapidement. 
J'ai ainsi constaté qu'un simple "apt-get update" va chercher des fichiers qui n'existent pas sur les serveurs et le proxy SQUID note soigneusement ces accès "loupés" ce qui déclenche un message et le blocage de l'IP "fautive", la White List est ici la bienvenue. 
Exemple de message OSSEC : 

OSSEC HIDS Notification.2010 Sep 14 23:29:39 
Received From: xxxxx->syscheck 
Rule: 550 fired (level 7) -> "Integrity checksum changed." 
Portion of the log(s): 
Integrity checksum changed for: '/etc/bind/db.192.1' 
Size changed from '1603' to '1657' 
Ownership was '0', now it is '105' 
Old md5sum was: '99bd18192e46198c2330a2f4b715fd00' 
New md5sum is : '146b5b6ddd094f633f1f55961ed17055' 
Old sha1sum was: 'aeacec95643c35ab23f9b45fdc0b4d137a04a38d' 
New sha1sum is : '39ccae1efc06a417b856242694fbe0931836b623' 
--END OF NOTIFICATION 
En effet j'ai procédé à une mise à jour d'un fichier de mon petit DNS interne, le signalement est rapide. 

OSSEC HIDS Notification. 2010 Sep 15 23:17:02 
Received From: (pcnic) 192.168.1.7->syscheck 
Rule: 550 fired (level 7) -> "Integrity checksum changed." 
Portion of the log(s): 
Integrity checksum changed for: 'ossec.conf' 
Size changed from '7554' to '7634' 
Old md5sum was: '91e2cfd5503cb7eeee496f6b83a195b4' 
New md5sum is : 'be35b5b28f893182a6c730e9533ed64d' 
Old sha1sum was: 'e0d47353e1d3339a7d4a5b080fb2853ed1ad8cc0' 
New sha1sum is : 'c25c7b4d2a6ea97c842f106df645874c5985a5ea' 
--END OF NOTIFICATION 
Là j'ai ajusté une règle pour modifier les conditions de syscheck sur le répertoire "c:\program files", la réaction a été très rapide car l'option "realtime" est activée sur les répertoires "sensibles". 
Pour les machines Windows j'attends le prochain "patch tuesday" pour voir ce qui est déclenché. 
En bref c'est un très bon logiciel qui semble très complet. Le paramétrage offre de grandes possibilités pour "filtrer" des messages superflus, le mot "error" dans un message logué est très mal vu ! Je suis abonné à une liste de distribution dont l'adresse de retour par défaut comporte le mot fatidique "error@....", une petite surcharge de règle et le tour est joué, les messages du log comportant un destinataire "error@...." ne déclenchent plus rien. 
Il faut essayer d'être assez précis dans ce type de filtre pour ne pas cacher de vrais "ERRORS". 
Ca y est, les patchs Windows sont arrivés et il y en a 11. Je déclenche cette mise à jour et je vais observer les messages de OSSEC dès leur arrivée. 
Tiens c'est curieux, déjà une heure de passée et aucun message ?!?! 
La machine en question vient de migrer sur un nouveau matériel à processeur ATOM et carte mini dans le même boitier que celui du petit frontal Internet pour un encombrement et une consommation  minimum. 
J'attends le prochain passage de patchs.

OSSEC : filtrage de regles

OSSEC : filtrage de regles jpp

Il arrive que certains messages pourtant "normaux" de votre système encombrent inutilement les mails envoyés par OSSEC. 
Certains logiciels laissent des traces dans les logs systèmes et OSSEC repère ces "anomalies", il est particulièrement sensible à certains mots "failed", "error" ... 
Si une de vos applications génère de tels messages il faut installer un filtre secondaire permettant d'éliminer ces "fausses alertes". 
Il faut alors récupérer le numéro de la règle offensée dans le message (la 1002 est particulièrement sensible) et créer une règle dépendante éliminant le cas gênant. 
Le fichier "local_rules.xml" est destiné à cet effet. 
Par exemple : 
Xen me génère régulièrement des messages "this function is not supported by the hypervisor: virConnectNumOfInterfaces" et c'est encore la règle 1002 qui repère ce truc. 
Il suffit d'ajouter dans le fichier local : 
  <rule id="101117" level="0"> 
    <if_sid>1002</if_sid> 
    <match>this function is not supported by the hypervisor: virConnectNumOfInterfaces</match> 
    <description>erreurs</description> 
  </rule> 
Il faut donner :

  • Un numéro à votre règle ( > 100000), ici 101117 et un niveau d'erreur. Un niveau à zéro annule la condition d'erreur <balise <rule...>. On pourrait aussi rendre une erreur plus grave en augmentant son LEVEL.
  • La règle offensée (ici la fameuse règle 1002) balise <if_sid>
  • Le texte du message, avec les blancs (je ne suis pas un spécialiste des expressions régulières ...)
  • Une description et c'est fini.

Un petit restart de OSSEC et le message ennuyeux s'évanouit ! 

Pour des messages plus complexes, comportant par exemple des parties variables il faut enchaîner deux règles dépendantes : 
  <rule id="101110" level="0"> 
    <if_sid>5104</if_sid> 
    <match>device tap</match> 
    <description>erreurs</description> 
  </rule> 
  <rule id="101111" level="0"> 
    <if_sid>101110</if_sid> 
    <match>entered promiscuous mode</match> 
    <description>erreurs</description> 
  </rule> 
Le message a intercepter comportait une partie variable : le numéro de "tap" concerné, rappel : je ne suis pas un spécialiste des expressions régulières ...). 
Bon filtrage ...

OSSEC : passage en Debian 6

OSSEC : passage en Debian 6 jpp

J'ai dernièrement passé la machine serveur de OSSEC de Debian 5 (Lenny) vers Debian 6 (Squeeze) et lors d'une mise à jour suivante OSSEC a refusé de démarrer avec un message "libmysqlclient_15 not found". 
J'ai vérifié la version installée, c'était la 16 qui avait désinstallé la 15. 
En attendant de tester une nouvelle version de OSSEC (2.5.1, version actuelle 2.4.1) j'ai cherché où trouver cette foutue librairie. 
Quelques recherches sur le site Debian m'ont montré que ce paquet était disponible dans "Lenny" sour le nom "libmysqlclient15off", le temps mettre la bonne ligne dans mon fichier "source.list" 
un "apt-get update" et un "apt-get install libmysqlclient15off" 
plus tard tout est OK. 
Ce paquet semble exister aussi pour Ubuntu dans certains depots "universe". 

Le prochain article sera consacré à l'upgrade de OSSEC 2.4.1 en 2.5.1 avec les problèmes pénibles (pas trop j'espère) d'une mise à niveau par un fichier "tar.gz" et donc une partie de compilation.

OSSEC : passage version 2.6

OSSEC : passage version 2.6 jpp

J'ai décidé d'upgrader mon installation de OSSEC de 2.4 en 2.6, il faut rester à la pointe du progrès. 
J'ai donc téléchargé le tar.gz de la 2.6 et je l'ai installé dans un petit coin tout propre. 
Là, dans le répertoire principal un joli petit script "install.sh" nous attends. 
Mais, d'abord sauvegardons le contenu "actuel" du logiciel : /var/ossec. 
Ensuite seulement on peut frapper le fatidique "./install.sh", Eh mais non, il faut d'abord activer l'accès Mysql. On va dans le répertoire "src" et on chante un petit truc comme "make setdb" et ... l'incantation fonctionne. Un petit "cd .." et le tentant "./install.sh" :

** Para instalação em português, escolha [br] 
  ** 要使用中文进行安装, 请选择 [cn]. 
  ** Fur eine deutsche Installation wohlen Sie [de]. 
  ** Για εγκατάσταση στα Ελληνικά, επιλέξτε [el]. 
  ** For installation in English, choose [en]. 
  ** Para instalar en Español , eliga [es]. 
  ** Pour une installation en français, choisissez [fr] 
  ** Per l'installazione in Italiano, scegli [it]. 
  ** 日本語でインストールします.選択して下さい.[jp]. 
  ** Voor installatie in het Nederlands, kies [nl]. 
  ** Aby instalować w języku Polskim, wybierz [pl]. 
  ** Для инструкций по установке на русском ,введите [ru]. 
  ** Za instalaciju na srpskom, izaberi [sr]. 
  ** Türkçe kurulum için seçin [tr]. 
  (en/br/cn/de/el/es/fr/it/jp/nl/pl/ru/sr/tr) [en]: fr

Il y a quelques hiéroglyphes mais je choisis bravement "fr".

OSSEC HIDS v2.6 Script d'installation - http://www.ossec.net 
Vous êtes sur le point d'installer OSSEC HIDS. 
Vous devez avoir une compilateur C préinstallé sur votre système. 
Si vous avez des questions ou des commentaires, envoyez un email 
à dcid@ossec.net (ou daniel.cid@gmail.com). 
  - Système: Linux kmail 2.6.39 
  - Utilisateur: root 
  - Hôte: xxxxxx 
  -- Appuyez sur Entrée pour continuer ou Ctrl-C pour annuler. -- 

Après un appui sur entrée : 
 - Vous avez déjà installé ossec. voulez-vous le mettre à jour ? (o/n): o 
 - Voulez-vous mettre à jour les règles ? (o/n): o 
Après 2 "o"+entrée la compilation démarre et 
Starting OSSEC HIDS v2.6 (by Trend Micro Inc.)... 
OSSEC analysisd: Testing rules failed. Configuration error. Exiting. 
/var/ossec/bin/ossec-dbd: /usr/lib/libmysqlclient.so.15: version `libmysqlclient_15' not found 
(required by /var/ossec/bin/ossec-dbd) 
- Configuration correctement terminée. 
- Pour démarrer OSSEC HIDS: 
        /var/ossec/bin/ossec-control start 
- Pour arrêter OSSEC HIDS: 
        /var/ossec/bin/ossec-control stop 
- La configuration peut être visualisée ou modifiée dans /var/ossec/etc/ossec.conf 
    Merci d'utiliser OSSEC HIDS. 
    Si vous avez des questions, suggestions ou si vous trouvez 
    un bug, contactez nous sur contact@ossec.net ou en utilisant la 
    liste de diffusion publique sur ossec-list@ossec.net 
    ( http://www.ossec.net/en/mailing_lists.html ). 
    Plus d'information peut être trouver sur http://www.ossec.net 
    ---  Appuyez sur Entrée pour finir (peut-ếtre plus d'info plus bas). ---

La tuile, OSSEC utilise une vieille version de la librairie Mysql Client, heureusement que j'ai aussi de vieilles machines qui possèdent encore cette librairie, je copie le tout dans /usr/lib : 
lrwxrwxrwx 1 root root      24 Aug  2 23:19 libmysqlclient.so.15 -> libmysqlclient.so.15.0.0 
-rw-r--r-- 1 root root 1993916 Feb 17  2009 libmysqlclient.so.15.0.0 
lrwxrwxrwx 1 root root      26 Aug  2 23:19 libmysqlclient_r.so.15 -> libmysqlclient_r.so.15.0.0 
-rw-r--r-- 1 root root 2002908 Feb 17  2009 libmysqlclient_r.so.15.0.0 

C'est pas très beau (horrible ?) de faire ce genre de chose dans un beau système Debian bien ordonné mais un petit tour dans le fichier "Contents...." ne me montre aucune librairie en version 15 accessible dans les magasins où je me sers habituellement. Aux grands maux les grands moyens. 
Un petit "service ossec start" et aucun message d'insulte, tout est OK. 
Les processes OSSEC ont l'air "ps -ef | grep ossec" d'être là. Un petit tour par l'interface graphique pour constater que le serveur a repris contact avec ses clients préférés et que tout semble baigner dans le plus parfait bonheur. 

Au fait j'ai gardé le tar des librairies dans un magnifique répertoire de sauvegarde de vieux trucs, ça pèse quand même # 4Mo.

OSSEC : version 2.7 et nouveau serveur

OSSEC : version 2.7 et nouveau serveur jpp

L'ancienne machine était très économique mais son processeur 32bits commençait à dater, par exemple les nouvelles versions de ZIMBRA ne se font plus qu'en 64bits. 
Il était donc nécessaire de passer sur une carte mère 64bits avec un Corei3 en version ECO TDP de 35W maxi dans le même boitier. Je passe l'installation (toujours Debian) pour en arriver à OSSEC en version 2.7. 
L'installation par elle même n'a pas changé, voir les chapitres précédents. 
Toutefois, pour changer un peu, je n'ai pas intégré OSSEC dans la base MYSQL de ZIMBRA mais j'ai utilisé une base PostgreSQL. 
La procédure est identique (on travaille dans les répertoires "sources" et non dans les répertoires d'installation du logiciel) :

cd mes_sources_OSSEC/src 
make setdb 
cd .. 
./install.sh

cd  répertoire_d_installation 
./bin/ossec-control enable database 

Il faut alors, comme pour MYSQL mettre en place (au début du fichier etc/ossec.conf le paramétrage de notre base PostgreSQL, par exemple en début de fichier :

<ossec_config> 
  <database_output> 
    <hostname>127.0.0.1</hostname> 
    <port>5432</port> 
    <username>mon_user_ossec</username> 
    <password>le_password_qui_tue</password> 
    <database>ma_base_ossec</database> 
    <type>postgresql</type> 
  </database_output> 
</ossec_config>

Il faut ensuite créer une base PostgreSQL avec le user qui va bien et initialiser cette base à l'aide du script dans le répertoire "répertoire_source/ossec-hids-2.7/src/os_dbd", on lance alors psql pour créer les tables: 
psql -U un_user_admin -W ma_base_ossec <postgresql.schema
On peut ensuite démarrer OSSEC et le tour est joué.
 
Mais tout ça c'était avant la découverte d'un nouvel interface Web pour OSSEC : ANALOGI. 
Cet interface est à première vue surprenant mais très efficacce, manque de pot il ne marche qu'avec MYSQL, donc exit PostgreSql et retour à Mysql. 
Vite un article sur ANALOGI malheureusement aujourd'hui défunt que j'ai du remplacer par un petit développement "perso".

OSSEC : 2.7 et interface Web ANALOGI

OSSEC : 2.7 et interface Web ANALOGI jpp

Note 2019 : La version décrite ici est ancienne et incompatible avec les version récentes (>2.9) de Ossec, il est possible d'utiliser la version décrite ici pour Ossec >= 3.0.

En installant la nouvelle version 2.7 j'ai cherché un interface Web un peu plus "sexy" que l'ancien interface d'OSSEC. En cherchant un peu je suis tombé sur AnaLogi et j'ai décidé de le tester, mais comme indiqué dans l'article précédent pas de PostgreSql avec AnaLogi. 
Note 2018, Analogi n"est plus compatible avec les versions de OSSEC >= 2.9.3,  voir ici. 
On le trouve à l'URL suivante : https://github.com/ECSC . 
L'installation est assez simple, on dézippe le machin dans un coin et on se débrouille pour que Apache soit capable de le trouver (si vous préférez Nginx cela ne devrait pas poser de problèmes). 
Ajouter dans "sites-available" le fichier "ANALOGI" contenant :

<VirtualHost 127.0.0.1:83> 
    ServerAdmin webmaster@localhost 
    ServerName  analogi.xxxx.xxx 
    Include /etc/apache2/sites-available/ANALOGI_body 
</VirtualHost> 
L'adresse en 127.0.0.1 est due à l'utilisation de "haproxy" pour aiguiller les requêtes, vous pouvez bien entendu mettre directement une adresse visible de l'extérieur.

Le fichier ANALOGI_body contient :

#       "Body" du site AnaLogi 
        DocumentRoot /opt/AnaLogi     
        <Directory /> 
                Options FollowSymLinks 
                AllowOverride None 
        </Directory> 
        <Directory /opt/AnaLogi> 
                Options Indexes FollowSymLinks MultiViews 
                AllowOverride None 
                Order allow,deny 
                allow from all 
        </Directory> 
        DirectoryIndex  index.php 
        ErrorLog /var/log/apache2/ANALOGI_error.log 
        # Possible values include: debug, info, notice, warn, error, crit, 
        # alert, emerg. 
        LogLevel warn 
        LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" personnel 
        CustomLog /var/log/apache2/ANALOGI_access.log personnel

Créer ensuite le lien adéquat de "sites-enabled" vers "sites-available" et relancer Apache.

La page d'accueil présente dès le lancement un récapitulatif des résultats : 
Page d'accueil ANALOGI 
En bas les principaux "problèmes" rencontrés, ces liens sont cliquables et mènet à une page détail. 
La recherche est donc très rapide. 
La zone "Filters" permet de :

  • Limiter la période,
  • Effectuer une statistique par source (machine)
  • Par chemin (répertoire d'origine des informations)
  • Par niveau.
  • Par règle.

La zone "Top Loc" donne la principale origine des messages. la zone "Rare" signale les événements un peu originaux qui peuvent être les plus intéressants. 
Les liens cliquables mènent sur une page détail qui présente une courbe en fonction du temps et le détail des alertes en partie basse. 
Page détail

L'exemple affiché ici concerne des tentatives de relais de mail avec toujours le même emmerdeur qui veut envoyer un mail à "therichsheickc@yahoo.com" , la plupart des serveurs ne sont pas en relais ouvert ce genre de "truc" est donc un peu inutile.

La période d'affichage est réglée par défaut à 72 heures ce qui est beaucoup pour moi, mais il est très facile de modifier cette valeur : 
Fichier = config.php 
Ligne à modifier : "$glb_hours=72;" 
Je l'ai mis à 12 heures ce qui me semble suffisant.

En bref je suis enchanté de cet interface qui simplifie grandement la vérification des anomalies interceptées par OSSEC, à utiliser et conseiller sans modération.

Analogi fonctionne encore en version 2.8.x de OSSEC.

OSSEC passage V2.9

OSSEC passage V2.9 jpp

J'ai voulu passer à la dernière version, la 2.9 mais cela m'a posé quelques problèmes car le schéma de la base  de données est différent. Il faut donc "laisser tomber" l'ancienne base et en créer une nouvelle et perdre l'historique à moins de se lancer dans une reprise de données (qui, par ailleurs, ne semble pas trop complexe). 
J'ai installé ensuite le serveur à partir du package Debian fourni par "Atomic corp" en version 2.9.3. 
Mon interface favori (ANALOGI) ne fonctionne plus (schéma de base différent) mais j'ai trouve une version améliorée d'ANALOGI (adaptée à la 2.8) téléchargeable : https://github.com/NunesGodinho/OSSEC-WUI et je suis en train d'en tirer une version adaptée au nouveau schéma de base de données en y ajoutant quelques fonctionnalités. 
Je vais la tester sur la future version 3.0 de OSSEC ( voir les résultats ici)  avant de la diffuser, car le schéma de base de données est identique à celui présent en version 2.9.3.

OSSEC : V3.0 stable

OSSEC : V3.0 stable jpp

Test complet de Ossec V3.0.0 stable. 
Cela va me permettre de tester la nouvelle version de l'interface OSSEC_GUI en version adaptée pour la 3.0.  
Cette version est issue de Analogi et de OSSEC_WUI,cCette nouvelle version reste compatible avec la 2.9.3 au niveau de la base de données.

Note juin 2018 : la version adaptée de l'interface est disponible, voir ici.

OSSEC V3.0.0 stable Installation serveur

OSSEC V3.0.0 stable Installation serveur jpp

J'ai commencé par télécharger l'archive par : 
 wget https://github.com/ossec/ossec-hids/archive/master.zip

Pour changer de Mysql (bloqué en 5.5.999 dans Stretch) j'installe MariaDB 10.1 qui, lui, estprésent dans Stretch. 
Pré-requis : 
un compilateur ... 
make 
Il m'a fallu faire un "ln -s " pour la commande "cc", "ar" et "nm" étaient OK. 
libmysql++-dev 
apt-get install libmysql++-dev 
qui installe aussi default-libmysqlclient-dev libmariadbclient-dev libmariadbclient-dev-compat libmysql++3v5 zlib1g-dev. 
Par précaution j'ai créé par avance un utilisateur "ossec"" avec son groupe.

Après dézippage de l'archive qui crée un répertoire "ossec-hids-master" on entre dans le vif du sujet et dans ce répertoire puis :

cd src 
make clean 
make TARGET=server DATABASE=mysql 2>&1 | tee LOG.MAKE

Tout se déroule bien et un examen du log ne montre que quelques warnings correspondant à des variables non initialisées.

La trace complète de la compilation est disponible ICI. 
Tout ceci étant OK on va pouvoir se lancer dans la procédure d'installation .

cd ossec-hids-master 
sudo ./install.sh

... 
  ** Para instalar en Español , eliga [es]. 
  ** Pour une installation en français, choisissez [fr] 
  ** A Magyar nyelvű telepítéshez válassza [hu]. 
.... 
  (en/br/cn/de/el/es/fr/hu/it/jp/nl/pl/ru/sr/tr) [en]: --> fr

Je vous épargne ici la trace complète que vous pouvez consulter ici. 
Le script "ossec" a été ajouté dans "/etc/init.d" mais aucun process ne tourne, un regard rapide dans le répertoire "/var/ossec" montre la structure de l'installation :

ls -1 /var/ossec 
active-response 
agentless 
bin 
etc 
logs 
lua 
queue 
rules 
stats 
tmp 
var

Ceci ressemble furieusement à d'autres installations de OSSEC.

Il nous reste maintenant à nous occuper de la base de données. 
Un magnifique fichier "./src/os_dbd/mysql.schema" attire l'oeil, et un examen superficiel montre que la structure de la base est identique à celle de la version 2.9.3. Mais il faut d'abord créer utilisateur et base de données, on lance donc mysql :

mysql --user=root -p 
create database ossec_base; 
create user 'ossec'@'localhost' identified by 'User_Ossec_1234'; 
create user 'ossec'@'ip_du_serveur_web' identified by 'User_Ossec_1234'; 
use ossec_base; 
source ./src/os_dbd/mysql.schema 
.... 
show tables; 
+----------------------------+ 
| Tables_in_ossec_base       | 
+----------------------------+ 
| agent                      | 
| alert                      | 
| category                   | 
| location                   | 
| server                     | 
| signature                  | 
| signature_category_mapping | 
+----------------------------+ 
7 rows in set (0.00 sec) 
-- Autoriser notre user (localhost) sur cette base. 
grant all on ossec_base.* to 'ossec'@'localhost'; 
grant select,insert,update,delete on ossec_base.* to 'ossec'@'ip_du_serveur_web'; 
-- On réduira les droits plus tard

Je vous conseille aussi de créer un "trigger" sur la table "alert" afin de s'assurer que toute signature est bien définie dans la table signature afin que tout fonctionne normalement. Pour cette action voir ici.

PS : au passage créer un utilisateur spécifique comme DBA, il n'y en a pas par défaut et 'root' ne convient pas pour MariaDB (10.1). Par contre cela est OK en 10.3.

Si vous voulez initialiser les tables (signature, category et signature_category_mapping) avec les valeurs que j'utilise, voir la page ici. 
Il nous faut maintenant activer le support BDD :

passer en "root" 
cd /var/ossec/bin 
./ossec-control enable database

La base est initialisée et il ne reste plus qu'à indiquer les éléments de connexion dans le fichier /var/ossec/etc/ossec.conf :

<database_output> 
    <hostname>127.0.0.1</hostname> 
    <port>3306</port> 
    <username>le_user</username> 
    <password>le_mot_de_passe</password> 
    <database>la_base</database> 
    <type>mysql</type> 
  </database_output>

Au passage il est bon de supprimer (ou commenter) les fichiers de règles qui ne vous concernent pas, cela allègera la config. Attention il peut y avoir des problèmes au redémarrage car certains fichiers présentent des éléments liés à d'autres fichiers ... mais il y a un message d'erreur à peu près explicatif dans les logs.

On lance pour voir :

/etc/init.d/ossec start 
Starting OSSEC HIDS v3.0.0 (by Trend Micro Inc.)... 
Started ossec-dbd... 
Started ossec-execd... 
Started ossec-analysisd... 
Started ossec-logcollector... 
Started ossec-remoted... 
Started ossec-syscheckd... 
Started ossec-monitord... 
Completed.

Tout s'est bien lancé ! Et on a même déjà un fichier "log" dans /var/ossec/logs", un petit regard dans ce fichier ne montre aucune anomalie, c'est le pied ! Et, en plus au bout de quelques secondes la table "alert" enregistre ses premiers rangs.

OSSEC V3.0.0 stable compilation agent

OSSEC V3.0.0 stable compilation agent jpp

Installation dans une machine KVM munie d'une debian Stretch "de base". 
Installation d'un environnement de compilation : gcc ... make. 
La aussi j'ai du effectuer un ln -s 
cd /usr/bin 
sudo ln -s gcc-6 cc 
Curieusement ar,nm et ranlib étaient OK. 
  
Aucun autre pré-requis pour l'installation de l'agent.

Lancer la compilation :

cd le_répertoire de compil/src 
make TARGET=agent 2>&1 | tee LOG.MAKE 
    CC external/cJSON/cJSON.o 
    LINK libcJSON.a 
    RANLIB libcJSON.a 
...... 
make[1]: Leaving directory '/usr/src/PGM/BUILD/ossec-hids-master/src' 
Done building agent

La trace ne montre aucune erreur ou même warning, on va donc pouvoir lancer le script "install.sh" (toujours dans le répertoire de compil) ... et voir la trace d'installation. 
Tout s'est bien passé, on passe en "root" pour aller faire les ajustements de paramétrage nécessaires du fichier ossec.conf : 
- enlever les fichiers inutiles (avec prudence) 
- paramétrer les répertoires à surveiller 
- ... 
Le fichier agent.conf a disparu ce qui est plutôt un bien. 
Il faut maintenant extraire une clef du serveur :

cd /var/ossec/bin 
./manage_agents 
**************************************** 
* OSSEC HIDS v2.9.0 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: -->A 
- Adding a new agent (use '\q' to return to the main menu). 
  Please provide the following: 
   * A name for the new agent: -->xxxxxxx 
   * The IP Address of the new agent: XXX.XXX.XXX.XXX 
   * An ID for the new agent[001]: 
Agent information: 
   ID:001 
   Name:kvmtest 
   IP Address:192.168.100.100

Confirm adding it?(y/n): -->y 
Agent added. 
**************************************** 
* OSSEC HIDS v2.9.0 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: -->E 
Available agents: 
   ID: 001, Name: kvmtest, IP: 192.168.100.100 
Provide the ID of the agent to extract the key (or '\q' to quit): 001 
Agent key information for '001' is: 
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxU=

** Press ENTER to return to the main menu.

Copier cette valeur de "clef" pour recopie sur le client. 
Sur la machine cliente :

cd /var/ossec/bin 
./manage_agents 
**************************************** 
* OSSEC HIDS v2.9.0 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (I)mport key from the server (I). 
   (Q)uit. 
Choose your action: I or Q: I

* Provide the Key generated by the server. 
* The best approach is to cut and paste it. 
*** OBS: Do not include spaces or new lines.

Paste it here (or '\q' to quit): xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxU= 
Agent information: 
   ID:001 
   Name:kvmtest 
   IP Address:192.168.100.100 
Confirm adding it?(y/n): y 
Added. 
** Press ENTER to return to the main menu.

Puis lancer notre agent et aller voir ce qui se passe dans les logs, pour moi tout est OK. Ne pas oublier de mettre le lancement en mode automatique : 
update-rc.d ossec enable 
systemctl start ossec

Et rien n'apparait dans la base de données du serveur, un oeil sur les logs qui montre des messages : 
...ossec-syscheckd: WARN: Process locked. Waiting for permission... 
...ossec-logcollector: WARN: Process locked. Waiting for permission... 
Il suffit d'enlever le fichier  /var/ossec/queue/ossec/.wait et tout rentre dans l'ordre.

Au bout de quelques minutes des messages apparaissent sur le serveur ce qui est plutôt bon signe. 
En bref : tout c'est (presque) bien passé. 
Petit contrôle sur le serveur :

mysql .... 
select lo.name,al.rule_id 
from alert al, location lo 
where al.location_id = lo.id 
order by 1;

Si cela "crache" quelque chose avec le nom du client dans la "location" c'est bon signe. 
 

OSSEC V3.0.0 installation agent

OSSEC V3.0.0 installation agent jpp

Installation paquet OSSEC agent sur une Debian Stretch. 
On trouve sur le site des paquets pour les principales distributions. 
Pré-requis : 
Installer les paquets "expect" et "tcl-expect": 
apt-get install tcl-expect expect 
Télécharger l'archive depuis https://updates.atomicorp.com/channels/ossec/debian/pool/main/o/ossec-hids-agen…... 
Prenez la dernière version : ossec-hids-agent_3.0.0.5609stretch_amd64.deb à ce jour et installez le paquet avec :  
dpkg -i ossec-hids-agent_3.0.0.5609stretch_amd64.deb 
L'installation ajoute le user "ossec" et le groupe du même nom, tout est installé dans le répertoire /var/ossec. 
Aller vérifier le fichier "ossec.conf" dans le répertoire "/var/ossec/etc" et bien vérifier que l'adresse "<server-ip>.....</server-ip>" est bien celle du serveur, sinon corriger la valeur par défaut de "127.0.0.1". 
Il faut ensuite autoriser l'agent et le serveur à interagir :

  • Sur le serveur :

Aller dans le répertoire /var/ossec/bin et lancer ./manage-agent

**************************************** 
* OSSEC HIDS v2.9.2 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q:   A 
- Adding a new agent (use '\q' to return to the main menu). 
  Please provide the following: 
   * A name for the new agent: le_nom_de_l_agent 
   * The IP Address of the new agent: 192.168.2.x 
   * An ID for the new agent[005]:  
Agent information: 
   ID:005 
   Name:le_nom_de_l_agent 
   IP Address:192.168.2.x

Confirm adding it?(y/n): y 
Agent added. 
**************************************** 
* OSSEC HIDS v2.9.2 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: E 
Available agents:  
   ID: 001, Name: ....................... 
   ID: 002, Name: ....................... 
   ID: 003, Name: ............................ 
   ID: 004, Name: ............................. 
   ID: 005, Name: le_nom_de_l_agent, IP: 192.168.2.x 
Provide the ID of the agent to extract the key (or '\q' to quit): 005 
Agent key information for '005' is: MDA1IHBjbmljMiAxOT belle clef incompréhensible TU5  
Copier cette clef

** Press ENTER to return to the main menu. 
**************************************** 
* OSSEC HIDS v2.9.2 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (A)dd an agent (A). 
   (E)xtract key for an agent (E). 
   (L)ist already added agents (L). 
   (R)emove an agent (R). 
   (Q)uit. 
Choose your action: A,E,L,R or Q: q

  • Sur le client : 
    Aller dans le répertoire /var/ossec/bin et lancer ./manage-agent

**************************************** 
* OSSEC HIDS v2.9.0 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (I)mport key from the server (I). 
   (Q)uit. 
Choose your action: I or Q: I 
* Provide the Key generated by the server. 
* The best approach is to cut and paste it. 
*** OBS: Do not include spaces or new lines.

Paste it here (or '\q' to quit): Coller la clef obtenue du serveur

Confirm adding it?(y/n): y 
Added. 
** Press ENTER to return to the main menu. 
**************************************** 
* OSSEC HIDS v2.9.0 Agent manager.     * 
* The following options are available: * 
**************************************** 
   (I)mport key from the server (I). 
   (Q)uit. 
Choose your action: I or Q: Q

** You must restart OSSEC for your changes to take effect.

manage_agents: Exiting.

Un petit coup de "systemctl restart ossec" et le tour est joué, on vérifie la connection dans le fichier "/var/ossec:logs/ossec.log".

Il faut maintenant configurer correctement les paramètres de notre nouvel agent. Ceci concerne surtout les fichiers de log à surveiller et quelques paramètres. 
Les fichiers à surveiller sont fonction de chaque distribution, ne laisser que les fichiers utiles, cela évite des messages d'erreur.

 et des informations inutiles ... 
Voir aussi le fichier /var/ossec/etc/shared/agent.conf 
Fichiers de style "xml" les commentaires se définissent entre "<!--" et "-->" comme pour du HTML. 
Attention, certains fichiers ou répertoires se trouvent "en double" entre ossec.conf et agent.conf ce qui générera des erreurs dans les logs. 
J'ai par exemple mis en commentaire "Directories to check" dont les répertoires sont déjà indiqués dans le fichier "ossec.conf". 
On peut même mettre en commentaires ce qui ne concerne pas notre système préféré, j'ai commenté tout ce qui concernait Windows inutile ici.  
Si la machine supervisée n'est pas un serveur il faudra probablement inhiber les contrôles <system_audit>...</system_audit> dans le fichiers agent.conf ou au moins n'activer que celui correspondant à votre distribution. 
Pour vérifier rapidement si Ossec est bien actif rien de tel que : 
ps -ef | grep ossec 
Qui doit répondes gentiment : 
root     16688     1  0 18:14 ?        00:00:00 /var/ossec/bin/ossec-execd 
ossec    16692     1  0 18:14 ?        00:00:00 /var/ossec/bin/ossec-agentd 
root     16696     1  0 18:14 ?        00:00:00 /var/ossec/bin/ossec-logcollector 
root     16700     1  0 18:14 ?        00:00:00 /var/ossec/bin/ossec-syscheckd 
Remarques : 
Au premier passage il vous sera probablement signalé pas mal d'erreurs de droits sur certains fichiers/répertoires, il est bon de les corriger pour éviter des messages ultérieurs inutiles. 
Pour tester je tente une mise à jour du cron et quelques secondes plus tard mon interface graphique OSSEC-GUI montre l'événement.

Image ecran OSSEC-WUI 3.0
Copie écran après mise à jour crontab

 

OSSEC GUI V3.0

OSSEC GUI V3.0 jpp

J'avais beaucoup apprécié l'interface Analogi qui permettait de suivre assez agréablement les événements enregistrés par OSSEC, j'avais d'ailleurs écrit un article sur ce logiciel. 
Lorsque j'ai migré mes systèmes en 2.9 cet interface agréable ne fonctionnait plus du fait de la différence de structure de la base de données. 
J'ai cherché un produit équivalent plus récent (Analogi n'est plus maintenu depuis longtemps) et j'avais trouvé une version dérivée baptisée OSSEC WUI que l'on peut trouver sur github.

Malheureusement cette version utilise le schéma de base de données antérieur. J'ai donc décidé de repartir de cette version en l'adaptant au nouveau schéma de la base. J'ai ensuite vu paraître une nouvelle version d'Ossec (version V3.0) et je me suis dépêché de la tester pour bien vérifier si le schéma de la base avait évolué. J'ai vite constaté que ce schéma était resté identique (à celui de la version 2.9.3) et je me suis penché un peu plus sur OSSEC-WUI pour l'améliorer encore et y ajouter quelques fonctions statistiques, la possibilité de détruire des rangs spécifiques et séparer la réorganisation de la base de données de l'application "Management". 
J'ai aussi pensé à une fonctionnalité nouvelle, fonctionner selon deux modes :

  • Mode "running" directement à partir de la base alimentée par OSSEC, les événements une fois expliqués et/ou résolus peuvent être supprimés ce qui permet de n'avoir que peu d'alertes "actives". Rassurez vous ils ne sont pas perdus mais reportés dans une deuxième base de données.
  • Mode "history" qui fonctionne à partir de la base de sauvegarde avec exactement les mêmes fonctionnalités.

Voir quelques images d'écrans.

Afin de "sécuriser" les données, surtout les données archivées, j'ai ajouté une fonction d'authentification avec trois niveaux de responsabilité :

  1. Niveau lecture seule
  2. Niveau "delete autorisé" sur la base "running"
  3. Niveau "Admin" qui a tous les droits sur les deux modes, y compris pour la mise à jour des utilisateurs.


Note 2018/06/09 cette version baptisée "OSSEC-GUI-3.0" est disponible sur github en release V3.0.

Le projet contient toutes les doc d'installation des différentes possibilités :

  • Installation "simple"
  • Installation avec ou sans mode "historique"
  • Mise en place possible d'une l'authentification


J'espère que les docs sont OK, sinon il est facile de signaler les problèmes dans Github.

OSSEC ne recoit plus

OSSEC ne recoit plus jpp

Petit ennui : Les agents n'envoient plus rien au serveur. 
Depuis environ le 11 avril les données des clients ne sont plus reçues par la machine serveur. 
L'analyse des logs montre un message, un peu cryptique, après chaque redémarrage : 
getaddrinfo: Name or service not known 
Sans autre explication et aidé par quelques congés j'ai presque un mois pour trouver une solution ! 
En fait il m'aurait probablement suffi de porter mon attention sur la ligne suivante des logs : 
ossec-remoted(1206): ERROR: Unable to Bind port '1514' 
Qui m'aurait probablement ouvert les yeux ou au moins mis sur la piste. 
Je ne sais pas ce qu'il s'est passé aux environ du 11/04 mais "getaddrinfo" s'est mis à ne plus donner de résultat ??? alors que le DNS fonctionne parfaitement bien. 
La solution : mettre dans le fichier "/etc/hosts" une ligne avec l'adresse IP de communication avec les clients et le nom du serveur : "192.168.2.2 xxxxx xxxxx.yyy.zzz". 
C'est d'ailleurs ce que je fais en général, mais j'avais du l'oublier ici. 
Depuis OSSEC reçoit de nouveau les données des clients, la commande suivante permet de vérifier lla "bonne" ouverture du port UDP/1514 : 
lsof -Pn | grep UDP | grep :1514 
ossec-rem  9692         ossecr    4u     IPv4     41151085      0t0        UDP *:1514 
ossec-rem  9692  9694   ossecr    4u     IPv4     41151085      0t0        UDP *:1514 
..... 
Comme quoi il vaut mieux bien lire les logs en cas de problème !!!

IPSET une nouvelle arme contre les méchants ?

IPSET une nouvelle arme contre les méchants ? jpp

Note 2020 : depuis tous ce temps, (début 2013) j'utilise un pare-feu à base d'IPSET car  les règles iptables utilisant des IPSET sont très performantes. Un set rempli d'adresses "douteuses" n'est pas une cause de latence, c'est d'autre part beaucoup plus facile à maintenir, enlever ou ajouter une adresse est quasiment instantané et cela évite surtout un empilage de règles difficiles à maintenir et qui finissent par être une cause importante de latence. Il est par exemple très facile et performant créer un "set" d'adresses de pays que l'on ne désire pas voir accéder à un système.

Dès qu'une machine est reliée à Internet elle subit de nombreuses tentatives d'entrée ou de test. Un bon Firewall permet de contrôler en partie ces tentatives mais les services offerts par chaque machine ne peuvent que moins facilement être protégés des « méchants ». Si par exemple vous avez un serveur de mails vous recevrez de nombreux essais d'envoi de mail bien que votre serveur ne soit pas configuré en mode « open ». Un serveur HTTP entrainera un tas de tests sur des bugs de beaucoup de logiciels. C' est énervant, cela remplit bêtement les logs d'enregistrements inutiles et alourdit leur lecture, toute cette brume de tentatives indiscrètes peut finir par cacher certains messages utiles.

Note 2017 : Ipset est en version 6.30 et tout fonctionne toujours correctement avec un noyau 4.13.7.

Le site « emerging threats » fournit des listes d'adresses IP, voire de réseaux entiers, qui hébergent ces vilains pollueurs de logs qui peuvent quand même planter des services ou même réussir à faire pire encore. Ces listes sont régulièrement mises à jour.

On peut récupérer (ou créer) de longues listes de règles « iptables » qui ralentissent évidemment le fonctionnement de votre firewall et fait d'un simple « iptables -vnL » une liste infinie.

Et alors IPSET est arrivé …. en fait la fonctionnalité existe depuis longtemps mais était assez difficile à maîtriser. Aujourd'hui avec les noyaux récents et la dernière version du protocole (version 6) cela semble très stable et parfaitement maîtrisable avec des performances qui semblent excellentes.

Un simple "apt-get install ipset" est OK, mais votre noyau doit être compilé avec les options adéquates :

make menuconfig

Networking support / Networking options / Network packet filtering framework / Ipset support.

Vérifier aussi la version de protocole de "ipset" :

ipset --version 
ipset v6.12.1, protocol version: 6 
 

Les versions de "ipset" et du noyau doivent être "en phase" pour fonctionner, ce qui peut parfois poser quelques problèmes de compatibilité.

IPSET 6.19 fonctionne avec tous les noyaux de 3.2 à 3.11, IPSET 6.12 avec ceux de 3.2 à 3.10. 

Je n'ai pas essayé de noyaux < 3.2.

Mes tests ont été réalisés avec des noyaux 3.9, 3.10 et 3.11-rc2 afin d'avoir les fonctionnalités les plus récentes. Le programme "ipset" 6.19) a été chargé depuis la version "unstable" de Debian afin de disposer là aussi des éléments les plus récents compatibles avec ces noyaux.

L'ensemble est simple à utiliser :

  • coté « iptables » une simple règle permet d'éliminer d'un seul coup toutes les adresses contenues dans un « set »
  • coté gestion des « sets » la commande « ipset » permet de gérer assez simplement les choses.

Cette commande possède un paramètre permettant de remplacer d'un seul coup un « set » par un autre et ce sans stopper le firewall ni supprimer la règle. La commande « swap » réalise cette opération instantanément sans interruption de la sécurité. Vous pouvez donc préparer tranquillement un nouveau « set » puis le « swapper » instantanément avec un set existant.

Il existe différentes catégories de « sets » selon que l'on veut traiter :

  • des adresses IP
  • des réseaux en notation CIDR
  • des adresses/port
  • ….

Le tout en deux modes principaux : HASH et BITMAP.

N'ayant ici que besoin de traiter des adresses et des réseaux je ne me suis intéressé qu'aux deux types « iphash » et « nethash » qui semblent adaptés à mon besoin et sont d'une très grande rapidité.

J'utilise en entrée trois listes d'adresses sources :

  • une petite liste personnelle en notation CIDR
  • un fichier de « emerging threats » nommé « compromised-ips.txt » contenant des adresses IP et des adresses en notation CIDR
  • un autre fichier « emerging threats » nomme « rbn-malvertisers-ips.txt »

Un traitement simple des listes d'adresses élimine les commentaires et les ligne vides puis sépare les adresses simples des adresses CIDR. Chaque groupe d'adresses est ensuite trié avec élimination des doubles (la présence de doubles provoque un arrêt d'urgence des chargements de sets) et remplit les deux sets adresses IP et adresses CIDR.

Les règles iptables se limitent à deux (en PREROUTING pour stopper le plus tôt possible les paquets vicieux) :

iptables -t raw -I PREROUTING -m set --match-set BLACK_IP src -j DROP

iptables -t raw -I PREROUTING -m set --match-set BLACK_NET src -j DROP

On peut aussi créer une chaîne perso ici "NOUVIN" sur laquelle on redirige les connections "nouvelles". Par exemple :

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
iptables -A INPUT -m state --state NEW -j NOUVIN 
On insérera les règles "SET" dans cette chaîne "NOUVIN" :

iptables I NOUVIN -m set --match-set BLACK_IP  src     -j DROP 
iptables I NOUVIN -m set --match-set BLACK_NET src     -j DROP

Après un rechargement des deux sets nommés chez moi « BLACK_IP » et « BLACK_NET » il suffit, après récupération des fichiers et traitement préparatoire de créer et remplir deux nouveaux sets de travail. Remarque la commande « ipset » peut aussi être installée dans /usr/sbin.

SET=W_BLACK_IP

/sbin/ipset --create $SET iphash --hashsize 50000

puis de remplir le set par une boucle sur la lecture de la liste préparée sur la commande

/sbin/ipset --add $SET $ADDR

SET=W_BLACK_NET

/sbin/ipset --create $SET nethash --hashsize 4096

suivre le même process en utilisant :

/sbin/ipset –add $SET $ADDR $MASK

Une fois nos deux sets « W » prêts il suffit de les « swapper » avec les sets permanents :

/sbin/ipset swap W_BLACK_IP BLACK_IP

/sbin/ipset swap W_BLACK_NET BLACK_NET

puis de détruire les sets « W » de travail :

/sbin/ipset --destroy W_BLACK_IP

/sbin/ipset --destroy W_BLACK_NET


Et le tour sera joué ... et les méchants joués.

Bloquer IP par pays

Bloquer IP par pays jpp

Cet article présente un tout petit ensemble de scripts permettant la création et la mise à jour d'un "set" comprenant toutes les classes d'adresses IP allouées à certains pays, le tout paramétrable par le fichier de configuration. 
J'utilisais comme source d'adresses le site "https://www.ipdeny.com" qui permet d'obtenir facilement les classes d'adresses allouées à chaque pays, mais, depuis quelques mois, les données ne semblent plus évoluer ... 
Je me suis donc mis à la recherche d'une nouvelle source et j'ai trouvé le site "https://ip2location.com" qui fournit plusieurs listes d'IP, certaines payantes, mais une version "LITE" est en accès libre. Comme je n'ai pas besoin d'une grande précision géographique (le pays me suffit) la version LITE me convient parfaitement. 
Le "set" constitué à partir de ces adresses est utilisé dans une règle iptables simple :

## Interface vers l'extérieur 
IFEXT=eth0 
TYP= ' -t mangle ' 
OPTLIM=' -m limit --limit 30/h --limit-burst 10 ' 
...... 
iptables $TYP -A PREROUTING  -i $IFEXT                -j  PRE_EXT 

.......

iptables $TYP -A PRE_EXT -m set --match-set BLOCK_COUNTRY src -j MARK --set-mark 97 
iptables $TYP -A PRE_EXT -m mark --mark 97    $OPTLIM         -j LOG --log-tcp-options --log-prefix 'MSG=COUNTRY_PRE ' 
iptables $TYP -A PRE_EXT -m mark --mark 97                    -j DROP 
......

Le seul problème pour moi c'est que les données récupérées depuis IP2LOCATION ne sont pas en format CIDR mais sous forme de "ranges" tels que : 192.168.1.0-192.168.3.255 ce qui n'est pas exploitable facilement avec des "sets" qui préfèrent la notation CIDR. 
Heureusement quelqu'un a inventé et réalisé "ipcalc" qui réalise ce type d'opérations en un tour de main et si le range fourni ne peut être exprimé en une seule expression il en fournit plusieurs qui réalisent le truc, c'est tout simplement génial.

Afin d'automatiser la récupération des données et la construction du set j'ai réalisé un petit groupe de scripts qui réalisent les opérations suivantes :

  • Récupération du fichier sur le site IP2LOCATION
  • Dé-zipper les données
  • Reformater les données reçues pour les soumettre à "ipcalc"
  • Les soumettre à la sagacité d'ipcalc
  • Mettre en forme les résultats pour charger un fichier "set" utilisable avec : 
    "ipset --restore MON_SET < Le_fichier_formaté"

Le fichier de configuration est assez simple et j'y ai inséré quelques commentaires pour faciliter le remplissage.

Le tout est disponible ici sous forme de "tar.gz". 
Ce paquet est à installer dans un petit endroit douillet d'où il sera facile à utiliser. 
Le paramétrage "exemple" est assez sévère pour beaucoup de pays mais ce site en français intéresse peu russes et chinois (bien qu'ils scannent régulièrement le serveur) et d'autres qui ne visent qu'à pirater un site de plus pour lui faire subir toutes sortes de choses désagréables ou même miner du bitcoin ... 
Une autre partie du filtrage est réalisé par Suricata et Modsecurity, chaque individu mal intentionné qui est pris dans le filet permet d'ajouter de nouvelles règles de filtrage ...

Scripts IPSET quelques exemples

Scripts IPSET quelques exemples jpp

Script de récupération des fichiers "emerging threats" et de création du set IP.

#!/bin/bash
#
# Creation IPSET depuis emergingthreat
#
# compromised-ips.txt
# rbn-malvertisers-ips.txt
# emerging-Block-IPs.txt
# ==============================================================================
SORTIE ()
{
DELFIC LISTE
DELFIC LISTE_TMP
DELFIC FICH01
DELFIC FICH02
DELFIC FICH03
 
if [ $1 -ne 0 ]
   then
echo ' '
echo '=========> Sortie en erreur code : '$1
   else
echo ' '
echo 'Sortie OK'
fi
exit $1
}
DELFIC ()
{
if [ -f "$1" ]
   then
rm -f $1
fi
}
#
# Charge liste des IP recues
# --------------------------
CHARGE_IP ()
{
ret=0
NBR=0
export NBR
echo 'A traiter : '$(wc -l LISTE)
#
# Tri pour elminier les doublons
#
sort -u -t\. -k1n -k2n -k3n -k4n LISTE | while read ADDR 
do
NBR=$(expr $NBR + 1)
/sbin/ipset --add $SET $ADDR
ret=$?
if [ $ret -ne 0 ]
    then
echo 'ERREUR : '$ret' NBR='$NBR
return $ret
fi
done
return $ret
}
# cas des fichiers ne contenant que des IP
# ----------------------------------------
IPSIMPLE ()
{
cd /var/tmp
wget $1 --output-document=LISTE
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Fichier en echec : ('$1')'
return $ret
fi
if [ ! -f LISTE ]
   then
echo 'LISTE inexistant' 
return 100
fi
NBR=$(wc -l LISTE)
echo 'A charger '$NBR' de fichier : '$1
return $ret
}
#
# Cas des fichiers avec commentaires
# et même des reseaux en notation CIDR
# ------------------------------------
IPCOMMENTE ()
{
cd /var/tmp
wget $1 --output-document=LISTE_TMP
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Fichier en echec : ('$1')'
return $ret
fi
if [ ! -f LISTE_TMP ]
   then
echo 'LISTE_TMP inexistant' 
return 100
fi
#
# On elimine les '/CIDR' et les commentaires
#
grep -v '/' LISTE_TMP | awk -f /etc/reseau/CRE_SET_IP.aw1 >LISTE
#
# On garde (a part) les réseaux, sans commentaires
#
grep '/'    LISTE_TMP | awk -f /etc/reseau/CRE_SET_IP.aw1 >LISTE_NET
 
NBR=$(wc -l LISTE)
echo 'A charger '$NBR' de fichier : '$1
return $ret
}
# =============================================================================
SET=W_BLACK_IP
trap "SORTIE" 1 23 4 5 6 7 8 9 10 11 12 13 14 15
cd /var/tmp
DELFIC LISTE_NET
/sbin/ipset -X $SET
/sbin/ipset --create $SET iphash --hashsize 50000
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Impossible creer '$SET
SORTIE 99
exit 99
fi
#
# Get the file for compromised IP
# -------------------------------
FICHIER=http://rules.emergingthreats.net/blockrules/compromised-ips.txt
IPSIMPLE $FICHIER
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur fichier '$FICHIER
SORTIE 1
exit 1
fi
mv LISTE FICH01
 
#
# Get the file for Bad Guys
#
FICHIER=http://rules.emergingthreats.net/blockrules/rbn-malvertisers-ips.txt
IPSIMPLE $FICHIER
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur fichier '$FICHIER
SORTIE 2
exit 2
fi
mv LISTE FICH02
#
# Get the file for IP to block
#
FICHIER=http://rules.emergingthreats.net/fwrules/emerging-Block-IPs.txt
IPCOMMENTE $FICHIER
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur fichier '$FICHIER
SORTIE 3
exit 3
fi
mv LISTE FICH03
#
# Concatener les trois fichiers, trier, sans doubles
#
mv FICH01 LISTE_TMP
cat FICH02 >>LISTE_TMP
cat FICH03 >>LISTE_TMP
sort -u -t\. -k1n -k2n -k3n -k4n LISTE_TMP >LISTE
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur sur SORT'
SORTIE 4
exit 4
fi
#
# Charger le SET
#
CHARGE_IP 
/sbin/ipset -L $SET | sort -t\. -k1n -k2n -k3n -k4n
SORTIE 0
 
Le script AWK associé.
BEGIN {
}
{
IGN = 0;
if ( match($0,"#") ) { IGN = 1; }
if ( length($0) < 6 )   { IGN = 1; }
 
if ( IGN == 0 )
   { print $0;
   }
}
 
Script d'insertion des adresses réseau ( format ADR CIDR).
#!/bin/bash
#
# ============================================================================
SORTIE ()
{
DELFIC LISTE
DELFIC LISTE_TMP
DELFIC LISTE_NET
 
if [ $1 -ne 0 ]
   then
echo ' '
echo '=========> Sortie en erreur code : '$1
   else
echo ' '
echo 'Sortie OK'
fi
 
exit $1
}
DELFIC ()
{
if [ -f "$1" ]
   then
rm -f $1
fi
}
#
# Charger le SET
# --------------
IPNET ()
{
/sbin/ipset --add $SET $ADDR'/'$MASK
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur IPSET code : '$ret
fi
return $ret
}
# ==========================================================================
SET=W_BLACK_NET
trap "SORTIE" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 
if [ ! -f /var/tmp/LISTE_NET ]
   then
echo 'LISTE_TMP absent dans /var/tmp'
SORTIE 1
exit 1
fi
 
# set -x
 
/sbin/ipset --destroy $SET
 
/sbin/ipset --create $SET nethash --hashsize 4096 
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Impossible creer '$SET
SORTIE 99
exit 99
fi
 
#
# Constitution LISTE 
# concatener liste reseau de CRE_SET_IP
# plus liste perso
# et tri sans doubles
#
cd /var/tmp
cp LISTE_NET LISTE_TMP
cat /etc/reseau/LISTE_IP >>LISTE_TMP
sort -u -t\. -k1n -k2n -k3n -k4n LISTE_TMP >LISTE
ret=$?
if [ $ret -ne 0 ]
   then
echo 'ERREUR SUR SORT'
SORTIE 2
exit 2
fi
 
echo 'A charger : '$(wc -l LISTE)
#
# Chargement des SET reseaux
#
cat LISTE | sed 's!/! !' | while read ADDR MASK
do
case "$MASK" in
2[0-9]) IPNET    $ADDR $MASK
ret=$?
;;
1[2-9]) IPNET    $ADDR $MASK
ret=$?
;;
6|7|8|9) IPNET    $ADDR $MASK
ret=$?
;; 
*) echo '????? ('$MASK')'
ret=9
;;
esac
if [ $ret -ne 0 ]
  then
echo 'Erreur trt code : '$ret
SORTIE $ret
exit $ret
fi
done
 
/sbin/ipset -L $SET
 
SORTIE 0
 
Script d'enchainement global :
#!/bin/bash
#
RAC=/etc/reseau
 
$RAC/CRE_SET_IP
ret=$?
if [ $ret -ne 0 ]
   then
exit $ret
fi
 
$RAC/CRE_SET_NET
ret=$?
if [ $ret -ne 0 ]
   then
exit $ret
fi
 
/sbin/ipset swap W_BLACK_IP BLACK_IP
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur SWAP BLACK_IP'
exit $ret
fi
/sbin/ipset --destroy W_BLACK_IP
 
/sbin/ipset swap W_BLACK_NET BLACK_NET
ret=$?
if [ $ret -ne 0 ]
   then
echo 'Erreur SWAP BLACK_NET'
exit $ret
fi
/sbin/ipset --destroy W_BLACK_NET
 
exit 0
 
 

IPSET: quelques statistiques

IPSET: quelques statistiques jpp

Mon firewall fonctionne avec plusieurs "Sets" gérés par ipset et permet de rejeter directement un certain nombre de connexions le plus souvent indésirables ou qui ne lisent pas le français ! 
Le "remplissage" des sets a quelque peur évolué au cours du temps ... en fonction des analyses. 
J'ai quelques scripts qui analysent les résultats du firewall à travers les données présentes dans syslog. 
J'ai réalisé un premier tableau statistique en juin 2014 et j'ai voulu refaire la même analyse en octobre 2016, j'ai été surpris moi-même des résultats, l'accès à Internet s'est vraiment répandu dans le monde et énormément d'adresses IP différentes viennent "titiller" nos petites machines :

On remarque tout de suite le nombre de pays présents en 2016, beaucoup plus élevé qu'en 2014 (dommage j'ai perdu cette page), on passe de quelques dizaines de pays à quasiment l'intégralité du monde ! 
Il est vrai que mes critères de rejet sont maintenant beaucoup plus sévères (plus de ports "interdits") et utilisent plus de listes de "mauvaises"  IP et par ailleurs bloquent systématiquement plus de pays (Chine, Russie ... et les petits nouveaux Vietnam et Brésil).

Nftables : remplacant de Iptables

Nftables : remplacant de Iptables jpp

NOTE février 2022 : CE "LIVRE" EST TOUJOURS EN COURS DE REALISATION. 
Le noyau utilise Nftables mais, par manque de temps, j'utilise toujours l'interface iptables + ipset, pour le moment cela fonctionne encore très bien. 
En plus je n'ai pas encore bien compris la philosophie sous tendue par Nftables et j'ai du mal à concevoir un pare-feu à la fois simple, complet et facile à maintenir. 
Nouveauté Mai 2016 : utilisation notation CIDR et intervalles dans un "set nommé", voir l'article spécifique.

"NFTABLES" :

C'est le remplaçant prévu des commande IPTABLES et IPSET utilisées par tous les parefeux sour Linux. 
Le développement ne semble pas hyper actif ni réactif et de nombreuses commandes ne sont pas encore, à mon goût, complètes, notamment au niveau des "sets" (remplaçants de Ipset) ou suffisament souples. 
Tout est prêt au niveau du noyau Linux depuis déjà quelques versions (3.16 en principe) mais je pense que pour des tests (NFTABLES ne semble pas encore prêt pour mise en exploitation) il vaut mieux utiliser une version très récente du noyau. 
Ici j'utiliserai une 3.19-rc6, la dernière disponible au moment de ces tests. 
Il faut utiliser un moyau compilé avec tous les modules spécifiques à NFTABLES, malheureusement dans "make menuconfig" les sifférentes options sont un peu dispersées. Il faut aussi se rappeler que NFTABLES concernera IpV6 aussi bien que IpV4, donc configurer le tout.

Il faut avoir configuré dans le noyau (>= 3.16, ici 3.19) les extensions pour "nftables": 
   <M> Netfilter nf_tables support 
   <M>   Netfilter nf_tables mixed IPv4/IPv6 tables support 
   <M>   Netfilter nf_tables IPv6 exthdr module 
   <M>   Netfilter nf_tables meta module 
   <M>   Netfilter nf_tables conntrack module 
   <M>   Netfilter nf_tables rbtree set module 
   <M>   Netfilter nf_tables hash set module 
   <M>   Netfilter nf_tables counter module 
   <M>   Netfilter nf_tables log module 
   <M>   Netfilter nf_tables limit module 
   <M>   Netfilter nf_tables masquerade support 
   <M>   Netfilter nf_tables redirect support 
   <M>   Netfilter nf_tables nat module 
   <M>   Netfilter nf_tables queue module 
   <M>   Netfilter nf_tables reject support 
Ajouter Ethernet bridge nf_tables support 
--- Ethernet Bridge nf_tables support    
  <M>   Netfilter nf_table bridge meta support 
  <M>   Netfilter nf_tables bridge reject support

Il est conseillé de charger tous les modules nécessaires au démarrage en constituant une liste des modules dans un fichier dédié (ici nftables.conf) dans /etc/modules-load.d pour une Debian "Testing" ou dans le fichier /etc/modules pour une Debian "stable". 
Les modules se situent dans /lib/modules/$(uname -r)/kernel/net/netfilter et commencent presque tous par "nft"  sauf les deux plus importants "nf_tables_inet" et "nf_tables". 
Liste des modules chargés : 
nf_tables 
nf_tables_inet 
nft_chain_nat_ipv6 
nft_chain_nat_ipv4 
nft_chain_route_ipv6 
nft_chain_route_ipv4 
nft_counter 
nft_ct 
nft_exthdr 
nft_hash 
nft_limit 
nft_log 
nft_masq 
nft_meta 
nft_nat 
nft_queue 
nft_rbtree 
nft_redir 
nft_reject_inet 
nft_reject 
nft_reject_ipv4 
nft_reject_ipv6 
On sera ainsi parés pour toutes les éventualités.  
 

Quelques références : 
http://wiki.gentoo.org/wiki/Nftables 
http://wiki.nftables.org/wiki-nftables/index.php/Main_Page 
 

NFTABLES : un peu de vocabulaire

NFTABLES : un peu de vocabulaire jpp

Aucune "table" n'est définie par défaut comme avec "iptables", c'est à vous de les définir ! 
Rappel : 
Plus de différence entre IPV4 et IPV6, tout peut être traité dans le même flot, si on utilise des tables "inet", par défaut c'est "ip" (IPV4) qui est choisi, on peut aussi utiliser "ip6" pour du spécifique IPV6. 

Commandes disponibles : 
list 
  ruleset 
  tables [famille] 
  table [famille] <nom> 
  chain [famille] <table> <nom> 
add 
  table [famille] <nom> 
  chaine [famille] <table> <nom> [paramètres de la chaîne] 
  rule [famille] <table> <chaine> <paramètres de la règle> 
  element [famille] <table> <set> { 1..n elements } 
table [famille] <nom> (raccourci pour "add table`) 
insert 
  rule [famille] <table> <chaine> <paramètres de la règle> 
delete 
  table [famille] <nom> 
  chain [famille] <table> <nom> 
  rule [famille] <table> <numero handle> 
  set [famille] <table> <set>     : il ne doit plus être référencé 
  element [famille] <table> <set> { 1..N elements a enlever } 
flush 
  table [famille] <nom> 
  chain [famille] <table> <nom> 

Remarques : 
La famille "ip" (ipv4) est prise par défaut. 
Attention à la syntaxe de "list" "list tables" et "list table ENTREE". 
Liste des familles de "tables" et l'outil iptables correspondant 
ip            iptables 
ip6          ip6tables 
inet         iptables and ip6tables 
arp          arptables 
bridge     ebtables 
Liste des "hooks" existants, tiens tiens ! Les noms me rappellent quelque chose : 
INPUT                    paquet entrant dans le système local 
OUTPUT                paquet sortant du système local 
FORWARD            paquet traversant 
PREROUTING      paquet entrant 
POSTROUTING    paquet sortant 
Liste des "types" de tables existants, là aussi les noms semblent familiers : 
filter        Valeur par défaut 
nat 
route      (mangle), ne semble utilisable qu'avec le hook "output". 
Ordres supportés par la commande "table" 
add 
delete 
list 
flush 
Ordres supportés par la commande "chain" : 
add 
create 
delete 
list 
flush 
rename 
Ordres supportés par la commande "rule" : 
add     ajoute une règle en fin de chaîne 
insert    ajoute une règle en début de chaîne 
delete    détruit une règle, utilisé avec un "handle" cf "nft -a list ...."

Ordres supportés par la commande "ruleset" : 
flush   efface tout 
list       liste tout

Destination des paquets 
accept 
reject 
drop 
snat 
dnat 
log 
counter 
return 
jump    <chaine> 
goto     <chaine> 

Quelques "mots clefs" pour les règles : 
oif       interface sortie suivi d'un numéro 
iif       interface entree suivi d'un numéro 
oifname    nom de l'interface de sortie 
iifname nom de l'interface d'entree 
type    suivi d'un type ICMP par exemple "echo-request" 
protocol tcp, udp ... 
daddr    adresse destination 
saddr    adresse source 
dport    port de destination 
sport    port source 
ct         connexion tracking + state ( NEW, ESTABLISHED, RELATED, INVALID) 
C'est un bon début.

NFTABLES : premier test Debian testing

NFTABLES : premier test Debian testing jpp

Pour ce premier essai j'ai utilisé les paquets disponibles à ce jour sur "testing" : 
libjansson4_2.7-1_amd64.deb 
libmxml1_2.6-2_amd64.deb 
libnftnl0_1.0.3-4_amd64.deb 
nftables_0.4-2_amd64.deb 
Une fois tout ce petit monde en place on peut commencer à tenter de se servir de ce nouvel outil remplaçant désigné de "iptables". 
Références : 
Accéder à "http://people.netfilter.org/wiki-nftables/index.php/Main_Page" pour tous les détails sur nftables. 
Un autre Wiki bien fait est celui d'Archlinux accessible à "https://wiki.archlinux.org/index.php/Nftables".

Premier essai : 
"nft list tables" ou "nft list tables ip6" ne donnent aucune sortie puisque avec Nftables rien n'est créé par défaut ! 
Par contre dès qu'une chaine existe une sortie est fournie : 
nft add table entree     
nft list tables 
--> 
table entree 
L'ensemble a donc l'air parfaitement fonctionnel. On va pouvoir passer à des choses plus sérieuses.

NFTABLES : quelques tests

NFTABLES : quelques tests jpp

Points importants :

  • Nftables est prévu pour fonctionner avec l'option "-f" avec laquelle les données sont contenues dans un fichier. Ce fichier peut être généré par la commande "list" et utilisé ensuite en entrée de la commande "nftables -f ".
  • A l'origine, rien n'est créé, les différentes tables et chaines existant par défaut avec "iptables" n'existent pas ici par défaut. Il faut donc créer toutes les "tables" et y attacher toutes les "chaines" nécessaires.

Quelques exemples : 
 

  • Création d'une table "ENTREE" (Ipv4 par défaut le parametre "ip" étant omis) :

nft add table ENTREE 

Liste des tables : 
nft list tables 
--> table ENTREE

  • Ajout d'une table "SORTIE"

nft add table SORTIE 
nft list tables 
--> 
table ENTREE 
table SORTIE

  • Destruction de la table "SORTIE" :

nft delete table SORTIE 

nft list tables 
--> 
table ENTREE 

Ajout d'une chaine nommée "INTERNE" dans la table ENTREE (type filter et Ipv4 par défaut) : 
nft add chain ENTREE INTERNE 

Destruction de la chaine "INTERNE" de la table ENTREE 
nft delete chain ENTREE INTERNE 

Addition d'une règle dans notre table ENTREE (à la fin) : 
nft add table ENTREE 
nft add chain ENTREE INTERNE 
nft add rule ENTREE INTERNE ip saddr 127.0.0.1 accept 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ip saddr 127.0.0.1 accept 
    } 
}

Remarque : On aurait pu ici utiliser aussi "nft list ruleset" pour lister l'ensemble des tables.

  • On accepte le port 22

nft add rule ENTREE INTERNE tcp dport 22 accept 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ip saddr 127.0.0.1 accept 
         tcp dport ssh accept 
    } 
}

  • Insérer une règle en début de chaîne

nft insert rule ENTREE INTERNE ct state established, related accept 
On fait une liste avec les numeros de "handle" (option "-a") : 
nft -a list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 5 
         ip saddr 127.0.0.1 accept # handle 2 
         tcp dport ssh accept # handle 4 
    } 
}

  • On ne peut détruire une règle que par son numéro (handle), Ici on détruit la règle 4

nft delete rule ENTREE INTERNE handle 4 
nft -a list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 5 
         ip saddr 127.0.0.1 accept # handle 2 
    } 
}

  • On sauvegarde notre table :

nft list table ENTREE >SAUVE

  • On efface tout

nft delete table ENTREE 
nft list tables 
--> ne retourne rien

  • On restaure notre jeu de test

nft -f sauve 
nft list table ENTREE 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept 
         ip saddr 127.0.0.1 accept 
    } 
} 
On retrouve notre table telle qu'avant destruction, la sauvegarde d'un jeu de règles et sa restauration sont d'une belle simplicité.

  • On rajoute une autorisation pour SSH et on logue la connexion :

nft add rule ENTREE INTERNE tcp dport ssh log prefix \"MSG=Connect SSH \" 
nft -a list ruleset 
--> 
table ip ENTREE { 
    chain INTERNE { 
         ct state established,related accept # handle 2 
         ip saddr 127.0.0.1 accept # handle 3 
         tcp dport ssh log prefix "Connect SSH" # handle 4 
    } 
}

NFTABLES : on passe par la case COMPIL

NFTABLES : on passe par la case COMPIL jpp

Les tests de "map" et autres joyeusetés n'ayant pas fonctionné avec les versions "standard" il faut passer par la case "compil" et récupérer les morceaux dans un petit répertoire bien tranquille (pour moi "/usr/src/PGM/BUILD/NFT"): 
git clone git://git.netfilter.org/nftables.git 
git clone git://git.netfilter.org/libmnl.git 
git clone git://git.netfilter.org/libnftnl.git 

Pré-requis : 
bison 
flex 
libgmp-dev 
libreadline-dev 
libmnl0 
libmnl-dev 
Remarque : il peut y avoir d'autres pré-requis, la machine ayant servi à la compil est une Debian "stable" avec "backports" qui a déjà beaucoup vécu et comporte déjà pas mal de packages "-dev".

Compilation de "LIBMNL" le script :

#!/bin/bash

cd NFT/libmnl ...... le répertoire source 
zzz=$(pwd) 
yyy=$(basename $zzz) 
case $yyy in 
    libmnl)        echo 'OK' 
            ;; 
    *)        echo 'pas dans libmnl' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure libmnl 
CONFOPT=" --prefix=/usr/local/libmnl --exec-prefix=/usr/local/libmnl "

./configure ${CONFOPT} 2>&1 | tee LOG.CONF

make 2>&1 | tee LOG.MAKE

Ne pas oublier ensuite (en "root") le "make install". 

Compilation de "LIBNFTNL" le script :

#!/bin/bash

cd NFT/libnftnl 
zzz=$(pwd) 
yyy=$(basename $zzz) 
case $yyy in 
    libnftnl)        echo 'OK' 
            ;; 
    *)        echo 'pas dans libnftnl' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure libnftnl 
CONFOPT=" --prefix=/usr/local/libnftnl --exec-prefix=/usr/local/libnftnl " 
CONFOPT=${CONFOPT}' LIBMNL_LIBS=/usr/local/libmnl ' 
CONFOPT=${CONFOPT}' LIBMNL_CFLAGS=/usr/local/libmnl'

./configure ${CONFOPT} 2>&1 | tee LOG.CONF

make 2>&1 | tee LOG.MAKE

Ne pas oublier (toujours) le "make install" en "root". 

Une fois tout vérifié j'ai copié : 
/usr/local/libmnl/lib/libmnl.* dans  /lib/x86_64-linux-gnu 
/usr/local/libnftnl/lib/libnftm* dans /lib/x86_64-linux-gnu 

et vérifié que la version Debian de "nft" fonctionnait toujours --> OK 

Compilation de "NFTABLES" le script :

#!/bin/bash

PKG_CONFIG_PATH=${PKG_CONFIG_PATH}':/usr/local/libnftnl/lib/pkgconfig' 
PKG_CONFIG_PATH=${PKG_CONFIG_PATH}':/usr/local/libmnl/lib/pkgconfig' 
export PKG_CONFIG_PATH

cd /usr/src/PGM/BUILD/NFT/nftables 
zzz=$(pwd) 
yyy=$(basename ${zzz}) 
case ${yyy} in 
    nftables)    echo 'OK' 
            ;; 
    *)        echo 'pas dans nftables' 
            exit 
            ;; 
esac

make clean

./autogen.sh

# configure nftables

CONFOPT=' --prefix=/usr/local/nftables --exec-prefix=/usr/local/nftables/bin ' 
CONFOPT=${CONFOPT}' --includedir=/usr/include ' 
CONFOPT=${CONFOPT}' LIBMNL_LIBS=/usr/local/libmnl/lib/libmnl.so  ' 
CONFOPT=${CONFOPT}' LIBNFTNL_LIBS=/usr/local/libnftnl/lib/libnftnl.so  '

./configure ${CONFOPT} 2>&1 | tee LOG.CONFIGURE

make 2>&1 | tee LOG.MAKE

echo 'PKG_CONFIG_PATH=('${PKG_CONFIG_PATH}')'

echo '' >./doc/nft.8

Ne pas oublier (encore) le "make install", puis on expédie "/usr/local/nftables/bin/sbin/nft" dans "/usr/sbin".

On pourra ainsi reprendre nos essais ... avec la dernière version.

NFTABLES : version compilée tests

NFTABLES : version compilée tests jpp

Cette petite série de tests a été conduite avec la version compilée localement de "nft" car les autres versions essayées ne "comprenaient" pas certaines nouvelles fonctionnalités.

Premier test : réaliser du NAT : 
Si la table existe un petit "flush" remet tout dans l'ordre, si la table n'existe pas cela déclenche une erreur fatale et rien n'est fait ! C'est très dommage pour l'atomicité des opérations. 
Pour être tranquilles il faut donc tester l'existence de la table et la créer (vide) si besoin. Cela peut se faire avec le petit bout de script suivant :


# On teste l'existence de la table !  
# 
nft list table ip POSTROUTE 2>/dev/null >/dev/null 
ret=$? 
# 
# On crée la table si elle n'existe pas !!! 
# 
if [ $ret -ne 0 ] 
    then 
       nft add table ip POSTROUTE 
fi 
On peut maintenant lancer la suite du script avec : 
nft -f 
Mon fichier contient dans notre cas : 
flush table ip POSTROUTE;  
table ip POSTROUTE { chain DEFAUT { 
type nat hook postrouting priority 0; 
ip saddr 192.168.2.0/24 masquerade; 
ip saddr 192.168.3.0/24 masquerade; } }


On peut noter la création d'une table avec un nom "en français" pour faire plus beau !

Deuxième test, effectuer une redirection transparente de HTTP/HTTPS : 
Tous les "clients" HTTP à destination de l'extérieur sont "interceptés". Seules les adresses précisées subissent une redirection du HTTPS, le "set" GO_HTTPS contiendra les adresses sélectionnées. 
On ajoute des compteurs pour suivre le travail. 

flush table ip PREROUTE; 
table ip PREROUTE { chain DEFAUT { type nat hook prerouting priority 0; 
     ip daddr != 192.168.2.1/24 tcp dport 80 counter redirect to 3127 
     ip daddr != 192.168.2.1/24 
     ip saddr @GO_HTTPS tcp dport https counter redirect to 3129 
     } 
set GO_HTTPS { type ipv4_addr; }; 
}

Ensuite on ajoute les adresses au set :

nft add element PREROUTE GO_HTTPS { 192.168.2.9 } 
nft add element PREROUTE GO_HTTPS { 192.168.2.10 , 192.168.2.8} 
et on vérifie : 
nft list set PREROUTE GO_HTTPS 
set GO_HTTPS { type ipv4_addr elements = { 192.168.2.9, 192.168.2.8, 192.168.2.10} }

Troisième test : envoyer des paquets vers une "queue" en espace utilisateur par exemple pour un IPS : 
Ici l'IPS est Suricata, on mettra un compteur sur chaque règle. 
On utilise la "famille" inet pour intercepter aussi IPV6 et une priorité de -100 pour passer avant les autres chaines. On ne peut pas utiliser le type "route" qui ne fonctionne pas avec un autre "hook" que "output".

delete table inet IPS; 
table inet IPS       { 
    chain ENT_150    { type filter hook input         priority -100; 
            counter queue num 0 
            } 
     
    chain SOR_150    { type filter hook output        priority -190; 
            counter queue num 0 
            } 

    chain FOR_150   { type filter hook forward    priority -100; 
            counter queue num 1-2; 
            } 
}

Après quelques accès internet la commande " nft list table inet IPS " renvoie :

table inet IPS { 
    chain ENT_150 { 
         type filter hook input priority -100; 
         counter packets 1676 bytes 490186 queue num 0 
    } 

    chain SOR_150 { 
         type filter hook output priority -190; 
         counter packets 1969 bytes 398894 queue num 0 
    } 

    chain FOR_150 { 
         type filter hook forward priority -100; 
         counter packets 0 bytes 0 queue num 1-2 
    } 
}


Des paquets "locaux" sont bien passés dans la queue 0 et l'un d'entre eux a été "repéré" par Suricata car il contenait un mot de passe de connexion sur un site WEB.

A suivre ....

NFTABLES : sets, maps et dictionnaires

NFTABLES : sets, maps et dictionnaires jpp

NFTABLES :  

Nftables dispose d'un arsenal de modèles permettant de simplifier la réalisation des tests en utilisant des notions analogues à celles des "Ipsets" mais présentant quelques perfectionnements intéressants. 
Il existe plusieurs types de tables dans deux saveurs :

  • Gadgets "nommés", décrits "à part" et utilisés par une règle.
  • Gadgets "inline" non nommés qui peuvent faire partie d'une règle.

Les gadgets nommés permettent de réaliser des ajouts/suppressions "en ligne" gràce aux opérations sur les éléments (de manière analogue à "ipset").

Un certain nombre de "types" de données sont admis pour les éléments :

  • ipv4_addr/ipv6_addr      Adresses IPV4 ou IPV6, avec option "flags interval" pour notation CIDR ou intervalles, nécessite noyau >= 4.7-rc2 et dernière version nftables (à charger et compiler).
  • ether_addr                        Adresse MAC
  • inet_service                     Ports, sous forme numérique ou texte pour les plus connus (ssh, http, https ...)
  • inet_proto                         Prototype : ICMP, TCP ....
  • mark                          Marque posée par une autre règle.

Ces différents types répondent à la plupart des besoins, il manquerait toutefois la possibilité de désigner un réseau sous forme CIDR en plus des adresses IP. Cette possibilité existe dans les "vmap" non nommées, mais pas pour cellles nommées ? Un oubli sans doute ? 
Juin 2016 : 
Cet oubli est corrigé dans la dernière version de Nftables et nécessite un kernel >= 4.7-rc2, la syntaxe de la création du set est légèrement différente, il faut ajouter "flags interval" dans la déclaration du set nommé qui devient : 
set MONSET ( type ipv4-addr; flags interval)

Une autre nouveauté intéressante de ces "gadgets" est donnée par le deuxième élément possible : l'action à réaliser si l'élément "matche", drop, jump table, goto table, accept ..... Cela ouvre des horizons assez sympatiques. 
Par exemple on peut en une seule règle refouler toutes les IP d'un pays à l'aide des listes fournies par différents sites par exemple "ipdeny.com". On peut récupérer la liste des réseaux concernés, mettre en forme la règle (un simple script AWK le fait très bien, générer un fichier au "bon" format et utiliser ce fichier dans un script "Nftables" à l'aide de l'instruction "include" (je vous avais bien dit que la syntaxe Nftables se rapprochait d'un langage !). Dommage d'être obligé d'utiliser un bloc de données non nommé car si on en a besoin plusieurs fois .... par exemple en Entrée et en Forward ou en sortie. 
Exemple de syntaxe pour la règle ci dessus :

add rule INPUT ENT_100 ip saddr vmap { 
1.0.1.0/24 : drop, 
1.0.2.0/23 : drop, 
1.0.8.0/21 : drop, 
........ 
254.254.0.0/24 : drop }

Qui ajoute une règle à la chaine "ENT_100" de la table "INPUT".

Ce fichier est appelé par  l'include suivant dans le script Nftables de création de la table "INPUT" : 
#include "le_chemin_de_mon_fichier" 
Autre petit exemple, répartir sur plusieurs "chaînes" les entrées en fonction de l'interface d'origine pour les compter, on utilisera une "vmap" :

flush table ip ENTREE;

table ip ENTREE { 
    chain INP_INT { 
         counter 
    } 
    chain INP_EXT { 
        counter 
    } 
    chain INP_LOC { 
        counter 
    } 
    chain DEFAUT { 
         type filter hook input priority 0; 
         iifname vmap { br0 : jump INP_EXT, br1 : jump INP_INT, 
                        lo  : jump INP_LOC  } ; 
    } 
}

Après quelques instants on liste :

nft list table ENTREE 
table ip ENTREE { 
    chain INP_INT { 
         counter packets 53 bytes 8010 
    } 
    chain INP_EXT { 
         counter packets 2 bytes 64 
    } 
   chain INP_LOC { 
         counter packets 12 bytes 774 
    }    chain DEFAUT { 
         type filter hook input priority 0; 
         iifname vmap { "lo" : jump INP_LOC, "br1" : jump INP_INT, "br0" : jump INP_EXT} 
    } 
}

C'est bien ce qui était demandé...

Attention en manipulant les sets il existe quelques problèmes lors de la mise à jour d'une table contenant des sets, il est impossible de "flusher" une table tant qu'il y a un set, il faut détruire le set d'abord avant de faire le flush de la table sinon on arrive à un crash système. 
Ce problème est résolu pour les noyaux >= 4.0.0-rc4. 
 

NFTABLES : sets nommés en notation CIDR

NFTABLES : sets nommés en notation CIDR jpp

Juin 2016 : depuis la version 0.5 de Nftables, la dernière que j'ai chargée et testée, on peut créer des sets nommés en utilisant les intervalles et/ou une notation CIDR. Il faut, en plus de cette version récente, disposer d'un kernel >= 4.7-rc2 avec toutes les options "NFT_...." activées en modules. 
Exemple de création d'une table avec deux sets nommés, un en IPV4, l'autre en IPV6 :

table ip TEST      { 
   chain ENT_100    { type filter hook input    priority -100 ; 
            counter; 
            }

    set DISPAT     { type ipv4_addr; flags interval; };  # bien noter les deux ";"

    chain BIDON    { type filter hook input    priority 0; 
            counter; 
            }

    set EXAMPLE    { type ipv6_addr; }; 
}

On peut ensuite ajouter des éléments aux sets, par exemple :

add element TEST  DISPAT    { 192.168.2.2,192.168.2.4 }; 
add element TEST  DISPAT    { 192.168.3.0/24 }; 
add element TEST  DISPAT    { 192.168.0.0/24, 192.168.1.0/24 }; 
add element TEST  DISPAT    { 192.168.4.10 - 192.168.4.127 }; 
La commande de liste du set donne le résultat suivant : 
nft list set TEST DISPAT 
table ip TEST { 
    set DISPAT { 
        type ipv4_addr 
        flags interval 
        elements = { 192.168.0.0/23, 192.168.2.1, 192.168.2.2, 192.168.2.4, 192.168.3.0/24, 192.168.4.10-192.168.4.127} 
    } 
}

On peut remarquer la "fusion" réalisée automagiquement de "192.168.0.0/24, 192.168.1.0/24". 
IPV6 n'étant pas activé chez moi (ni chez mon FAI) je n'ai pas fait de tests sur les sets IPV6.

NtopNG et scripts pour sécurité

NtopNG et scripts pour sécurité jpp

NtopNG intercepte et stocke des tas de données sur tous les événements réseau traités, l'exploitation de ces données permet, outre quelques statistiques, de repérer des événements liés à la sécurité.

Premier exemple : 
Exploiter les alertes NtopNG, repérer les accès sur des ports non actifs (fermés ou filtrés). 
Une version plus récente est disponible ici.

Deuxième exemple : 
Repérer les scans de ports, même lents.

Exploiter les alertes NtopNG

Exploiter les alertes NtopNG jpp

Note : cette description "date" un peu et une version plus récente est disponible ici.

Exploiter les alertes générées par NtopNG. 
Les dernières versions de NtopNG permettent d'activer un suivi d'alertes. Ces alertes sont levées pour différentes raisons :

  • Accès depuis une adresse "blacklistée" par utilisation d'une liste du site Emergingthreats.
  • Tentative d'accès à un port fermé ou bloqué
  • Autres anomalies de comportement

Or ces alertes sont stockées dans une base de données Sqlite et donc très faciles à exploiter. 
Les tables comportent le même type de renseignements que celles enregistrant les flux dans une base de données plus traditionnelle. 
Les principales données sont :

  • Données temporelles    . timestamp, firstswitched, lastswitched
  • Données sur le client.    . cli_addr, cli_country (code pays), cli_port
  • Données coté serveur.    . srv_addr, srv_country, srv_port
  • Données quantitatives.    . cli2srv_bytes, srv2cli_bytes, cli2srv_packets, srv2cli_packets
  • Données "techniques".    . flags IP, blacklist ou pas, .....

La conservation de ces données est ajustable dans le logiciel selon différents critères dans le paramétrage de NtopNG. 
Il vaut mieux limiter un peu le volume car Sqlite n'est pas adapté aux gros volumes. 
On peut repérer à partir de ces données tout "hit" sur un port fermé et par exemple bloquer cette adresse avec un "ipset" bien placé dans un règle de pare-feu. 
Le petit script suivant permet de repérer ces adresses IP :

select min(first_switched),cli_addr 
from flows_alerts 
where cli_addr not like '192.168.1%' 
  and cli_addr not like '192.168.2%' 
  and cli_addr not like '192.168.3%' 
  and cli_addr not like '%:%'            -- éliminer IPV6 
  and cli_addr not like '0.0.0.0' 
  and srv_port < 32768 
  and first_switched > ${DATEMIN} 
group by cli_addr 
order by first_switched;

Il faut éliminer : 
- les enregistrements "anciens", la date minimum est au format "epoch", j'utilise les deux dernières heures : 
    DATEMIN=$(date +%s) 
    DATEMIN=$(expr ${DATEMIN} - 7200) 
- les origines dans son propre réseau : 
- ceux qui utilisent des ports "client d'un service local", ici seuls les ports inférieurs à 32768 sont pris en compte. Voir ces limites avec la commande "sysctl -a | grep local_port_range" . 
Il est parfois un peu délicat de repérer les bases Sqlite car les noms de répertoires sont différents selon les machines. Pour moi le répertoire principal est /var/tmp/ntopng et les bases sont dans 
13/alerts/alerts_v7.db et 15/alerts/alerts_v7.db sur une machine, sur une autre machine les répertoires sont 1 et 3 donc très différents. 
Ce script est très rapide car la base Sqlite contient assez peu de rangs (moins de 5000) et peut être lancé par "cron" avec une fréquence importante pour alimenter régulièrement un "set" de blocage par IP.

Exploiter les alertes NtopNG V2

Exploiter les alertes NtopNG V2 jpp

NtopNG pour détecter les scans (V2).

Depuis plusieurs versions NtopNG utilise une petite base de données Sqlite pour stocker des données prises « au vol ». Au fil des versions le nombre de données, et de tables, a fortement augmenté. Certaines de ces données permettent de repérer les accès qui n’ont donné lieu à aucun transfert vers le « client » car ils tentaient un accès à un port fermé ou bloqué par le pare-feu. D'autres éléments indiquent des accès depuis des adresses "blacklistées".

A partir de ces données il est très facile, et rapide de repérer les scans de ports, même l’accès à un seul port est repérable. La base étant très légère (à la journée) les traitements sont très rapides et peuvent donc être exécutés souvent.

D’abord une mini description de la structure de ces bases de données situées dans /var/lib/ntopng dans une installation « « standard ».

L’organisation générale comporte 3 répertoires nommés : « -1 » « 0 » et « 1 ». chacun de ces répertoires contient plusieurs répertoires et nous nous intéresserons ici qu’à « alert ». 
Chacun de ces répertoires contient un fichier, ici « alert_store_v11.db » dont le nom varie, malheureusement, à chaque version. Les noms des colonnes ont aussi varié au cours des versions … 
En ouvrant ce répertoire dans SqliteBrowser on peu y voir la liste des tables et index.

Remarque : Il est normal que certains des 3 répertoires contiennent des tables vides … toute recherche doit donc concerner les trois répertoires. 
La table qui nous intéresse ici est « flow_alerts » dont les colonnes suivantes nous intéressent :

  • cli_ip et cli_port adresse et port de l’émetteur
  • srv_ip et srv_port adresse et port du destinataire

On y trouve d’autres colonnes intéressantes :

  • cli_name et srv_name les noms DNS
  • cli_country et srv_country les codes pays
  • cli_blacklisted et srv_blacklisted des indicateurs de qualité des adresses (0 ou 1) indiquant l’appartenance à une liste noire de l’adresse correspondante. Les listes noires sont maintenues à jour automatiquement et sont paramétrables dans l’interface Web de NtopNG, y compris leur fréquence de mise à jour?

Enfin les compteurs de la transmission en octets et paquets :

  • cli2srv_bytes / cli2srv_pkts et srv2cli_bytes / srv2cli_pkts ce sont principalement ces compteurs qui nous intéressent car une valeur à zéro implique le refus de transmission qui marque un port fermé ou bloqué par une règle de firewall.

Certaines colonnes telles is_cli_attacker , is_srv_attacker ou is_srv_attacker , is_srv_victim précisent les choses par leur valeur 0 je fais partie des gentils, 1 je suis un méchant !

Il est donc très facile de lister par des ordres SQL simples les adresses IP dont les accès n’ont donné lieu à aucun transfert en retour. 
Ensuite les adresses IP sont comparées aux « set » de "méchants" existants, si elles sont trouvées on abandonne car elles sont déjà bloquées, si elles ne sont pas trouvées elles sont stockées dans un set spécial d’attente, mais tout accès depuis une adresse présente dans ce set sera « dropé » par une règle iptables comme pour les adresses contenues dans les sets "permanents" de méchants.

Ce set est exploré toutes les heures et toute adresse présente depuis plus d’une heure est transférée dans un set permanent sauvegardé et détruite du set d’attente. 
Le transfert dans un set permanent entraîne par ailleurs l’analyse des accès liés à cette adresse sur les dernières 24 heures et l’envoi d’un message au site ABUSEIPDB.COM avec la liste des ports touchés pour faire profiter les autres de la découverte d’un vilain méchant et horrible qui scanne internet, probablement pour un but pas très honnête ...

Toutes ces opérations sont assez simples à réunir et quelques scripts, un peu de bash, de SQL et de mise en forme avec awk font l’affaire. 
Voir ci-dessous l'ordre SQL qui "va bien".

select min(first_seen),cli_ip from flow_alerts 
where cli_ip not like '192.168.1%'   and cli_ip not like '192.168.2%' 
  and cli_ip not like '192.168.3%'   and cli_ip not like '192.168.4%' 
  and cli_ip not like '%:%'          and cli_ip not like '0.0.0.0' 
  and srv_port < 32768 
  and tstamp > ${DATEMIN} 
  and srv_port not in (80,443) 
  and cli_port not in (liste de ports) 
group by cli_ip 
order by tstamp; 
.quit

DATEMIN est obtenu depuis le script bash : 
DATEMIN=$(date +%s) 
DATEMIN=$((${DATEMIN} - 3600 ))  # ou 7200 pour étendre ) 2 heures

Repérer les scans lents

Repérer les scans lents jpp

Repérer les scans "lents" avec NtopNG. 
SI vous stockez les données de flux dans une base Mysql avec une certaine durée il est possible de repérer les scans de ports, même lents, de manière simple à l'aide d'un ordre SQL simple. 
Cela permet de repérer les adresses IP qui scannent très lentement pour éviter d'être repérées trop facilement, et de les bloquer avec un "ipset" bien placé dans votre pare-feu. Attention les adresses IP sont stockées dans le format interne de Mysql et il faut utiliser les fonctions "inet_aton" et "inet_ntoa". 
Ici on sélectionne les IP qui ont "atteint" plus de 10 ports (sans données retournees) sur les 10 derniers jours :

select  inet_ntoa(IP_SRC_ADDR) SRC,inet_ntoa(IP_DST_ADDR) DST, 
        count(distinct L4_DST_PORT) NPORT 
from flowsv4 
where FIRST_SWITCHED > UNIX_TIMESTAMP(DATE_SUB(now(), interval 10 day)) 
  and IP_SRC_ADDR not between inet_aton('192.168.1.1') and inet_aton('192.168.3.255') 
  and L4_DST_PORT < 32768 
  and OUT_BYTES 0
group by 1,2,4 
having NPORT > 10 
order by IP_SRC_ADDR;

Ne pas oublier de ne sélectionner que les ports inférieurs à la limite sur votre système : 
sudo sysctl -a 2>/dev/null | grep local_port_range  
afin de ne pas bloquer de clients légitimes. 
Cet ordre permet de repérer les adresses IP d'origine de scans lents sur 10 jours (ou plus si votre historique est plus long) concernant plus de 10 ports différents. 
Il est très facile ensuite à partir de la liste obtenue de bloquer ces adresses en les intégrant dans un "set" exploité dans un pare-feu. 
L'exécution de ce script peut être assez longue selon le nombre de rangs contenus dans la table principale malgré un index favorable sur le timestamp, mais il peut être lancé quelques fois chaque jour sans surcharge excessive.

Ici ce type de recherche est exploité "manuellement" pour tenir à jour une liste d'adresses IP à éviter, voir article spécifique ici.

Listes adresses IP agressives

Listes adresses IP agressives jpp

Pour protéger l'accès à mes machines j'utilise plusieurs listes d'adresses IP réputées "BLACK", par exemple :

Il en existe pas mal d'autres mais celles-ci fournissent déjà une bonne protection et donnent chez moi plus de 2000 hits par jour. 
Une fois bien triées :

  • Les ip simples on élimine les doubles
  • Les sous-réseaux on les passe dans Ipcalc là aussi pour éliminer les doublons.

Ensuite les deux "paquets" sont chargés dans deux "sets" (un set IP et un set NET) et le tour est joué en utilisant ces sets pour filtrer INPUT,FORWARD et même OUTPUT.

Une autre méthode consiste à éliminer les réseaux en provenance de pays très laxistes sur la surveillance ou dont le piratage est un des piliers. On trouve ces renseignements par exemple sur le site http://www.ipdeny.com/ipblocks/data/countries/INITIALES_PAYS.zone 
Soit par exemple "http://www.ipdeny.com/ipblocks/data/countries/cn.zone" pour éliminer tous les chinois d'un coup ! 
Aujourd'hui j'utilise les données fournies par IP2location pour gérer cette partie "PAYS". La liste des pays actuellement "bloques" :

BAD_LAND_LIST = AR,BR,CL,CN,CO,EC,EG,GE,ID,IN,IR,KZ,LV,MN,MX,NG,PH,PK,PS,RU,SC,TR,VE,VN

Toutes ces adresses ou réseaux chargés dans des sets assurent une meilleure tranquillité !

Blocage intempestif

Blocage intempestif jpp

Petite mésaventure avec une de ces listes d'adresses, une de celles que j'utilise a eu l'idée saugrenue de mettre dans cette liste une adresse non routable dans une plage réservée aux réseaux privés (192.168.1.x). 
Lors de la dernière mise à jour cette adresse a donc été intégrée au pare-feu dans un "ipset" me causant quelques désagréments. 
Le premier à se rendre compte d'une anomalie a été Shinken qui m'a signalé que mon site Web (accédé en local) était devenu inaccessible. 
Après quelque recherche je me suis aperçu que les contrôles de Shinken étaient bloqués par le pare-feu (tous les refus sont enregistrés), la page des services était presque entièrement passée au "rouge". 
J'ai repéré assez rapidement l'adresse fautive et l'ai supprimée du "set" et Shinken s'est trouvé libéré. 
Il m'a fallu un peu plus de temps pour trouver l'origine du phénomène et ajouter un petit bout de code dans ma procédure ( tester range 192.168.1.0 à 192.168.3.255 dans mon cas) pour éviter ce type d'ennui à l'avenir. 
OUF !

Listes IP douteuses

Listes IP douteuses jpp

Note 15 juin 2021 : mises à jour :

  • Liste "IP_DOUTEUSES" actualisée plusieurs fois par jour 
    Suite à une erreur de manip la liste n'a pas été mise à jour sur le site du 13 avril au 15 juin 2021 !!! 
    C'est réparé ...
  • Liste "Speciale Web" (origine modsecurity) actualisée une à deux fois par jour
  • Liste "Spéciale Windows" actualisée une fois par jour 
    Une erreur de manip a bloqué la mise à jour sur le site du 13 avril au 15 juin 2021 !!! 
    C'est là aussi réparé et la liste sera mise à jour automatiquement chaque jour.

Note 23 Septembre 2019 : une fantaisie de "modsecurity" (liée au passage en Debian Buster ?) a gêné l'accès à la liste principale, c'est en principe réparé ...

Je tiens à jour pour mes besoins propres deux listes d'adresses IP "douteuses" ou franchement "hostiles", ces adresses sont repérées à partir des logs du système (via OSSEC par exemple), des données de Suricata, de Modsec, de NtopNG (scans lents) ou encore de l'analyse directe des logs de serveurs Web ou mail. 
J'ai utilisé pendant longtemps cette liste première liste "brute" pour remplir un "set" (ipset) permettant d'exécuter un drop pur et simple de tout ce qui provient d'une de ces adresses utilisées par d'infâmes personnages. Cette lisre s'ajoute à celles obtenus des listes déja citées et aux réseau de pays "bannis".
Cette liste, mise à jour souvent (au minimum deux fois par jour), peut être utilisée avec un set "ipset" dans un firewall "iptables" :

# pour ne pas permettre la sortie vers ces adresses 
iptables -t mangle -A PREROUTING  -o "internet" -m set --match-set BLOCK_TMP dst -j MARK --set-mark 99 
iptables -t mangle -A PREROUTING  -o "internet" -m mark --mark 99 -m limit --limit 30/h --limit-burst 10      -j LOG --log-tcp-options --log-prefix 'MSG=Le_message_desiré ' 
iptables -t mangle -A PREROUTING -A PRE_EXT -m mark --mark 99                -j DROP 
# pour ne pas permettre l'entrée depuis ces adresses 
iptables -t mangle -A PREROUTING  -i "internet" -m set --match-set BLOCK_TMP src -j MARK --set-mark 98 
iptables -t mangle -A PREROUTING  -i "internet" -m mark --mark 98 -m limit --limit 30/h --limit-burst 10      -j LOG --log-tcp-options --log-prefix 'MSG=Le_message_desiré ' 
iptables -t mangle -A PREROUTING -A PRE_EXT -m mark --mark 98                -j DROP

ou un set nommé dans un firewall "nftables." :

ip saddr @BLOCK_TMP log prefix " MSG=Le_message_désiré " drop

Pour chaque adresse un commentaire est fourni indiquant le principal problème lié à l'adresse, certains rangs récupérés de l'ancien fichier n'ont pas de commentaire indicatif. 
Certaines adresses sont munies d'un suffixe autre que /32 lorsque plusieurs adresses d'un même sous-réseau ont été repérées, ce sous  réseau est alors réputé "plein de pirates" ... ou faisant partie du réseau d'un FAI un peu trop "permissif". 
A l'occasion j'ai "modernisé" la méthode de gestion de ce "set" (à l'origine simple fichier) pour passer à une table dans une base de données (MariaDB) qui me permet "d'oublier" les adresses n'ayant pas donné signe de vie (dans les tables de NtopNG) depuis une date spécifiée en ne sélectionnant que les #180 jours précédents. Mes tables NtopNG étant actives depuis mi 2016 j'utilise actuellement ( juin 2020) la date de 2020/01/01 comme butée. La gestion est assurée par trois scripts :

  • Un script SQL pur à faire tourner "de temps en temps", au moins une fois par semaine qui permet de tenir à jour la date de dernière "visite" de ces adresses à partir des enregistrements de NtopNg. 
    La sélection est donc moins de 180 jours depuis la dernière visite.
  • Un script Bash + SQL qui permet d'extraire et mettre en forme les données.
  • Un script de chargement du set (ipset actuellement) qui fonctionne par chargement d'un set intermédiaire suivi d'un "swap" avec le set permanent et d'un drop de l'ancien set permanent.

Cette liste (#42000 adresses au 29/02/2024) rafraîchie plusieurs fois par jour est disponible ici.

Note : 
Afin de mieux protéger le réseau de l'extérieur quelques adresses ont été rajoutées "en dur" dans la table :

  • Adresses non routables telles : 10.0.0.0/8, 172.16.0.0/12 ...
  • Plages "réservées pour usage futur" : 240.0.0.0/4 ...


Autre liste "spéciale Windows" (#5600 adresses au 15/02/2022) disponible ici et rafraîchie au moins une fois par jour. 
Cette liste de #5600 adresses comporte toutes les adresses ayant tenté un accès sur un des ports suivants : 
22,135,137,138,139,445,1433,3389 au cours des 60 jours précédents, je viens d'y ajouter le port 23 (telnet) à cette liste qui cible aujourd'hui les objets connectés. 
Note : certaines de ces adresses peuvent déjà figurer dans les "grandes" listes d'IP à éviter.

Nouvelle liste "spéciale web" établie à partir des logs de Modsec, elle aussi rafraichie plusieurs fois par jour. 
Cette liste ne comporte, pour le moment, que peu d'adresses (#1000 au 29/02/2024) car mon installation de Modsec est relativement récente et que Suricata stoppe pas mal de cochonneries sur le port 80, mais elle devrait s'enrichir rapidement, surtout pour les adresses utilisant le port 443. Elle est constituée d'adresses ayant, au moins une fois, tenté un accès douteux (/wp-login.php, xmlrpc.php, /phpmyadmin ...) ,ou plusieurs fois un accès par l'adresse IP seulement (Scanner bète et méchant). Je n'aime pas non plus les "visiteurs" qui n'ont pas de header, par souci de discrétion probablement. Cela concerne surtout des "attaques"  en HTTPS car la plupart de celles sur le port 80 sont bloquées par Suricata). Par ailleurs les attaques sur le port 80 ont tendance à diminuer car ce site ne réponds pllus sur le port 80.  
Le format de ce fichier est particulier : 
211.20.101.36    #1# 2018/12/26 12:55:36  Bad Bot (no header)                      
211.36.156.120   #2# 2018/09/30 19:16:17  Pirate, possible ?  / Host header is a numeric IP address

  1. Adresse IP
  2. #N# si N = 1 c'est une adresse ne présentant pas de danger "a priori" (script kiddy ?), mais cela peut aussi être de la reconnaissance. Ce type d'adresse n'apparaît que si au moins deux accès ont été constatés dans la période. Si N = 2 c'est une adresse ayant tenté des accès frauduleux du type /admin/login.php ou /phpmyadmin/setup.php .... /wp-login ... un seul accès suffit alors pour passer dans la liste.
  3. Commentaire décrivant le type d'accès détecté.

Les adresses sont éliminées au bout de 120 jours, si leurs utilisateurs n'ont pas récidivé ! Une seule récidive entraîne la remise a zéro de la période de 120 jours?
Le site AbuseIPDB à connaître pour vérifier (ou rapporter) la "malfaisance" d'une adresse IP :

AbuseIPDB Contributor Badge 

Bots sans DNS Name

Bots sans DNS Name jpp

De plus en plus de "crawlers" sont "anonymes", la présence d'un user agent n'est pas suffisante pour certifier l'origine, n'importe qui peut cloner un "user agent", l'avantage du DNS name est qu'il existe une bonne probabilité que le détenteur du nom de domaine soit identifiable et cela semble une preuve probablement suffisante de l'origine de ce robot et de la confiance que l'on peut lui accorder.
Un "robot" non identifié peut très bien n'être qu'un vulgaire "pirate" en train de chercher une faille dans votre site.

Depuis quelques temps je bloque donc systématiquement au niveau du firewall les adresses de ces robots "anonymes" afin de décourager cette pratique et je conseille à tous de faire la même chose afin d'obtenir un internet un peu plus sain.

Il semble, notamment, que les robots destinés à alimenter les moteurs d"IA sont souvent anonymes pour ne pas montrer qu'ils se servent des idées des autres pour "éduquer" leur "intelligence".

Filtrage DNS

Filtrage DNS jpp

Installer un filtrage DNS, quelle est son utilité ?
Cela permet, à condition de disposer de listes de "mauvais" sites, de ne pas prendre le risque d'y être envoyés ou redirigés par un site piraté ou peu scrupuleux. Cela peut aussi éviter certains sites de phishing. 
Plusieurs sources de liste de noms de domaines à éviter sont récupérables sur Internet, l'une de ces listes est maintenue par "abuse.ch" qui présente aussi d'autres listes liées à la sécurité. 
Si vous disposez d'un DNS bind9 la prise en compte d'une telle liste est extrêmement facile et ne nécessite que quelques petits ajouts dans le paramétrage de Bind9/named et l'installation d'un commande en "crontab" pour tenir à jour le fichier de référence. 
1) La première modification doit être faite dans le fichier de paramètres qui contient la définition de vos "zones" (en général "named.conf"). Cette modification consiste à créer une nouvelle "zone" ce qui se fait en ajoutant en fin de fichier la description de la nouvelle zone : 
zone "urlhaus.zone" { 
    type master; 
    file "/etc/bind/urlhaus.rpz"; 
    allow-query { any; }; 
    allow-update { none; }; 
    allow-transfer { none; }; 
};

2) Il faut ensuite définir la nouvelle fonctionnalité dans les "options" (en général dans le fichier "named.conf.local"). Il suffit d'y ajouter la ligne suivante dans le paragraphe "options" : 
response-policy { zone "urlhaus.zone"; }; 
Attention à bien placer cette ligne entre les deux accolades du paragraphe "options".

3) Récupérer ensuite le fichier sur le site, à l'aide du script suivant que vous pourrez référencer dans votre "crontab" (au moins une fois par jour) :

#!/bin/bash 
# 
#    GET new RPZ file 
# --------------------------------------------------------------- 
cp /etc/bind/urlhaus.rpz /etc/bind/urlhaus.rpz_old 
wget -O /etc/bind/urlhaus.rpz https://urlhaus.abuse.ch/downloads/rpz/ 
chmod +r /etc/bind/urlhaus.rpz

Un simple "reload" de Bind9 suffit à activer cette nouvelle fonctionnalité et les sites "douteux" ne pourront plus être atteints par votre machine. 
On peut même (avec un gentil petit script) y ajouter des noms de domaines si on le désire. La seule bizarrerie (?) c'est que je n'arrive pas à me débarrasser de domaines en ".top", pour les autres cela fonctionne très bien. 
Mettez dans votre fichier personnel les lignes suivantes : 
toto.com CNAME .    ; commentaire 
*.toto.com CNAME .  ; autre commentaire 
et ... tout le domaine "toto.com" deviendra inaccessible ... c'est pas mal pour certaines pubs, le DNS réponds instantanément que le site n'existe pas, donc aucun risque d'aller y faire un tour pour qu'il vous en joue de mauvais.