Skip to main content
Version: Next

chaitin-waf

Description#

The chaitin-waf Plugin integrates with the Chaitin WAF (SafeLine) service to provide advanced detection and prevention of web-based threats, enhancing application security and protecting sensitive user data.

Response Headers#

The Plugin can add the following response headers, depending on the configuration of append_waf_resp_header and append_waf_debug_header:

HeaderDescription
X-APISIX-CHAITIN-WAFIndicates whether APISIX forwarded the request to the WAF server.
yes: Request was forwarded to the WAF server.
no: Request was not forwarded to the WAF server.
unhealthy: Request matches the configured rules, but no WAF service is available.
err: An error occurred during Plugin execution. The X-APISIX-CHAITIN-WAF-ERROR header is also included with details.
waf-err: Error while interacting with the WAF server. The X-APISIX-CHAITIN-WAF-ERROR header is also included with details.
timeout: Request to the WAF server timed out.
X-APISIX-CHAITIN-WAF-TIMERound-trip time (RTT) in milliseconds for the request to the Chaitin WAF server, including both network latency and WAF server processing.
X-APISIX-CHAITIN-WAF-STATUSStatus code returned to APISIX by the WAF server.
X-APISIX-CHAITIN-WAF-ACTIONAction returned to APISIX by the WAF server.
pass: Request was allowed by the WAF service.
reject: Request was blocked by the WAF service.
X-APISIX-CHAITIN-WAF-ERRORDebug header. Contains WAF error message.
X-APISIX-CHAITIN-WAF-SERVERDebug header. Indicates which WAF server was selected.

Attributes#

NameTypeRequiredDefaultValid valuesDescription
modestringfalseblockoff, monitor, blockMode to determine how the Plugin behaves for matched requests. In off mode, WAF checks are skipped. In monitor mode, requests with potential threats are logged but not blocked. In block mode, requests with threats are blocked as determined by the WAF service.
matcharray[object]falseAn array of matching rules. The Plugin uses these rules to decide whether to perform a WAF check on a request. If the list is empty, all requests are processed.
match.varsarray[array]falseAn array of one or more matching conditions in the form of lua-resty-expr to conditionally execute the plugin.
append_waf_resp_headerbooleanfalsetrueIf true, add response headers X-APISIX-CHAITIN-WAF, X-APISIX-CHAITIN-WAF-TIME, X-APISIX-CHAITIN-WAF-ACTION, and X-APISIX-CHAITIN-WAF-STATUS.
append_waf_debug_headerbooleanfalsefalseIf true, add debugging headers X-APISIX-CHAITIN-WAF-ERROR and X-APISIX-CHAITIN-WAF-SERVER to the response. Effective only when append_waf_resp_header is true.
configobjectfalseChaitin WAF service configurations. These settings override the corresponding metadata defaults when specified.
config.connect_timeoutintegerfalse1000The connection timeout to the WAF service, in milliseconds.
config.send_timeoutintegerfalse1000The sending timeout for transmitting data to the WAF service, in milliseconds.
config.read_timeoutintegerfalse1000The reading timeout for receiving data from the WAF service, in milliseconds.
config.req_body_sizeintegerfalse1024The maximum allowed request body size, in KB.
config.keepalive_sizeintegerfalse256The maximum number of idle connections to the WAF detection service that can be maintained concurrently.
config.keepalive_timeoutintegerfalse60000The idle connection timeout for the WAF service, in milliseconds.
config.real_client_ipbooleanfalsetrueIf true, the client IP is obtained from the X-Forwarded-For header. If false, the Plugin uses the client IP from the connection.

Plugin Metadata#

NameTypeRequiredDefaultValid valuesDescription
nodesarray[object]TrueAn array of addresses for the Chaitin WAF service.
nodes.hoststringTrueAddress of Chaitin WAF service. Supports IPv4, IPv6, Unix Socket, etc.
nodes.portintegerFalse80Port of Chaitin WAF service.
modestringFalseblockMode to determine how the Plugin behaves for matched requests. In off mode, WAF checks are skipped. In monitor mode, requests with potential threats are logged but not blocked. In block mode, requests with threats are blocked as determined by the WAF service.
configobjectFalseChaitin WAF service configurations.
config.connect_timeoutintegerFalse1000The connection timeout to the WAF service, in milliseconds.
config.send_timeoutintegerFalse1000The sending timeout for transmitting data to the WAF service, in milliseconds.
config.read_timeoutintegerFalse1000The reading timeout for receiving data from the WAF service, in milliseconds.
config.req_body_sizeintegerFalse1024The maximum allowed request body size, in KB.
config.keepalive_sizeintegerFalse256The maximum number of idle connections to the WAF detection service that can be maintained concurrently.
config.keepalive_timeoutintegerFalse60000The idle connection timeout for the WAF service, in milliseconds.
config.real_client_ipbooleanFalsetrueIf true, the client IP is obtained from the X-Forwarded-For header. If false, the Plugin uses the client IP from the connection.

