chaitin-waf
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. • 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-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. • pass: Request was allowed by the WAF service.• 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. |
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).
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.
- Admin API
- ADC
- Ingress Controller
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_API_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_API_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
}
}
}'
❶ Set mode to block to block requests identified to be malicious.
❷ Set append_waf_resp_header to true to include WAF-related standard response headers.
❸ Set append_waf_debug_header to true to include WAF-related debugging response headers.
plugin_metadata:
chaitin-waf:
nodes:
- host: "172.22.222.5"
port: 8000
services:
- name: chaitin-waf-service
routes:
- name: chaitin-waf-route
uris:
- /anything
plugins:
chaitin-waf:
mode: block
append_waf_resp_header: true
append_waf_debug_header: true
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ nodes: List of Chaitin WAF service addresses. Update the host and port to match your Chaitin WAF (SafeLine) deployment.
❷ Set mode to block to block requests identified to be malicious.
❸ Set append_waf_resp_header to true to include WAF-related standard response headers.
❹ Set append_waf_debug_header to true to include WAF-related debugging response headers.
Update your GatewayProxy manifest to configure the plugin metadata. If Chaitin WAF is installed on a host machine outside the cluster, use the host's IP address. In most deployments, expose Chaitin WAF as a reachable Service, IP address, or DNS name inside the cluster, or use the node/LoadBalancer address instead.
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# ...
# your control plane connection configuration
pluginMetadata:
chaitin-waf:
nodes:
- host: "172.22.222.5"
port: 8000
❶ nodes: List of Chaitin WAF service addresses. Update the host and port to match your Chaitin WAF (SafeLine) deployment.
- Gateway API
- APISIX CRD
Create a route with chaitin-waf to block malicious requests:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: chaitin-waf-plugin-config
spec:
plugins:
- name: chaitin-waf
config:
mode: block
append_waf_resp_header: true
append_waf_debug_header: true
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: chaitin-waf-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f chaitin-waf-ic.yaml
Create a route with chaitin-waf to block malicious requests:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
ingressClassName: apisix
http:
- name: chaitin-waf-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: chaitin-waf
enable: true
config:
mode: block
append_waf_resp_header: true
append_waf_debug_header: true
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f chaitin-waf-ic.yaml
❷ Set mode to block to block requests identified to be malicious.
❸ Set append_waf_resp_header to true to include WAF-related standard response headers.
❹ Set append_waf_debug_header to true to include WAF-related debugging response headers.
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.
- Admin API
- ADC
- Ingress Controller
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_API_KEY}' \
-d '{
"nodes": [
{
"host": "172.22.222.5",
"port": 8000
}
],
"mode": "monitor"
}'
❶ Set mode to monitor in the plugin metadata. This applies to all chaitin-waf plugin instances if mode is not specified on a route.
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_API_KEY}" \
-d '{
"id": "chaitin-waf-route",
"uri": "/anything",
"plugins": {
"chaitin-waf": {}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
plugin_metadata:
chaitin-waf:
nodes:
- host: "172.22.222.5"
port: 8000
mode: monitor
services:
- name: chaitin-waf-service
routes:
- name: chaitin-waf-route
uris:
- /anything
plugins:
chaitin-waf: {}
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ nodes: List of Chaitin WAF service addresses. Update the host and port to match your Chaitin WAF (SafeLine) deployment.
❷ Set mode to monitor in the plugin metadata. This applies to all chaitin-waf plugin instances if mode is not specified on a route.
Update your GatewayProxy manifest to configure the plugin metadata. If Chaitin WAF is installed on a host machine outside the cluster, use the host's IP address. In most deployments, expose Chaitin WAF as a reachable Service, IP address, or DNS name inside the cluster, or use the node/LoadBalancer address instead.
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# ...
# your control plane connection configuration
pluginMetadata:
chaitin-waf:
nodes:
- host: "172.22.222.5"
port: 8000
mode: monitor
❶ Set mode to monitor in the plugin metadata. This applies to all chaitin-waf plugin instances if mode is not specified on a route.
- Gateway API
- APISIX CRD
Create a route with chaitin-waf enabled without any plugin-level configuration, so it inherits the monitor mode from the plugin metadata:
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: chaitin-waf-plugin-config
spec:
plugins:
- name: chaitin-waf
config: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: chaitin-waf-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f chaitin-waf-ic.yaml
To override the monitor mode and block malicious requests on the route, update the PluginConfig to set mode: block:
# other configs
# ---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: chaitin-waf-plugin-config
spec:
plugins:
- name: chaitin-waf
config:
mode: block
Apply the updated configuration to your cluster:
kubectl apply -f chaitin-waf-ic.yaml
Create a route with chaitin-waf enabled without any plugin-level configuration, so it inherits the monitor mode from the plugin metadata:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
ingressClassName: apisix
http:
- name: chaitin-waf-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: chaitin-waf
enable: true
config: {}
Apply the configuration to your cluster:
kubectl apply -f gatewayproxy.yaml -f chaitin-waf-ic.yaml
To override the monitor mode and block malicious requests on the route, update the ApisixRoute to set mode: block:
# other configs
# ---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
ingressClassName: apisix
http:
- name: chaitin-waf-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: chaitin-waf
enable: true
config:
mode: block
Apply the updated configuration to your cluster:
kubectl apply -f chaitin-waf-ic.yaml
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:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "chaitin-waf-route",
"uri": "/anything",
"plugins": {
"chaitin-waf": {
"mode": "block"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
plugin_metadata:
chaitin-waf:
nodes:
- host: "172.22.222.5"
port: 8000
mode: monitor
services:
- name: chaitin-waf-service
routes:
- name: chaitin-waf-route
uris:
- /anything
plugins:
chaitin-waf:
mode: block
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
Update the PluginConfig to set mode: block:
# other configs
# ---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: chaitin-waf-plugin-config
spec:
plugins:
- name: chaitin-waf
config:
mode: block
Apply the updated configuration to your cluster:
kubectl apply -f chaitin-waf-ic.yaml
Update the ApisixRoute to set mode: block:
# other configs
# ---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: chaitin-waf-route
spec:
ingressClassName: apisix
http:
- name: chaitin-waf-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: chaitin-waf
enable: true
config:
mode: block
Apply the updated configuration to your cluster:
kubectl apply -f chaitin-waf-ic.yaml
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"}