blob: 2f3e357dccd53374c9d51178b6a4ce3b08800fd7 [file] [log] [blame] [view]
---
title: chaitin-waf
keywords:
- Apache APISIX
- API Gateway
- Plugin
- WAF
description: The chaitin-waf Plugin integrates with Chaitin WAF (SafeLine) to detect and block web threats, strengthening API security and protecting user data.
---
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->
<head>
<link rel="canonical" href="https://docs.api7.ai/hub/chaitin-waf" />
</head>
## 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`:
| Header | Description |
|--------|-------------|
| `X-APISIX-CHAITIN-WAF` | Indicates whether APISIX forwarded the request to the WAF server.<br />• `yes`: Request was forwarded to the WAF server.<br />• `no`: Request was not forwarded to the WAF server.<br />• `unhealthy`: Request matches the configured rules, but no WAF service is available.<br />• `err`: An error occurred during Plugin execution. The `X-APISIX-CHAITIN-WAF-ERROR` header is also included with details.<br />• `waf-err`: Error while interacting with the WAF server. The `X-APISIX-CHAITIN-WAF-ERROR` header is also included with details.<br />• `timeout`: Request to the WAF server timed out. |
| `X-APISIX-CHAITIN-WAF-TIME` | Round-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-STATUS` | Status code returned to APISIX by the WAF server. |
| `X-APISIX-CHAITIN-WAF-ACTION` | Action returned to APISIX by the WAF server.<br />• `pass`: Request was allowed by the WAF service.<br />• `reject`: Request was blocked by the WAF service. |
| `X-APISIX-CHAITIN-WAF-ERROR` | Debug header. Contains WAF error message. |
| `X-APISIX-CHAITIN-WAF-SERVER` | Debug header. Indicates which WAF server was selected. |
## Attributes
| Name | Type | Required | Default | Valid values | Description |
|--------------------------|---------------|----------|---------|--------------------------|-------------|
| mode | string | false | block | `off`, `monitor`, `block`| Mode 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. |
| match | array[object] | false | | | An 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.vars | array[array] | false | | | An array of one or more matching conditions in the form of [lua-resty-expr](https://github.com/api7/lua-resty-expr#operator-list) to conditionally execute the plugin. |
| append_waf_resp_header | boolean | false | true | | If 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_header | boolean | false | false | | If 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`. |
| config | object | false | | | Chaitin WAF service configurations. These settings override the corresponding metadata defaults when specified. |
| config.connect_timeout | integer | false | 1000 | | The connection timeout to the WAF service, in milliseconds. |
| config.send_timeout | integer | false | 1000 | | The sending timeout for transmitting data to the WAF service, in milliseconds. |
| config.read_timeout | integer | false | 1000 | | The reading timeout for receiving data from the WAF service, in milliseconds. |
| config.req_body_size | integer | false | 1024 | | The maximum allowed request body size, in KB. |
| config.keepalive_size | integer | false | 256 | | The maximum number of idle connections to the WAF detection service that can be maintained concurrently. |
| config.keepalive_timeout | integer | false | 60000 | | The idle connection timeout for the WAF service, in milliseconds. |
| config.real_client_ip | boolean | false | true | | If 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
| Name | Type | Required | Default | Valid values | Description |
|--------------------------|---------------|----------|---------|--------------|-------------|
| nodes | array[object] | True | | | An array of addresses for the Chaitin WAF service. |
| nodes.host | string | True | | | Address of Chaitin WAF service. Supports IPv4, IPv6, Unix Socket, etc. |
| nodes.port | integer | False | 80 | | Port of Chaitin WAF service. |
| mode | string | False | | block | Mode 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. |
| config | object | False | | | Chaitin WAF service configurations. |
| config.connect_timeout | integer | False | 1000 | | The connection timeout to the WAF service, in milliseconds. |
| config.send_timeout | integer | False | 1000 | | The sending timeout for transmitting data to the WAF service, in milliseconds. |
| config.read_timeout | integer | False | 1000 | | The reading timeout for receiving data from the WAF service, in milliseconds. |
| config.req_body_size | integer | False | 1024 | | The maximum allowed request body size, in KB. |
| config.keepalive_size | integer | False | 256 | | The maximum number of idle connections to the WAF detection service that can be maintained concurrently. |
| config.keepalive_timeout | integer | False | 60000 | | The idle connection timeout for the WAF service, in milliseconds. |
| config.real_client_ip | boolean | False | true | | If 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)](https://docs.waf.chaitin.com/en/GetStarted/Deploy).
:::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:
```bash
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):
```shell
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:
```shell
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:
```shell
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:
```shell
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:
```text
...
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:
```shell
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:
```shell
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:
```shell
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:
```shell
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:
```text
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:
```shell
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:
```shell
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:
```shell
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:
```text
...
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"}
```