Skip to main content
Version: 3.9

chaitin-waf

Description#

After enabling the chaitin-waf plugin, the traffic will be forwarded to the Chaitin WAF service for the detection and prevention of various web application attacks, ensuring the security of the application and user data.

Response Headers#

Depending on the plugin configuration, it is optional to add additional response headers.

The response headers are listed below:

  • X-APISIX-CHAITIN-WAF: Whether APISIX forwards the request to the WAF server.
    • yes: forwarded
    • no: no forwarded
    • unhealthy: matches the match variables, but no WAF server is available.
    • err: an error occurred during the execution of the plugin. Also with X-APISIX-CHAITIN-WAF-ERROR request header
    • waf-err: Error while interacting with the WAF server. Also with X-APISIX-CHAITIN-WAF-ERROR request header
    • timeout: Timeout for request to the WAF server
  • X-APISIX-CHAITIN-WAF-ERROR: Debug header. WAF error message
  • X-APISIX-CHAITIN-WAF-TIME: The time in milliseconds that APISIX spent interacting with WAF.
  • X-APISIX-CHAITIN-WAF-STATUS: The status code returned to APISIX by the WAF server.
  • X-APISIX-CHAITIN-WAF-ACTION: Processing result returned to APISIX by the WAF server.
    • pass: request valid and passed
    • reject: request rejected by WAF service
  • X-APISIX-CHAITIN-WAF-SERVER: Debug header. Picked WAF server.

Plugin Metadata#

NameTypeRequiredDefault valueDescription
nodesarray(object)trueA list of addresses for the Chaitin SafeLine WAF service.
nodes[0].hoststringtrueThe address of Chaitin SafeLine WAF service. Supports IPV4, IPV6, Unix Socket, etc.
nodes[0].portstringfalse80The port of Chaitin SafeLine WAF service.
configobjectfalseConfiguration of the Chaitin SafeLine WAF service. The parameters configured here will be used when route is not configured.
config.connect_timeoutintegerfalse1000connect timeout, in milliseconds
config.send_timeoutintegerfalse1000send timeout, in milliseconds
config.read_timeoutintegerfalse1000read timeout, in milliseconds
config.req_body_sizeintegerfalse1024request body size, in KB
config.keepalive_sizeintegerfalse256maximum concurrent idle connections to the SafeLine WAF detection service
config.keepalive_timeoutintegerfalse60000idle connection timeout, in milliseconds

An example configuration is as follows.

curl http://127.0.0.1:9180/apisix/admin/plugin_metadata/chaitin-waf -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"nodes":[
{
"host": "unix:/path/to/safeline/resources/detector/snserver.sock",
"port": 8000
}
]
}'

Attributes#

NameTypeRequiredDefault valueDescription
matcharray[object]falseThe list of matching rules, default is empty
match.varsarray[array]falseList of variables to match for filtering requests for conditional traffic split. It is in the format {variable operator value}. For example, {"arg_name", "==", "json"}. The variables here are consistent with NGINX internal variables. For details on supported operators, lua-resty-expr.
append_waf_resp_headerboolfalsetrueWhether to add response headers
append_waf_debug_headerboolfalsefalseWhether or not to add debugging headers, effective when add_header is true.
configobjectfalseConfiguration of the Chaitin SafeLine WAF service. When the route is not configured, the parameters configured in the metadata are used.
config.connect_timeoutintegerfalseconnect timeout, in milliseconds
config.send_timeoutintegerfalsesend timeout, in milliseconds
config.read_timeoutintegerfalseread timeout, in milliseconds
config.req_body_sizeintegerfalserequest body size, in KB
config.keepalive_sizeintegerfalsemaximum concurrent idle connections to the SafeLine WAF detection service
config.keepalive_timeoutintegerfalseidle connection timeout, in milliseconds

A sample configuration is shown below, using httpbun.org as the example backend, which can be replaced as needed:

curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/*",
"plugins": {
"chaitin-waf": {
"match": [
{
"vars": [
["http_waf","==","true"]
]
}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbun.org:80": 1
}
}
}'

Test Plugin#

Test the above example configuration.

If the match condition is not met, the request can be reached normally:

curl -H "Host: httpbun.org" http://127.0.0.1:9080/get -i

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 408
Connection: keep-alive
X-APISIX-CHAITIN-WAF: no
Date: Wed, 19 Jul 2023 09:30:42 GMT
X-Powered-By: httpbun/3c0dc05883dd9212ac38b04705037d50b02f2596
Server: APISIX/3.3.0

{
"args": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbun.org",
"User-Agent": "curl/8.1.2",
"X-Forwarded-For": "127.0.0.1",
"X-Forwarded-Host": "httpbun.org",
"X-Forwarded-Port": "9080",
"X-Forwarded-Proto": "http",
"X-Real-Ip": "127.0.0.1"
},
"method": "GET",
"origin": "127.0.0.1, 122.231.76.178",
"url": "http://httpbun.org/get"
}

Potential injection requests are also forwarded as is and encounter a 404 error:

curl -H "Host: httpbun.org" http://127.0.0.1:9080/getid=1%20AND%201=1 -i

HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
Content-Length: 19
Connection: keep-alive
X-APISIX-CHAITIN-WAF: no
Date: Wed, 19 Jul 2023 09:30:28 GMT
X-Content-Type-Options: nosniff
X-Powered-By: httpbun/3c0dc05883dd9212ac38b04705037d50b02f2596
Server: APISIX/3.3.0

404 page not found

Normal requests are still reachable when the match condition is met:

curl -H "Host: httpbun.org" -H "waf: true" http://127.0.0.1:9080/get -i

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 427
Connection: keep-alive
X-APISIX-CHAITIN-WAF-TIME: 2
X-APISIX-CHAITIN-WAF-STATUS: 200
X-APISIX-CHAITIN-WAF: yes
X-APISIX-CHAITIN-WAF-ACTION: pass
Date: Wed, 19 Jul 2023 09:29:58 GMT
X-Powered-By: httpbun/3c0dc05883dd9212ac38b04705037d50b02f2596
Server: APISIX/3.3.0

{
"args": {},
"headers": {
"Accept": "*/*",
"Connection": "close",
"Host": "httpbun.org",
"User-Agent": "curl/8.1.2",
"Waf": "true",
"X-Forwarded-For": "127.0.0.1",
"X-Forwarded-Host": "httpbun.org",
"X-Forwarded-Port": "9080",
"X-Forwarded-Proto": "http",
"X-Real-Ip": "127.0.0.1"
},
"method": "GET",
"origin": "127.0.0.1, 122.231.76.178",
"url": "http://httpbun.org/get"
}

Potential attack requests will be intercepted and returned a 403 error:

curl -H "Host: httpbun.org" -H "waf: true" http://127.0.0.1:9080/getid=1%20AND%201=1 -i

HTTP/1.1 403 Forbidden
Date: Wed, 19 Jul 2023 09:29:06 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-APISIX-CHAITIN-WAF: yes
X-APISIX-CHAITIN-WAF-TIME: 2
X-APISIX-CHAITIN-WAF-ACTION: reject
X-APISIX-CHAITIN-WAF-STATUS: 403
Server: APISIX/3.3.0
Set-Cookie: sl-session=UdywdGL+uGS7q8xMfnJlbQ==; Domain=; Path=/; Max-Age=86400

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

Delete Plugin#

To remove the chaitin-waf plugin, you can delete the corresponding JSON configuration from the Plugin configuration. APISIX will automatically reload and you do not have to restart for this to take effect:

$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/*",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbun.org:80": 1
}
}
}'