Aller au contenu

Comment protéger un site Web avec HAProxy et ModSecurity via SPOE

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.

Malik Sako, , 11 min de lecture
Comment protéger un site Web avec HAProxy et ModSecurity via SPOE

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 :

  1. 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)
  2. HAproxy soumet la requête à la machine hébergeant le service SPOA (spoa01) afin que cette dernière soit analysée
  3. L’agent SPOA, sur spoa01 confronte la requête aux règles ModSecurity en place et envoie son verdict à HAproxy (rp01)
  4. 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)
  5. Le serveur Web (web01) envoie la réponse à la requête qui lui a été soumise par HAproxy (rp01)
  6. 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

Remerciements

Merci à Thierry FOURNIER pour son agent SPOA et les informations transmises et à Willy TARREAU pour ses suggestions d’améliorations.

Dans la même thématique

Tout le blog