OpenResty is a full-fledged web application server based on Nginx and LuaJIT. It offers a powerful and flexible way to build and extend web application servers while maintaining the high performance and reliability of Nginx. OpenResty serves as the foundation for gateway products like APISIX, Kong, and Ingress Nginx, making it an excellent choice as a unified entry point for WAF protection.
In this guide, we'll use the free SafeLine WAF Community Edition. For those interested, you can try it out here:SafeLine Demo.
This article explains how to enhance OpenResty with security protection using the free SafeLine WAF Community Edition and the lua-resty-t1k
plugin, achieving a security architecture that separates forwarding and detection services.
Basic Version
The basic setup involves installing both OpenResty and SafeLine WAF Community Edition on the same host.
Step 1 – Install SafeLine
SafeLine WAF Community Edition offers several installation methods. For detailed instructions, refer to the official documentation.
Step 2 – Configure OpenResty
We'll use the official alpine-fat
image of OpenResty as an example to enable SafeLine WAF protection:
First, navigate to the SafeLine WAF installation directory and ensure the resources/detector
directory exists. Then, start OpenResty:
docker run -d --name openresty -v $(pwd)/resources/detector:/opt/detector
openresty/openresty:alpine-fat
Next, enter the OpenResty container and install the lua-resty-t1k
plugin using luarocks
:
docker exec -it openresty bash
luarocks install lua-resty-t1k
Then, modify the OpenResty configuration located at /etc/nginx/conf.d/default.conf
to add the /t
path for testing WAF protection. Here's the complete configuration, which can be directly applied to 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;
}
}
Finally, validate and reload the OpenResty configuration:
openresty -t && openresty -s reload
Step 3 – Verify
Access /t/shell.php
to verify the protection:
curl http://127.0.0.1/t/shell.php
You should see a response like this:
{"code": 403, "success":false, "message": "blocked by Chaitin SafeLine Web Application Firewall",
"event_id": "2005f374e2c44757a449b1071f284e3b"}
You can also view the corresponding blocking log in the SafeLine WAF Community Edition.
Normal access to /t
should not trigger any blocking:
curl http://127.0.0.1/t/
passed
Advanced Version
In a production environment, SafeLine WAF Community Edition might not be on the same host as OpenResty, or there might be multiple OpenResty instances 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.
Locate the SafeLine WAF installation directory and modify the compose.yaml
file by adding port mapping to the detector
section. Here’s the updated configuration:
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
Next, modify the detection service configuration file resources/detector/snserver.yml
as follows:
fusion_sofile: ./config/libfusion2.so
ip_location_db: ./GeoLite2-City.mmdb
# bind_addr: unix:///resources/detector/snserver.sock # Commented out line
bind_addr: 0.0.0.0 # Newly added line
listen_port: 8000 # Newly added line
Apply the configuration changes by running:
docker compose up -d
You can verify that the detection service port is reachable using the nc
command:
nc -zv ${SafeLine WAF Community Edition Host IP} 8000
Connection to ${SafeLine WAF Community Edition Host IP} 8000 port [tcp/*] succeeded!
Finally, modify the OpenResty configuration file to specify the host
and port
. Here’s the updated configuration:
location /t {
access_by_lua_block {
local t1k = require "resty.t1k"
local t = {
mode = "block",
host = "${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
Now you can verify the security protection. Enjoy a more secure OpenResty setup!
Top comments (0)