Skip to content

web WAF

OpenResty + Lua WAF + Lua 简单风控统计 + GoAccess / Prometheus / Grafana

my-waf-resty


├─ conf/               # nginx.conf + vhost conf
│   ├─ nginx.conf
│   └─ sites-enabled/

├─ lua/                # Lua WAF 脚本
│   └─ waf.lua

├─ logs/               # access + error logs
│   ├─ access.log
│   └─ error.log
sh
docker network create -d bridge nginx-proxy-net

创建所需目录

sh
mkdir conf lua logs conf.d ssl www
mkdir -p prometheus/data grafana/data

copy nginx.conf

sh
docker run --rm registry.cn-chengdu.aliyuncs.com/qins-img/openresty:1.27.1.2-jwt cat /usr/local/openresty/nginx/conf/nginx.conf > ./conf/nginx.conf

# 或

# 1. 启动临时容器
docker run --name openresty-temp registry.cn-chengdu.aliyuncs.com/qins-img/openresty:1.27.1.2-jwt

# 2. 拷贝整个 conf 目录到宿主机
docker cp openresty-temp:/usr/local/openresty/nginx/conf ./conf

# 3. 删除临时容器
docker rm -f openresty-temp

copy prometheus 配置

sh
docker run --rm --entrypoint cat prom/prometheus:v2.54.1 /etc/prometheus/prometheus.yml > ./prometheus/prometheus.yml

修改 配置,添加 nginx 相关 vim prometheus/prometheus.yml

yml
- job_name: "nginx"
  static_configs:
    - targets: ["nginx-exporter:9113"]
sh
vim docker-compose.yml
yml
networks:
  nginx-proxy-net:
    external: true

services:
  openresty:
    image: registry.cn-chengdu.aliyuncs.com/qins-img/openresty:1.27.1.2-jwt
    container_name: my-waf-resty
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./conf:/usr/local/openresty/nginx/conf
      - ./lua:/usr/local/openresty/lualib/custom
      - ./logs:/usr/local/openresty/nginx/logs
      - ./conf.d:/etc/nginx/conf.d
      - ./ssl:/etc/nginx/ssl
      - /mydata/web-static:/mydata/web-static
      - ./www:/data/www
      - ./www-goaccess:/data/www-goaccess
    environment:
      - TZ=Asia/Shanghai
    restart: unless-stopped
    networks:
      - nginx-proxy-net
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "5"

  nginx-exporter:
    image: nginx/nginx-prometheus-exporter:1.1.0
    container_name: nginx-exporter
    command: ["--nginx.scrape-uri=http://openresty:4102/nginx_status"]
    depends_on:
      - openresty
    networks:
      - nginx-proxy-net

  prometheus:
    image: prom/prometheus:v2.54.1
    container_name: prometheus
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./prometheus/data:/prometheus
    ports:
      - "4101:9090"
    networks:
      - nginx-proxy-net

  grafana:
    image: grafana/grafana:11.0.0
    container_name: grafana
    ports:
      - "4100:3000"
    environment:
      - GF_SECURITY_ADMIN_USER=qin
      - GF_SECURITY_ADMIN_PASSWORD=你的密码
    networks:
      - nginx-proxy-net
    volumes:
      - ./grafana/data:/var/lib/grafana
    #   - ./grafana/conf:/etc/grafana

日志

nginx
http {
log_format main '$remote_addr - $remote_user [$time_local] '
                '"$request" $status $body_bytes_sent '
                '"$http_referer" "$http_user_agent"';

log_format nginxlog_json escape=json '{ "timestamp": "$time_iso8601", '
    '"remote_addr": "$remote_addr", "body_bytes_sent": $body_bytes_sent, '
    '"request_time": $request_time, "response_status": $status, '
    '"request": "$request", "request_method": "$request_method", '
    '"host": "$host", "upstream_addr": "$upstream_addr", '
    '"http_x_forwarded_for": "$http_x_forwarded_for", '
    '"http_referrer": "$http_referer", '
    '"http_user_agent": "$http_user_agent", '
    '"http_version": "$server_protocol", '
    '"nginx_access": true }';

access_log logs/access.log main;
access_log /dev/stdout nginxlog_json;
}
sudo vim /etc/logrotate.d/my-waf-resty
/mydata/my-waf-resty/logs/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    copytruncate
    su root root
}
sh
# 检查
sudo logrotate -f /etc/logrotate.d/my-waf-resty
  • daily:每天轮转
  • rotate 7:保留最近 7 个文件
  • compress:压缩历史日志
  • copytruncate:保持 nginx 继续写同一文件

Prometheus + Grafana

admin/gr

goaccess

放弃

goaccess:
    image: allinurl/goaccess:latest
    container_name: goaccess
    depends_on:
      - openresty
    volumes:
      - ./logs:/var/log/nginx:ro
      - ./www-goaccess:/var/www/html
    ports:
      - "7890:7890"
    networks:
      - nginx-proxy-net
    command: >
      /var/log/nginx/access.log
      --log-format=COMBINED
      --real-time-html
      -o /var/www/html/report.html
      --ws-url=118.25.219.177

111

第一步:
完善 OpenResty + 限流 + 黑名单

第二步:
开启基础监控(连接数 + 5xx)

第三步:
再接 Prometheus

流量管理( 限流/黑白名)

攻击防护(SQL注入、XSS、CSRF)

日志与可观测

规则管理

  • 访问控制(IP、区域、User-Agent、Referer)
  • 速率限制(单 IP 限流、全局 QPS 限制)
  • 异常流量识别(高频访问、扫描行为)

合格的网关

  1. 稳定性(不单点)
  2. 可观测(能看见问题)
  3. 可控(能封禁)
  4. 可恢复(崩了能恢复)
  5. 可扩展(未来能升级)

限流

Nginx 自带

黑名单持久化

Lua 读取 Redis

自动封禁

Lua + Redis

结构化日志