How to Secure OpenResty with a Free WAF

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 p…


This content originally appeared on DEV Community and was authored by Carrie

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:

  1. 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
    
  2. Enter the OpenResty container and install the lua-resty-t1k plugin with luarocks:

    docker exec -it openresty bash
    luarocks install lua-resty-t1k
    
  3. 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;
        }
    }
    
  4. 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.

  1. 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
    ...
    
  2. 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
    
  3. Execute the following command to apply the modification:

    docker compose up -d
    
  4. 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!
    
  5. Modify the OpenResty configuration file to specify the host and port:

    ...
    
    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")
        }
    }
    
    ...
    
  6. Validate and reload the OpenResty configuration:

    openresty -t && openresty -s reload
    

You can now verify the security protection capabilities.

Enjoy a more secure OpenResty!


This content originally appeared on DEV Community and was authored by Carrie


Print Share Comment Cite Upload Translate Updates
APA

Carrie | Sciencx (2024-09-19T02:52:17+00:00) How to Secure OpenResty with a Free WAF. Retrieved from https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/

MLA
" » How to Secure OpenResty with a Free WAF." Carrie | Sciencx - Thursday September 19, 2024, https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/
HARVARD
Carrie | Sciencx Thursday September 19, 2024 » How to Secure OpenResty with a Free WAF., viewed ,<https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/>
VANCOUVER
Carrie | Sciencx - » How to Secure OpenResty with a Free WAF. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/
CHICAGO
" » How to Secure OpenResty with a Free WAF." Carrie | Sciencx - Accessed . https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/
IEEE
" » How to Secure OpenResty with a Free WAF." Carrie | Sciencx [Online]. Available: https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/. [Accessed: ]
rf:citation
» How to Secure OpenResty with a Free WAF | Carrie | Sciencx | https://www.scien.cx/2024/09/19/how-to-secure-openresty-with-a-free-waf/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.