---
title: "FAIL2BAN : APACHE2 et l'authentification basique."
canonical: "https://blog.kaptus.net/space/BKAP/blog/290915266/FAIL2BAN%20%3A%20APACHE2%20et%20l'authentification%20basique."
format: markdown
---
> Macro (toc)

# 1. Introduction.

Lors de la mise en place d’APIs REST en Java depuis le serveur d’application TOMCAT, j’ai été confronté au problème de sécurisation des accès à ces APIs. Effectivement, je ne souhaitais pas que mes APIs soient accessibles.

J’avais 2 solutions : 

1. Mettre en place une authentification au niveau des APIs REST
2. Reporter l’authentification au niveau de l’application en frontal (dan mon cas APACHE2 HTTPD).

Après réflexion, j’ai choisi la solution 2. Pourquoi ?

1. Beaucoup plus simple à mettre en place.
2. Beaucoup plus sécure (car je vais pouvoir coupler simplement l’accès aux APIs REST avec [Fail2Ban](https://github.com/fail2ban/fail2ban)).
3. Beaucoup plus simple à gérer.
4. Indépendant de mes applications.

Cette article est un retour d’expérience sur la mis en place de cette solution.

# 2. Le contexte.

Pour un projet en cours de développement, j’ai du mettre en place une API REST qui me permet de valider une adresse électronique : 

- Vérification de l’existence de l’extension du domaine.
- Vérification de l’existence du nom de domaine.
- Vérification syntaxique de l’adresse électronique.
- Vérification de l’existence de l’adresse électronique (2/28/2024 → En cours d’implémentation).

> 📝 3/2/2024 → J’ai décidé de faire ce développement sous forme d’APIs REST, en prévision de transformer en micro-service si nécessaire.

Pour accéder à ce service, il a fallu que je mettes en place un accès restreint afin que : 

1. Le service ne puisse pas être attaqué.
2. Le service puisse seulement être utilisé par des applications ou des utilisateurs accrédités.

Voici un exemple d’appel et de résultat avec une extension invalide : 

> Macro (drawio)

Un autre exemple avec un nom de domaine qui n’existe pas : 

> Macro (drawio)

Et avec une adresse email valide : 

> Macro (drawio)

# 3. Côté technique.

| **OS** | **Frontal** | **Serveur d’application** | **Langage** |
| --- | --- | --- | --- |
| DEBIAN 12 | Apache 2.4.57 | Apache Tomcat 9.0.83 | Java 21 |

## 3.1. Configuration `Apache2`.

Pour accéder à l’API REST, on va configurer le serveur Apache2 en mode proxy : 

```xml
#<VirtualHost xxxxxxxxxxxx.net:443>
<VirtualHost xxxxxxxxxxxx:443>
	ServerAdmin webmaster@naostech.com
    ServerName xxxxxxxxxxxx.net
    ServerAlias xxxxxxxxxxxx.net
    DocumentRoot "frontoffice"
    DirectoryIndex under_construction.html index.html
    LogLevel info authz_core:debug
    ErrorLog "webminut_app-error.log"
    TransferLog "webminut_app-access.log"
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{userID}n %{userStatus}n" pma_combined
    CustomLog "webminut_app-custom.log" pma_combined
    #
    # Errors files
    #
    ErrorDocument 400 "/webminut/error400.html"
    ErrorDocument 401 "/webminut/error401.html"
    ErrorDocument 403 "/webminut/error403.html"
    ErrorDocument 404 "/webminut/error404.html"
    ErrorDocument 408 "/webminut/error408.html"
    <IfModule http2_module>
        Protocols h2 h2c http/1.1
    </IfModule>
    SSLEngine on
    # certificat générés par KAPTUS avec Let's ENCRYPT
	SSLCertificateFile cert.pem
    SSLCertificateKeyFile privkey.pem
    SSLCertificateChainFile chain.pem
	#
	<Directory "frontoffice">
	    AllowOverride All
		Options FollowSymLinks
		order allow,deny
		allow from all
		# New directive needed in Apache 2.4.3:
		Require all granted
	</Directory>
	#
	<Proxy "*">
        AddDefaultCharset Off
        Order deny,allow
        Allow from all
    </Proxy>
    #
    # Proxy API REST authentification
    #
    <Proxy "*/api/*">
        Order deny,allow
        Allow from all
        Authtype Basic
        Authname "Password Required"
        AuthUserFile .htpasswd
        Require valid-user
    </Proxy>
    #
    RequestHeader unset Accept-Encoding
    # Avec RedirectMatch
    RedirectMatch "^/privateInterfaces/(.*)" "/webminut/privateInterfaces/$1"
    # RedirectMatch "^/private/(.*)" "/webminut/private/$1"
    RedirectMatch "^/jsp/(.*)" "/webminut/jsp/$1"
    RedirectMatch "^/javascripts/(.*)" "/webminut/javascripts/$1"
    RedirectMatch "^/html/(.*)" "/webminut/html/$1"
    RedirectMatch "^/css/(.*)" "/webminut/css/$1"
    RedirectMatch "^/images/(.*)" "/webminut/images/$1"
    RedirectMatch "^/tmp/(.*)" "/webminut/tmp/$1"
    
    ProxyPass /webminut ajp://localhost:8009/webminut
    ProxyPassReverse /webminut ajp://localhost:8009/webminut
</VirtualHost>
```

## 3.2. Configuration `Fail2Ban`.

La mise en place de cette solution est intéressant car elle me permet de la coupler avec Fail2Ban. 

Fail2Ban était déjà configuré lorsque 3 tentatives d’accès infructueuse étaient faites depuis la même adresse IP avec des identifiants. Mais j’ai voulu aller plus loin et aussi bloquer les accès si on voulait atteindre l’API sans aucune authentification (attaque `DDOS` par exemple). J'ai pu trouver une pattern pour capturer ce cas précis : 

```plaintext
failregex = ^.*\[authz_core:debug\].*\[client <HOST>:.*AH01628: authorization result: granted \(no directives\)$
             ^.*\[auth_basic:error.*pid.*\[client <HOST>:.*
```

Le résultat de l’application de cette règle, l’adresse IP est bien bloqué après 3 tentatives d’accès.

![image-20240311-164536.png](media://a4f4fb71-c9f1-459d-83d1-2995c7b3b343)

> 📝 J’ai ajouter un configuration spécifique pour que seulement le module apache2 `authz_core` soit en mode débug : 
> 📝 
> 📝 ```plaintext
> 📝 LogLevel info authz_core:debug
> 📝 ```

![image-20240311-165221.png](media://6279f3f6-2db6-4ec0-a6b9-ec4a639b3fb6)

# 4. Conclusion.

Même si j’ai mis un peu de temps pour mettre ne place cette solution, je pense qu’en déportant le contrôle des accès au niveau du serveur apache2, ça allège mon code et mon application. Ce qui la rendra encore plus portable si à l’avenir je souhaitais la découper en micro-service.