OpenResty is a full-featured web application server based on Nginx and LuaJIT. It provides a powerful and flexible way to build and extend web applications while maintaining the high performance and reliability of Nginx. As the foundation for gateway products such as APISIX, Kong, and Ingress Nginx, OpenResty and its derivatives are well-suited as a unified entry point for WAF protection.
Choosing a Free WAF
I use the community edition of SafeLine developed by Chaitin. You can find more information and try it out via this link.
This article will explain how to use the free community edition of SafeLine WAF and the lua-resty-t1k
plugin to add security capability to OpenResty, forming a security architecture that separates forwarding and detection services.
Basic Version
We'll take the example of installing OpenResty and the community edition of SafeLine WAF on the same host.
Step 1: Install SafeLine
The community edition of SafeLine WAF offers multiple installation methods. Refer to the official documentation for detailed instructions. Ensure the version is >= 2.0.0, which you can check in the lower left corner of the management page.
Step 2: Configure OpenResty
Using the official alpine-fat
image of OpenResty as an example, we'll enable SafeLine WAF:
-
Navigate to the installation directory of the SafeLine WAF community edition, check that the
resources/detector
directory exists, and start OpenResty:
docker run -d --name openresty -v $(pwd)/resources/detector:/opt/detector openresty/openresty:alpine-fat
-
Enter the OpenResty container and install the
lua-resty-t1k
plugin withluarocks
:
docker exec -it openresty bash luarocks install lua-resty-t1k
-
Modify the OpenResty configuration at
/etc/nginx/conf.d/default.conf
to add the/t
path for testing WAF protection. Here is the complete configuration, which can directly replace the/etc/nginx/conf.d/default.conf
file:
server { listen 80; server_name localhost; location /t { access_by_lua_block { local t1k = require "resty.t1k" local t = { mode = "block", host = "unix:/opt/detector/snserver.sock", } local ok, err, result = t1k.do_access(t, true) if not ok then ngx.log(ngx.ERR, err) end } header_filter_by_lua_block { local t1k = require "resty.t1k" t1k.do_header_filter() } content_by_lua_block { ngx.say("passed") } } location / { root /usr/local/openresty/nginx/html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/local/openresty/nginx/html; } }
-
Validate and reload the OpenResty configuration:
openresty -t && openresty -s reload
Step 3: Verification
Access /t/shell.php
to verify the protection effect:
curl http://127.0.0.1/t/shell.php
Expected return:
{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall", "event_id": "2005f374e2c44757a449b1071f284e3b"}
You should also see corresponding interception logs in the community edition of SafeLine WAF.
Normal access to /t
will not trigger interception:
curl http://127.0.0.1/t/
Expected return:
passed
Advanced Version
In a production environment, the community edition of SafeLine WAF might not be on the same host as OpenResty, or there might be multiple OpenResty instances distributed across different hosts. In this case, you need to map the detection service to a specified port on the host so that other hosts can access it via the network.
-
Navigate to the installation directory of SafeLine WAF Community Edition,modify the
compose.yaml
file to add port mapping:
... detector: container_name: safeline-detector restart: always image: chaitin/safeline-detector:${IMAGE_TAG} volumes: - ${SAFELINE_DIR}/resources/detector:/resources/detector - ${SAFELINE_DIR}/logs/detector:/logs/detector - /etc/localtime:/etc/localtime:ro environment: - LOG_DIR=/logs/detector networks: safeline-ce: ipv4_address: ${SUBNET_PREFIX}.5 cap_drop: - net_raw ports: ["8000:8000"] # Newly added line ...
-
Modify the configuration file
resources/detector/snserver.yml
of detection services:
fusion_sofile: ./config/libfusion2.so ip_location_db: ./GeoLite2-City.mmdb # bind_addr: unix:///resources/detector/snserver.sock # Commented out bind_addr: 0.0.0.0 # Newly added line listen_port: 8000 # Newly added line
-
Execute the following command to apply the modification:
docker compose up -d
-
Use the
nc
command to verify that the detection service port is reachable:
nc -zv ${Chaitin SafeLine WAF Community Edition Host IP} 8000
Expected return:
Connection to ${Chaitin SafeLine WAF Community Edition Host IP} 8000 port [tcp/*] succeeded!
-
Modify the OpenResty configuration file to specify the
host
andport
:
... location /t { access_by_lua_block { local t1k = require "resty.t1k" local t = { mode = "block", host = "${Chaitin SafeLine WAF Community Edition Host IP}", port = 8000, } local ok, err, result = t1k.do_access(t, true) if not ok then ngx.log(ngx.ERR, err) end } header_filter_by_lua_block { local t1k = require "resty.t1k" t1k.do_header_filter() } content_by_lua_block { ngx.say("passed") } } ...
-
Validate and reload the OpenResty configuration:
openresty -t && openresty -s reload
You can now verify the security protection capabilities.
Enjoy a more secure OpenResty!
Top comments (0)