HAProxy
Prerequisites
- HAProxy 2.8+ (with the built-in HTTP client)
- LuaSocket
HAProxy
You can check the version of HAProxy by running:
$ haproxy -v
HAProxy version 2.8.10-f28885f 2024/06/14 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2028.
Known bugs: http://www.haproxy.org/bugs/bugs-2.8.10.html
Running on: Linux 5.15.0-1066-aws #72~20.04.1-Ubuntu SMP Thu Jul 18 10:41:27 UTC 2024 x86_64
You can validate the version of Lua by running:
$ haproxy -vv
HAProxy version 2.8.10-f28885f 2024/06/14 - https://haproxy.org/
[...]
Built with Lua version : Lua 5.4.7
[...]
LuaSocket
About timestamps in Lua
By default, Lua generates timestamps with a second-level precision and a dependency on
lua-socket
is required to support millisecond precision. This enables better latency measures on the Protection API.
The lua-socket
package can be installed using:
apt install lua-socket -y
The presence of this package will be detected by Lua during runtime, no further action is required to improve time measurements.
Configuration
You need to follow the steps below:
- Download the latest DataDome module from this link here and extract it in your HAProxy configuration directory.
The archive includes the following files:
datadome.lua
: a Lua script that handles the transformation of the HTTP requestcore/helper.lua
: Lua scripts to manipulate strings and HTTP Requestshaproxy.cfg
: Example file of a working configuration
- Edit the HAProxy configuration file and set
DATADOME_SERVERSIDE_API_KEY
with your own API server key provided by DataDome. You can find this key inside our dashboard. - Update your HAProxy configuration file by replacing
<PATH>
with the actual path where you placed the file, and setting the different blocks needed: - Add the request/response hook as in the example below
global
[...]
httpclient.timeout.connect 150ms
httpclient.retries 0
# Edit Path here
lua-load-per-thread <PATH>/datadome.lua
set-var proc.Datadome_key str("DATADOME_SERVERSIDE_API_KEY") # Set your serverside key here
[...]
# Example of frontend which will be protected
frontend http
[...]
# Insert these lines on each frontend you want to protect
# Here check uri is not in exclusion path
acl excluded_files path_reg -i .\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|jsf|js|map)$
http-request lua.Datadome_request_hook if !excluded_files
http-response lua.Datadome_response_hook
# Insert this line before all default_backend / use_backend directives
use_backend failure_backend if { var(txn.dd.status) -m str blocked }
default_backend [...]
# Backend to serve the "challenged page"
backend failure_backend
mode http
http-request use-service lua.failure_service
Keep the failure_backend declaration first
HAProxy is using backends in the order they are defined in the configuration file.
backend failure_backend
should remain first in order to be used by HAProxy when a request is blocked by DataDome. If not, blocked requests will be let through and reach the backend you defined in priority.All of these rules are evaluated in their declaration order, and the first one which matches will
assign the backend. (HAProxy Reference documentation)
Settings
Settings | Description | Default Value | Required | File |
---|---|---|---|---|
DataDome_Key (*haproxy.cfg) | Your DataDome server-side key - Available inside our dashboard | Yes | haproxy.cfg | |
Endpoint | URL of the closest endpoint. More info here | api.datadome.co | Optional | datadome.lua |
Timeout | API request timeout for reused connections in ms | 150ms | Optional | datadome.lua |
FAQ
How can I have DataDome response status in the log?
- For each request protected by DataDome, the txn.dd.x_datadome_response contains the value of the HTTP response API
- If there is an issue in the call to Datadome, the variable txn.dd.error contains the error code and details.
- the main errors are as follow:
- 400 - Bad Request (Invalid DataDome Key ?)
- 504 - API Server times out
- 503 - Invalid response from API Server
How can I get Bot Name, RuleType and Bot/Human flags in my application?
It is possible to specify a Log-Format to log the returned Datadome Headers
Some headers returned by the API are:
- X-DataDome-botname
- X-DataDome-ruletype
- X-DataDome-isbot
- X-DataDome-requestid
- ...
and can be logged using the methodlua.ddHeaders
as follow
log-format "X-DataDome-botname: %{+Q}[lua.ddHeaders(X-DataDome-botname)] | X-DataDome-family: %{+Q}[lua.ddHeaders(X-DataDome-ruletype)] | X-DataDome-isbot: %{+Q}[lua.ddHeaders(X-DataDome-isbot)] | %{+Q}[lua.ddHeaders(X-DataDome-requestid)]"
You can find more information here.
How can I exclude files from DataDome protection?
In the Haproxy configuration, option to call DataDome is managed by an HAProxy ACL.
Default ACL is as follow
acl excluded_files path_reg -i .\.(avi|flv|mka|mkv|mov|mp4|mpeg|mpg|mp3|flac|ogg|ogm|opus|wav|webm|webp|bmp|gif|ico|jpeg|jpg|png|svg|svgz|swf|eot|otf|ttf|woff|woff2|css|less|jsf|js|map)$
It can be completed by custom rules / other ACLs
How do I restore the Referer
request header after a challenge is passed?
Referer
request header after a challenge is passed?After passing a DataDome challenge on browsers other than Firefox, the referrer value is updated to the current URL which can lead to inconsistent results in website analytics.
Since version 1.1.0
, it is possible to restore the Referer
header to its original value for your backend:
- Contact our support team, they will review your requirements and provide you with the best recommendations.
- Set the boolean value of
restore_referrer
inDATADOME_API_CONFIG
option totrue
in thedatadome.lua
file.
local DATADOME_API_CONFIG = helpers.activate({
restore_referrer = true
})
How can I log processing time and total time?
- Processing Time :
txn.dd.ptime
The processing time is the latency added by the protection, defined inms
(milliseconds)
Its measurement start when the request is received in the HaProxy frontend, and stops when a response is received from the DataDome Protection API. - Total Time:
txn.dd.ttime
The total time is the processing time, plus the time spent by HaProxy to add DataDome headers in the response to the end-user.
As adding headers is performant in HaProxy, time added to the processing time is measured inµs
(microseconds) and can be considered negligeable.
Logging these values is done by adding them to the log-format
in the haproxy.cfg
file as follow:
log-format "ptime=%{+Q}[var(txn.dd.ptime)] ttime=%{+Q}[var(txn.dd.ttime)]"
Updated 12 days ago