Afin de filtrer les accès Web, le chaînage classique HAProxy + Apache/ModSecurity + Serveur Web remplit toujours son rôle, mais reste complexe à maintenir. Il est possible de simplifier cette architecture grâce à la fonction SPOE de HAProxy, couplée à l’utilisation de la contribution ModSecurity de ce dernier.
Préambule
HAProxy® est un répartiteur de charge et un proxy open source pour les applications TCP et HTTP. HAProxy® est disponible gratuitement dans sa version communautaire, ou également de manière commerciale sous le nom de Hapee (version packagée) et Aloha (version appliance).
ModSecuritytm est un WAF (Web Application Firewall) open-source permettant de protéger les applications Web de nombreuses menaces, avec une grande granularité de configuration.
ModSecurity SPOA (Stream Processing Offload Agent) est une contribution permettant à HAProxy de déléguer à ce service, le traitement d’un flux à travers le mécanisme de filtre SPOE (Stream Processing Offload Engine) de HAProxy.
Cet article explique comment utiliser le service SPOA avec HAProxy pour renforcer la sécurité des accès aux applications Web avec ModSecurity.
Note : La distribution GNU/Linux utilisée ici est CentOS 8. Les noms des packages listés dans les pré-requis sont susceptibles de différer légèrement si une autre distribution est utilisée.
Dans la suite de ce document, le titre des chapitres fera apparaître entre parenthèses le nom de la machine sur laquelle les opérations sont à réaliser.
Architecture
Liste des machines
Dans la suite du document, nous ferons référence aux différentes machines de la maquette à travers les noms suivants :
- dev01 (serveur de développement, sur lequel se feront les compilations)
- rp01 (serveur hébergeant HAproxy, adresse IP : 10.0.200.5, adresse du frontend : 10.0.100.100)
- spoa01 (serveur hébergeant l’agent SPOA, adresse IP : 10.0.200.10)
- web01 (Serveur Apache, adresse IP : 10.0.215.15)
Schéma de principe
Le principe de fonctionnement est décrit ci-dessous, de manière simplifiée :