Examples#

The examples below demonstrate how you can configure chaitin-waf Plugin for different scenarios.

Before proceeding, make sure you have installed Chaitin WAF (SafeLine).

note

Only X-Forwarded-* headers sent from addresses in the apisix.trusted_addresses configuration (supports IP and CIDR) will be trusted and passed to plugins or upstream. If apisix.trusted_addresses is not configured or the IP is not within the configured address range, all X-Forwarded-* headers will be overridden with trusted values.

note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

Block Malicious Requests on a Route#

The following example demonstrates how to integrate with Chaitin WAF to protect traffic on a route, rejecting malicious requests immediately.

Configure the Chaitin WAF connection details using Plugin Metadata (update the address accordingly):

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/chaitin-waf" -X PUT \
-H 'X-API-KEY: ${admin_key}' \
-d '{
"nodes": [
{
"host": "172.22.222.5",
"port": 8000
}
]
}'

Create a Route and enable chaitin-waf on the Route to block requests identified to be malicious:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "chaitin-waf-route",
"uri": "/anything",
"plugins": {
"chaitin-waf": {
"mode": "block",
"append_waf_resp_header": true,
"append_waf_debug_header": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Send a standard request to the Route:

curl -i "http://127.0.0.1:9080/anything"

You should receive an HTTP/1.1 200 OK response.

Send a request with SQL injection to the Route:

curl -i "http://127.0.0.1:9080/anything" -d 'a=1 and 1=1'

You should see an HTTP/1.1 403 Forbidden response similar to the following:

...
X-APISIX-CHAITIN-WAF-STATUS: 403
X-APISIX-CHAITIN-WAF-ACTION: reject
X-APISIX-CHAITIN-WAF-SERVER: 172.22.222.5
X-APISIX-CHAITIN-WAF: yes
X-APISIX-CHAITIN-WAF-TIME: 3
...

{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "276be6457d8447a4bf1f792501dfba6c"}

Monitor Requests for Malicious Intent#

This example shows how to integrate with Chaitin WAF to monitor all routes with chaitin-waf without rejection, and to reject potentially malicious requests on a specific route.

Configure the Chaitin WAF connection details using Plugin Metadata (update the address accordingly) and configure the mode:

curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/chaitin-waf" -X PUT \
-H 'X-API-KEY: ${admin_key}' \
-d '{
"nodes": [
{
"host": "172.22.222.5",
"port": 8000
}
],
"mode": "monitor"
}'

Create a Route and enable chaitin-waf without any configuration on the Route:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "chaitin-waf-route",
"uri": "/anything",
"plugins": {
"chaitin-waf": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Send a standard request to the Route:

curl -i "http://127.0.0.1:9080/anything"

You should receive an HTTP/1.1 200 OK response.

Send a request with SQL injection to the Route:

curl -i "http://127.0.0.1:9080/anything" -d 'a=1 and 1=1'

You should also receive an HTTP/1.1 200 OK response as the request is not blocked in the monitor mode, but observe the following in the log entry:

2025/09/09 11:44:08 [warn] 115#115: *31683 [lua] chaitin-waf.lua:385: do_access(): chaitin-waf monitor mode: request would have been rejected, event_id: 49bed20603e242f9be5ba6f1744bba4b, client: 172.20.0.1, server: _, request: "POST /anything HTTP/1.1", host: "127.0.0.1:9080"

If you explicitly configure the mode on a route, it will take precedence over the configuration in the Plugin Metadata. For instance, if you create a Route like this:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
"id": "chaitin-waf-route",
"uri": "/anything",
"plugins": {
"chaitin-waf": {
"mode": "block"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'

Send a standard request to the Route:

curl -i "http://127.0.0.1:9080/anything"

You should receive an HTTP/1.1 200 OK response.

Send a request with SQL injection to the Route:

curl -i "http://127.0.0.1:9080/anything" -d 'a=1 and 1=1'

You should see an HTTP/1.1 403 Forbidden response similar to the following:

...
X-APISIX-CHAITIN-WAF-STATUS: 403
X-APISIX-CHAITIN-WAF-ACTION: reject
X-APISIX-CHAITIN-WAF: yes
X-APISIX-CHAITIN-WAF-TIME: 3
...

{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "c3eb25eaa7ae4c0d82eb8ceebf3600d0"}