Centinel AnalyticaCentinel Analytica
Platforms

HAProxy

Bot protection for HAProxy 2.4+ using SPOE and Lua hooks.

Prerequisites

  • Secret key from your dashboard
  • HAProxy 2.4+ compiled with Lua 5.3 and SPOE support

Installation

Download and extract the module

Download centinel-haproxy.zip and extract the three files to your HAProxy configuration directory:

curl -O https://docs.centinelanalytica.com/downloads/centinel-haproxy.zip
unzip centinel-haproxy.zip -d /etc/haproxy/lua/
mv /etc/haproxy/lua/spoe-centinel.conf /etc/haproxy/

The zip contains:

  • centinel-spoe.lua — Lua hooks for request routing, response headers, and block pages
  • json.lua — JSON encoder/decoder used by the Lua hooks
  • spoe-centinel.conf — SPOE filter configuration
Configure haproxy.cfg
global
    lua-prepend-path /etc/haproxy/lua/?.lua
    lua-load /etc/haproxy/lua/centinel-spoe.lua

frontend http-in
    bind *:80
    filter spoe engine centinel config /etc/haproxy/spoe-centinel.conf
    http-request lua.centinel-request-hook
    http-response lua.centinel-response-hook
    use_backend centinel-block if { var(txn.centinel_status) -m str blocked }
    default_backend servers

backend servers
    server app1 127.0.0.1:8080 check

backend centinel-block
    http-request use-service lua.centinel-block-service

backend spoe-centinel
    mode tcp
    server spoa validator.centinelanalytica.com:9000 ssl verify required ca-file /etc/ssl/certs/ca-certificates.crt

Fail-open by design

If the SPOA is unreachable or doesn't respond within timeout processing (500ms default), HAProxy lets the request through. A down SPOA never blocks traffic.

Set your secret key and reload
export CENTINEL_SECRET_KEY="sk_live_your_key_here"
haproxy -f /etc/haproxy/haproxy.cfg -sf $(cat /var/run/haproxy.pid)

For systemd:

[Service]
Environment="CENTINEL_SECRET_KEY=sk_live_your_key_here"

How it works

HAProxy's SPOE filter sends request metadata to the hosted SPOA over SPOP. The SPOA validates the request and returns a decision. Lua hooks then route the request:

  • allow / not_matched — request goes to your backend. Response headers and cookies from the validator get applied on the way out.
  • block / redirect — request hits the centinel-block-service Lua applet, which serves the block page or challenge HTML.

Static assets (images, fonts, CSS, JS, media files) are excluded by an ACL in spoe-centinel.conf and never reach the SPOA.


Advanced configuration

Timeouts are configured in spoe-centinel.conf:

spoe-agent centinel-agent
  timeout hello 500ms
  timeout idle 30s
  timeout processing 500ms
TimeoutDefaultDescription
timeout processing500msMax wait for the SPOA response. If exceeded, request is allowed (fail-open). Increase if you see frequent timeouts.
timeout hello500msTLS + SPOP handshake timeout. Only matters on first connection — subsequent requests reuse the persistent connection.
timeout idle30sIdle connection timeout before HAProxy drops the SPOA connection.

Static files are excluded by an ACL in spoe-centinel.conf line 3. These requests skip the SPOE pipeline entirely.

Default exclusions: .avi, .avif, .bmp, .css, .eot, .flac, .flv, .gif, .gz, .ico, .jpeg, .jpg, .js, .less, .map, .mka, .mkv, .mov, .mp3, .mp4, .mpeg, .mpg, .ogg, .ogm, .opus, .otf, .png, .svg, .svgz, .swf, .ttf, .wav, .webm, .webp, .woff, .woff2.

Edit the path_reg ACL in spoe-centinel.conf to add or remove extensions.

To skip bot protection on specific paths, add ACLs in your haproxy.cfg frontend before the SPOE filter:

frontend http-in
    bind *:80

    acl no_centinel path_beg /health /metrics /ready
    acl no_centinel path_beg /internal/

    filter spoe engine centinel config /etc/haproxy/spoe-centinel.conf
    http-request lua.centinel-request-hook unless no_centinel
    http-response lua.centinel-response-hook unless no_centinel

    use_backend centinel-block if { var(txn.centinel_status) -m str blocked }
    default_backend servers

Requests matching no_centinel bypass the Lua hooks. The SPOE filter still runs but with no matching event it does nothing.


Configuration reference

Environment variables

VariableDescription
CENTINEL_SECRET_KEYAPI key from the dashboard. Required.

HAProxy config directives

DirectivePurpose
lua-prepend-pathPath to Lua module directory
lua-loadLoads the Centinel Lua hooks at startup
filter spoeActivates the SPOE filter with spoe-centinel.conf
http-request lua.centinel-request-hookRoutes requests based on SPOA decision
http-response lua.centinel-response-hookApplies response headers/cookies on allow
use_backend centinel-blockRoutes blocked requests to the block service
backend spoe-centinelTLS+TCP backend pointing to the hosted SPOA

Changelog

  • 1.1.0 — TLS for SPOA connection, hardened block handling, trimmed static file ACL.
  • 1.0.0 — Initial release.

On this page