- Le client effectue une requête HTTP (ou HTTPS, en fonction de la configuration en place). Cette dernière est reçue par la machine HAproxy (rp01)
- HAproxy soumet la requête à la machine hébergeant le service SPOA (spoa01) afin que cette dernière soit analysée
- L’agent SPOA, sur spoa01 confronte la requête aux règles ModSecurity en place et envoie son verdict à HAproxy (rp01)
- A cette étape, 2 cas de figure sont possibles :
a- Le verdict est positif : HAproxy (rp01) se connecte au serveur Web (web01) et lui soumet la requête du client
b- Le verdict est négatif : HAproxy (rp01) répond à la machine cliente en indiquant que l’accès est refusé (code HTTP 403) - Le serveur Web (web01) envoie la réponse à la requête qui lui a été soumise par HAproxy (rp01)
- HAproxy (rp01) envoie la réponse du serveur Web (web01) à la machine cliente.
Pré-requis
Pour la compilation (dev01)
Afin de pouvoir compiler le service SPOA, il est nécessaire de procéder préalablement à la compilation de ModSecurity.
Pour cela, nous allons avoir besoin de plusieurs outils et bibliothèques :
- gcc
- httpd-devel
- libxml2-devel
- apr-devel
- libevent-devel
- pcre-devel
- libcurl-devel
- lua-devel
- yajl-devel
[zuser@spoa ~]$ sudo yum install gcc httpd-devel libxml2-devel apr-devel libevent-devel pcre-devel libcurl-devel lua-devel yajl-devel
Pour HAproxy (rp01)
La machine rp01 tiendra le rôle de reverse-proxy, et hébergera HAproxy
Nous allons donc l’y installer :
[zuser@rp01 ~]$ sudo yum install haproxy
et faire en sorte qu’il démarre avec le système :
[zuser@rp01 ~]$ sudo systemctl enable haproxy
Created symlink from /etc/systemd/system/multi-user.target.wants/haproxy.service to /usr/lib/systemd/system/haproxy.service.
Note : Nous considérerons dans la suite de cet article que nous disposons d’une configuration HAproxy fonctionnelle sur laquelle le filtrage ModSecurity se greffera. Nous considérerons également qu’un service Apache fonctionnel tourne sur la machine web01.
Pour la machine SPOA (spoa01)
Nous devons créer les dossiers de destination du binaire SPOA, et télécharger le jeu de règle ModSecurity :
[zuser@spoa01 ~]$ sudo mkdir -p /opt/spoa-modsec/bin
[zuser@spoa01 ~]$ wget https://github.com/coreruleset/coreruleset/archive/v3.2.0.zip
[zuser@spoa01 ~]$ sudo unzip v3.2.0.zip -d /opt/spoa-modsec/
Archive: v3.2.0.zip
be34e996fe19078d5fd07e101af21bef1df59e2c
creating: coreruleset-3.2.0/
creating: coreruleset-3.2.0/.github/
inflating: coreruleset-3.2.0/.github/ISSUE_TEMPLATE.md
inflating: coreruleset-3.2.0/.gitignore
inflating: coreruleset-3.2.0/.gitmodules
inflating: coreruleset-3.2.0/.travis.yml
inflating: coreruleset-3.2.0/CHANGES
inflating: coreruleset-3.2.0/CONTRIBUTING.md
inflating: coreruleset-3.2.0/CONTRIBUTORS.md
inflating: coreruleset-3.2.0/INSTALL
inflating: coreruleset-3.2.0/KNOWN_BUGS
inflating: coreruleset-3.2.0/LICENSE
inflating: coreruleset-3.2.0/README.md
inflating: coreruleset-3.2.0/crs-setup.conf.example
creating: coreruleset-3.2.0/documentation/
creating: coreruleset-3.2.0/documentation/OWASP-CRS-Documentation/
inflating: coreruleset-3.2.0/documentation/README
creating: coreruleset-3.2.0/rules/
inflating: coreruleset-3.2.0/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
inflating: coreruleset-3.2.0/rules/REQUEST-901-INITIALIZATION.conf
inflating: coreruleset-3.2.0/rules/REQUEST-903.9001-DRUPAL-EXCLUSION-RULES.conf
inflating: coreruleset-3.2.0/rules/REQUEST-903.9002-WORDPRESS-EXCLUSION-RULES.conf
(...)
inflating: coreruleset-3.2.0/util/virtual-patching/arachni2modsec.pl
inflating: coreruleset-3.2.0/util/virtual-patching/zap2modsec.pl
[zuser@spoa01 ~]$
Nous disposons désormais de tous les outils nécessaires. Nous pouvons donc passer à la phase de compilation.
Compilation de ModSecurity (dev01)
Note: Du fait de différences importantes entre ModSecurity 2.9.x et ModSecurity 3.x, ModSecurity 3.x n’est pas compatible avec le service que nous allons compiler. Nous utiliserons la dernière version de ModSecurity 2 qui est la 2.9.3 au moment de l’écriture de ces lignes.
La 1ère étape consiste à récupérer l’archive et à la décompresser :
[zuser@dev01 ~]$ wget https://www.modsecurity.org/tarball/2.9.3/modsecurity-2.9.3.tar.gz -O - | tar -xz
Nous devons ensuite procéder à la compilation de ModSecurity en mode standalone :
[zuser@dev01 ~]$ cd modsecurity-2.9.3
[zuser@dev01 ~]$ ./configure --prefix=$PWD/INSTALL --disable-apache2-module --enable-standalone-module --enable-pcre-study --with-lua --enable-pcre-jit
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... gcc
(...)
config.status: creating tests/regression/server_root/conf/httpd.conf
config.status: creating tools/rules-updater.pl
config.status: creating mlogc/Makefile
config.status: creating tests/Makefile
config.status: creating apache2/modsecurity_config_auto.h
config.status: apache2/modsecurity_config_auto.h is unchanged
config.status: executing depfiles commands
config.status: executing libtool commands
[zuser@dev01 modsecurity-2.9.3]$
Après la phase de configuration, il s’agit de passer à la compilation proprement dite et à l’installation :
[zuser@dev01 modsecurity-2.9.3]$ make && make -C standalone install
(...)
[zuser@dev01 modsecurity-2.9.3]$ mkdir -p $PWD/INSTALL/include
[zuser@dev01 modsecurity-2.9.3]$ cp standalone/*.h $PWD/INSTALL/include
[zuser@dev01 modsecurity-2.9.3]$ cp apache2/*.h $PWD/INSTALL/include
Compilation de SPOA (dev01)
Cet agent se trouve dans le dossier « contrib/modsecurity » du code source HAproxy. Il s’agit donc de commencer par télécharger ces sources, soit via un « git clone », soit directement :
zuser@dev01 modsecurity-2.9.3]$ cd
[zuser@dev01 ~]$ wget https://github.com/haproxy/haproxy/archive/master.zip
[zuser@spoa ~]$ unzip master.zip
(...)
Nous pouvons ensuite nous déplacer dans le dossier SPOA :
[zuser@dev01 ~]$ cd haproxy-master/contrib/modsecurity
[zuser@dev01 modsecurity]$
La lecture du fichier Makefile nous indique que nous devons modifier certaines variables afin que les options de compilation correspondant à notre cas de figure soient utilisées. Nous allons donc passer les paramètres nécessaires directement sur la ligne de commande. Nous en profiterons également pour renommer le fichier généré (« modsecurity ») en « spoa » :
[zuser@dev01 modsecurity]$ make MODSEC_INC=~/modsecurity-2.9.3/INSTALL/include MODSEC_LIB=~/modsecurity-2.9.3/INSTALL/lib APACHE2_INC=/usr/include/httpd APR_INC=/usr/include/apr-1 LIBS="-lpthread -levent -levent_pthreads -lcurl -lapr-1 -laprutil-1 -lxml2 -lpcre -lyajl -llua" && mv ./modsecurity spoa
La sortie du terminal doit ressembler à ceci :
cc -g -Wall -pthread -I../../include -I../../ebtree -I/home/zuser/modsecurity-2.9.3/INSTALL/include -I/usr/include/httpd -I/usr/include/apr-1 -I/usr/include/libxml2 -I/usr/include -c -o spoa.o spoa.c
cc -g -Wall -pthread -I../../include -I../../ebtree -I/home/zuser/modsecurity-2.9.3/INSTALL/include -I/usr/include/httpd -I/usr/include/apr-1 -I/usr/include/libxml2 -I/usr/include -c -o modsec_wrapper.o modsec_wrapper.c
cc -o modsecurity spoa.o modsec_wrapper.o /home/zuser/modsecurity-2.9.3/INSTALL/lib/standalone.a -lpthread -levent -levent_pthreads -lcurl -lapr-1 -laprutil-1 -lxml2 -lpcre -lyajl -llua
[zuser@spoa modsecurity]$
Une fois la compilation terminée, il s’agit de copier le binaire créé (nommé « spoa ») sur la machine spoa01.
[zuser@dev01 modsecurity]$ rsync -Pav spoa spoa01:~/
zuser@spoa01's password:
sending incremental file list
spoa
2,587,616 100% 97.46MB/s 0:00:00 (xfr#1, to-chk=0/1)
sent 2,588,347 bytes received 35 bytes 739,537.71 bytes/sec
total size is 2,587,616 speedup is 1.00
Lancement du service (spoa01)
Une fois compilé, le programme est prêt à être utilisé. Nous allons nous connecter à la machine spoa01 et placer le fichier dans le dossier définitif :
[zuser@spoa01 ~]$ sudo mv ./spoa /opt/spoa-modsec/bin/
Note : bien vérifier que les permissions d’exécution du fichier « spoa » incluent bien l’utilisateur « zuser ».
Nous allons désormais pouvoir utiliser l’agent :
[zuser@spoa01 bin]$ ./spoa -h
Usage : ./spoa [OPTION]...
-h Print this message
-d Enable the debug mode
-f <config-file> ModSecurity configuration file
-m <max-frame-size> Specify the maximum frame size (default : 16384)
-p <port> Specify the port to listen on (default : 12345)
-n <num-workers> Specify the number of workers (default : 10)
-c <capability> Enable the support of the specified capability
-t <time> Set a delay to process a message (default: 0)
The value is specified in milliseconds by default,
but can be in any other unit if the number is suffixed
by a unit (us, ms, s)
Supported capabilities: fragmentation, pipelining, async
Lors de la validation des pré-requis, nous avons téléchargé les fichiers de règles ModSecurity. Nous allons utiliser ces derniers avec l’agent SPOA.
Pour cette maquette, nous allons utiliser comme base, le fichier d’exemple présent dans le dossier « coreruleset-3.2.0 » :
[zuser@spoa01 ~]$ cd /opt/spoa-modsec/coreruleset-3.2.0/
[zuser@spoa01 coreruleset-3.2.0]$ cp crs-setup.conf.example crs-setup.conf
Nous allons ensuite créer un fichier de configuration « spoa.conf » regroupant le fichier précédemment créé et le jeu de règles ModSecurity (les « > » qui peuvent apparaître ont été supprimés afin de faciliter le copier/coller) :
[zuser@spoa01 coreruleset-3.2.0]$ sudo tee spoa.conf >/dev/null <<EOF
SecRuleEngine On
SecRequestBodyAccess On
SecTmpDir /tmp/
SecDataDir /tmp/
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsec_audit.log
SecDebugLog /var/log/modsec_debug.log
SecArgumentSeparator &
SecCookieFormat 0
SecStatusEngine Off
include ./crs-setup.conf
include ./rules/*.conf
EOF
[zuser@spoa01 coreruleset-3.2.0]$
Note : nous incluons ici l’ensemble des fichiers du jeu de règles de base ModSecurity.
Il n’est pas nécessaire de démarrer le service avec un compte à privilège. Il s’agit simplement de s’assurer que le compte utilisé est bien en mesure d’écrire son fichier de log (en fonction de la configuration ModSecurity chargée).
La ligne suivante permet de démarrer le service :
[zuser@spoa01 coreruleset-3.2.0]$ /opt/spoa-modsec/bin/spoa -n5 -f /opt/spoa-modsec/coreruleset-3.2.0/spoa.conf
1587670511.627131 [00] ModSecurity for nginx (STABLE)/2.9.3 (http://www.modsecurity.org/) configured.
1587670511.627161 [00] ModSecurity: APR compiled version="1.4.8"; loaded version="1.4.8"
1587670511.627166 [00] ModSecurity: PCRE compiled version="8.32 "; loaded version="8.32 2012-11-30"
1587670511.627169 [00] ModSecurity: LUA compiled version="Lua 5.1"
1587670511.627172 [00] ModSecurity: LIBXML compiled version="2.9.1"
1587670511.627174 [00] ModSecurity: Status engine is currently disabled, enable it by set SecStatusEngine to On.
1587670516.634719 [03] 0 clients connected
1587670516.634857 [04] 0 clients connected
1587670516.634984 [02] 0 clients connected
1587670516.635123 [01] 0 clients connected
1587670516.635258 [05] 0 clients connected
Cette commande définit 5 workers, qui seront en mesure de prendre en charge les requêtes (-n 5). Le paramètre « -f » permet de définir le fichier de configuration ModSecurity à utiliser.
Le service est désormais en fonctionnement, attaché au terminal courant, le temps de valider le bon fonctionnement.
Dans un autre terminal, nous vérifions que le service est bien en écoute :
[zuser@spoa01 coreruleset-3.2.0]# sudo netstat -pant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 9823/sshd
tcp 0 0 0.0.0.0:12345 0.0.0.0:* LISTEN 19881/./spoa
(..)
[zuser@spoa01 coreruleset-3.2.0]#
Il s’agit désormais de passer à la configuration de HAproxy.
Configuration HAProxy (rp01)
Nous allons tout d’abord définir la configuration relative au moteur de traitement des requêtes, pour leur soumission à ModSecurity. Cette configuration se fera dans un fichier de configuration séparé, que nous nommerons par exemple, spoe-modsecurity.conf :
[zuser@rp01 ~]$ sudo tee /etc/haproxy/spoe-modsecurity.conf >/dev/null <<EOF
[modsecurity]
spoe-agent modsecurity-agent
messages check-request
option var-prefix modsec
timeout hello 100ms
timeout idle 30s
timeout processing 15ms
use-backend spoe-modsecurity
spoe-message check-request
args unique-id method path query req.ver req.hdrs_bin req.body_size req.body
event on-frontend-http-request
EOF
[zuser@rp01 ~]$
Ce fichier de configuration est ensuite à référencer dans le Frontend ou Listener, dans la configuration HAproxy :
frontend main
bind 10.0.100.100:80
filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf
http-request deny if { var(txn.modsec.code) -m int gt 0 }
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %{+Q}[var(txn.modsec.code)]"
default_backend bk_bench
Le Backend bk_bench correspondra à la configuration de l’application à protéger. Nous pourrons, par exemple, utiliser la configuration suivante :
backend bk_bench
balance roundrobin
mode http
http-request deny if { var(txn.modsec.code) -m int gt 0 }
server web01 10.0.215.15:8080 check
Il est également nécessaire de définir un Backend, dont le nom correspondra à celui indiqué dans le fichier « spoe-modsecurity.conf » (use-backend spoe-modsecurity) :
backend spoe-modsecurity
mode tcp
balance roundrobin
timeout connect 5s
timeout server 3m
server modsec1 10.0.200.10:12345 maxconn 5
Dans cet exemple, le service s’exécute sur la machine « spoa01 » dont l’adresse IP est 10.0.200.10. Cette adresse est naturellement à faire correspondre avec l’adresse de la machine hébergeant l’agent SPOA.
Le fait de préciser « maxconn 5 » permet de faire en sorte que les requêtes qui ne pourraient pas être traitées par un worker ModSecurity, soient mises en file d’attente dans HAproxy. Ces requêtes ne seront donc pas dépendantes du timer de connexion, mais seront soumises au timer de file d’attente, ce qui est préférable.
Il ne reste désormais plus qu’à valider le bon fonctionnement.
Tests de fonctionnement
Afin de prendre en compte les modifications effectuées, le service HAproxy doit être démarré (ou redémarré) :
[zuser@rp01 ~]$ sudo systemctl restart haproxy
Au fur et à mesure de l’arrivée des requêtes, des lignes de ce type doivent apparaître sur la console dans laquelle l’agent SPOA a été lancé :
1590670670.561418 [00] [client 127.0.0.1] ModSecurity: Warning. Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/home/zuser/coreruleset-3.2.0/./rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "696"] [id "920350"] [msg "Host header is a numeric IP address"] [data "10.0.100.100"] [severity "WARNING"] [ver "OWASP_CRS/3.2.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "localhost.localdomain"] [uri "http://10.0.100.100/admin3.php"] [unique_id ""]
1590670670.561530 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase "etc/passwd" at ARGS:path. [file "/home/zuser/coreruleset-3.2.0/./rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "96"] [id "930120"] [msg "OS File Access Attempt"] [data "Matched Data: etc/passwd found within ARGS:path: ../../etc/passwd"] [severity "CRITICAL"] [ver "OWASP_CRS/3.2.0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-lfi"] [tag "OWASP_CRS"] [tag "OWASP_CRS/WEB_ATTACK/FILE_INJECTION"] [tag "WASCTC/WASC-33"] [tag "OWASP_TOP_10/A4"] [tag "PCI/6.5.4"] [hostname "localhost.localdomain"] [uri "http://10.0.100.100/admin3.php"] [unique_id ""]
1590670670.561594 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase "etc/passwd" at ARGS:path. [file "/home/zuser/coreruleset-3.2.0/./rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "509"] [id "932160"] [msg "Remote Command Execution: Unix Shell Code Found"] [data "Matched Data: etc/passwd found within ARGS:path: ../../etc/passwd"] [severity "CRITICAL"] [ver "OWASP_CRS/3.2.0"] [tag "application-multi"] [tag "language-shell"] [tag "platform-unix"] [tag "attack-rce"] [tag "OWASP_CRS"] [tag "OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION"] [tag "WASCTC/WASC-31"] [tag "OWASP_TOP_10/A1"] [tag "PCI/6.5.2"] [hostname "localhost.localdomain"] [uri "http://10.0.100.100/admin3.php"] [unique_id ""]
1590670670.561790 [00] [client 127.0.0.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:anomaly_score. [file "/home/zuser/coreruleset-3.2.0/./rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "91"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 13)"] [severity "CRITICAL"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-generic"] [hostname "localhost.localdomain"] [uri "http://10.0.100.100/admin3.php"] [unique_id ""]
1590670670.561851 [00] [client 127.0.0.1] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/home/zuser/coreruleset-3.2.0/./rules/RESPONSE-980-CORRELATION.conf"] [line "86"] [id "980130"] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 13 - SQLI=0,XSS=0,RFI=0,LFI=5,RCE=5,PHPI=0,HTTP=0,SESS=0): individual paranoia level scores: 13, 0, 0, 0"] [tag "event-correlation"] [hostname "localhost.localdomain"] [uri "http://10.0.100.100/admin3.php"] [unique_id ""]
1590670671.933448 [01] 1 clients connected
1590670671.933476 [02] 1 clients connected
Il est possible de tester assez simplement le blocage ou non à l’aide de Curl. La page n’a pas besoin d’exister, il suffit simplement de remplir la condition d’accès au Frontend et au Backend (donc, l’adresse IP ou le nom de domaine doivent être valides). Le test suivant doit provoquer un blocage et SPOA retournera un code 403 à HAProxy, qui servira à son tour un 403 en réponse à la requête Curl.
# curl -v 'http://10.0.100.100/admin3.php?path=../../etc/passwd'
Le test suivant doit en revanche permettre l’accès à la page :
# curl -v 'http://10.0.100.100/'
Dans Frontend, nous avons ajouté « %{+Q}[var(txn.modsec.code)] » à la fin de la ligne de définition du format de log (ce qui se trouve avant cette variable correspond au format de log utilisé par défaut dans HAProxy) :
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r %{+Q}[var(txn.modsec.code)]"
Cela permet de capturer la valeur du code retour de l’agent SPOA ModSecurity. Tant que la valeur retournée sera inférieure ou égale à 0, aucun blocage ne se produira. En revanche, toute valeur supérieure provoquera le blocage. La ligne suivante du Frontend permet de définir ce comportement :
http-request deny if { var(txn.modsec.code) -m int gt 0 }
Références
- GitHub HAProxy : https://github.com/haproxy/haproxy
- Contribution SPOA : https://github.com/haproxy/haproxy/tree/master/contrib/modsecurity
- Sources ModSecurity : https://modsecurity.org/download.html
- HAProxy « log-format » : https://www.haproxy.com/fr/blog/haproxy-log-customization/
Remerciements
Merci à Thierry FOURNIER pour son agent SPOA et les informations transmises et à Willy TARREAU pour ses suggestions d’améliorations.