UUSEC WAF Docker Compose 部署指南

UUSEC WAF 7.2.6 Docker Compose 部署全链路实测:起栈、管理台初始化、添加防护站点、正常回源与攻击拦截验证,含数据持久化、等价启动与踩坑记录

UUSEC WAF安全WAF2026/10/21

UUSEC WAF Docker Compose 部署指南

目标:以 UUSEC WAF(南墙)v7.2.6 为例,走通官方 Docker Compose 部署主线的全链路:起栈 → 管理台初始化 → 添加防护站点 → 正常回源验证 → 攻击拦截验证,并给出数据持久化、等价启动方式与常见问题的实测结论。 本篇全部命令与回显均在下述实验环境实测照抄;管理台操作同时提供 REST API 调用方式(官方 FAQ 认可的管理接口,认证方式见 《UUSEC WAF 7.2.6 管理 API 使用详解》)。

一、环境信息

  • 实验主机:Ubuntu 22.04.4 LTS,x86_64,内核 6.8(uname -m 回显 x86_64)
  • Docker:Docker 29.8.1(docker version --format 'Docker {{.Server.Version}}' 实测回显),Compose v2 语法插件 5.5.1(docker compose version --short 实测回显)
  • 软件版本:UUSEC WAF 7.2.6(官方镜像 uusec/waf:latest 与 uusec/waf:7.2.6 同步于 2026-10-12);元数据库 mysql:5.7
  • 部署目录:/opt/waf/(官方默认,本篇以 /opt/data/quzuo/tmp/uusec-waf/waf/ 等价替代,路径可自定义)
  • 端口占用说明:实验宿主 80 端口已被宿主上既有服务占用,故本篇实测将数据面 HTTP 监听从 80 调整为 8133(调整方法见第八章),443/4443/777/4447/6612 保持官方默认;生产环境若 80 空闲,无需任何调整
  • 演示域名:wafdemo.example.com(A 记录指向 WAF 服务器;本篇用 curl --resolve 等价模拟域名解析)
  • 演示源站:WAF 服务器本机 127.0.0.1:8139 的静态 Web 服务(代表"网站服务器 IP")

二、镜像选型说明

官方通过 Docker Hub 发布引擎镜像(docker hub uusec/waf,查询日期 2026-10-20):

镜像与 tag更新日期压缩体积说明
uusec/waf:latest2026-10-12156 MB官方 compose 默认引用,当前即 7.2.6
uusec/waf:7.2.62026-10-12156 MB与 latest 同步的版本固定 tag(推荐生产使用)
uusec/waf:7.2.52026-08-05156 MB上一稳定版
uusec/waf:7.2.02026-03-20161 MB7.2 系列首个版本

选型结论与实测口径:

  • 版本固定:官方 compose 引用 uusec/waf:latest。生产建议改成 uusec/waf:7.2.6 固定版本,升级动作显式可控(官方升级逻辑 manager.sh 选项 4 也是"重新下载 compose 文件 + pull 最新镜像",本质同样由 latest 驱动)。
  • 元数据库镜像:官方固定 mysql:5.7(本机实测拉取后 700 MB),不建议自行换成 8.x——uuwaf 服务的 UUWAF_DB_DSN 与官方初始化的库表结构按 5.7 交付;内存紧张的服务器官方还提供了低内存 MySQL 配置模板 low-memory-my.cnf(在 compose 中取消注释即可挂载生效)。
  • 本机实测落盘体积:uusec/waf:latest 约 615 MB,mysql:5.7 约 700 MB。

三、前置条件

  1. 架构:x86_64 专用(官方 installer.sh 明确不支持 ARM)。
  2. Docker 环境:Docker CE 20.10.14 以上、Compose 2.0.0 以上(官方 README 要求;本篇实测为 29.8.1/5.5.1)。验证命令:
# docker version --format 'Docker {{.Server.Version}}'
Docker 29.8.1
# docker compose version --short
5.5.1
  1. 端口规划(官方 installer.sh 预检端口 80/443/777/4443/4447/6612;生产需全部空闲):
端口用途本篇实测值
80 / 443站点 HTTP / HTTPS 流量(数据面 nginx)8133 / 443(80 被宿主占用改为 8133)
4443Web 管理台(HTTPS)4443
777人机验证(验证码)组件端口777
4447WAF 节点内部管理端口(仅 127.0.0.1,见 config.json waf_nodes)4447
6612元数据库 MySQL 对宿主映射6612
  1. 磁盘:镜像与数据落盘合计约 2 GB 起步(含 MySQL 数据目录)。
  2. 准备演示源站(代表被防护的真实网站,监听 127.0.0.1:8139):
# mkdir -p /opt/waf-demo && cat > /opt/waf-demo/index.html <<'EOF'
<!DOCTYPE html>
<html><head><title>WAF Demo Origin</title></head>
<body><h1>WAF Demo Origin Server</h1><p>backend page for UUSEC WAF protect test</p></body></html>
EOF
# docker run -d --name waf-demo-origin -p 127.0.0.1:8139:80 -v /opt/waf-demo:/usr/share/nginx/html:ro nginx:alpine
# curl -s -m 5 http://127.0.0.1:8139/ | head -2
<!DOCTYPE html>
<html><head><title>WAF Demo Origin</title></head>

四、部署步骤

4.1 获取官方部署包

官方一键安装脚本(sudo bash -c "$(curl -fsSL https://waf.uusec.com/installer.sh)")内部逻辑是:预检端口 → 安装 Docker(如缺失)→ 下载 https://waf.uusec.com/docker.tgz → 解压到 /opt/waf/。本篇直接取该安装包做显式 compose 编排(便于目录与版本自控):

# curl -fsSL -o docker.tgz https://waf.uusec.com/docker.tgz
# tar -zxf docker.tgz && ls waf/
docker-compose.yml  install-docker.sh  low-memory-my.cnf  manager.sh

安装包含 4 个文件:docker-compose.yml(编排定义)、manager.sh(管理脚本)、install-docker.sh(Docker 自动安装)、low-memory-my.cnf(低内存 MySQL 模板)。

4.2 编写 compose 文件与 .env

在官方 docker-compose.yml 基础上做两处显式化改编(其余保持官方原文):① 顶部加 name: 固定项目名,防止同名项目冲突与误删;② 给 uuwaf 服务增加 ./waf_conf:/uuwaf/conf 挂载(官方未挂载数据面 nginx 配置目录,挂出后改端口才能持久化,见第八章)。最终文件:

name: uusec-waf-7-2-6-stack

networks:
  wafnet:
    name: wafnet
    driver: bridge
    ipam:
      driver: default
      config:
      - gateway: 172.31.254.1
        subnet: 172.31.254.0/24
    driver_opts:
      com.docker.network.bridge.name: wafnet

services:
  uuwaf:
    image: uusec/waf:latest
    ulimits:
      nproc: 65535
      nofile:
        soft: 102400
        hard: 102400
    container_name: uuwaf
    restart: always
    network_mode: host
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - ./waf_config:/uuwaf/web/conf
      - ./waf_acme:/uuwaf/acme
      - ./waf_conf:/uuwaf/conf
      - ./waf_logs:/uuwaf/logs
    environment:
      - UUWAF_DB_DSN=root:${MYSQL_PASSWORD}@tcp(127.0.0.1:6612)/uuwaf?charset=utf8mb4&parseTime=true&loc=Local
    depends_on:
      wafdb:
        condition: service_healthy

  wafdb:
    image: mysql:5.7
    ulimits:
      nproc: 65535
      nofile:
        soft: 102400
        hard: 102400
    container_name: wafdb
    restart: always
    networks:
      wafnet:
        ipv4_address: 172.31.254.3
    ports:
      - "6612:3306"
    volumes:
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - ./waf_data:/var/lib/mysql
      #- ./low-memory-my.cnf:/etc/mysql/my.cnf
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
    command: ["--max_connections=512"]
    healthcheck:
      test: ["CMD", "mysqladmin", "-uroot", "-p${MYSQL_PASSWORD}", "ping", "-h", "127.0.0.1", "--silent"]
      start_period: 3s
      interval: 5s
      timeout: 3s
      retries: 10

配套 .env(官方脚本逻辑:不存在时自动生成 32 位随机密码;本篇用演示值):

MYSQL_PASSWORD=q1w2e3r4

⚠️ 注意:MYSQL_PASSWORD 是元数据库 root 密码,生产必须使用强随机值(官方自动生成逻辑:LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32);uuwaf 通过 UUWAF_DB_DSN 环境变量引用同一密码,两处必须一致。

4.3 启动与状态验证

# docker compose up -d
[+] Running 3/3
 ✔ Network wafnet   Created
 ✔ Container wafdb  Healthy
 ✔ Container uuwaf  Started
# docker compose ps --format '{{.Name}} {{.Status}}'
uuwaf Up 12 seconds
wafdb Up 15 seconds (healthy)

启动要点实测:

  • wafdb 带健康检查(mysqladmin ping),uuwaf 通过 depends_on: condition: service_healthy 等待数据库就绪后才启动,实测输出中 wafdb 先进入 Healthy;
  • uuwaf 使用 network_mode: host(数据面直接监听宿主 80/443/8133/4443/777/4447),wafdb 走 wafnet 桥接网络(子网 172.31.254.0/24,固定 IP 172.31.254.3),并把 3306 映射到宿主 6612 供 uuwaf 的 DSN(指向 127.0.0.1:6612)访问;
  • 实测监听快照(启动后):
# ss -ltn | grep -E ':(8133|443|4443|777|4447|6612) '
LISTEN 0  511   0.0.0.0:8133  0.0.0.0:*     # 数据面 HTTP(本篇改为 8133)
LISTEN 0  511   0.0.0.0:443   0.0.0.0:*     # 数据面 HTTPS
LISTEN 0  4096  *:4443        *:*           # 管理台
LISTEN 0  4096  [::]:777      [::]:*        # 人机验证
LISTEN 0  4096  127.0.0.1:4447 0.0.0.0:*    # 节点内部端口(仅本机)
LISTEN 0  4096  0.0.0.0:6612  0.0.0.0:*     # 元数据库映射

4.4 管理台初始化(改默认密码)

浏览器访问 https://<服务器IP>:4443(自签名证书,需信任),默认账号 admin、默认密码 #Passw0rd(官方 README 明示)。以下同步给出 REST API 等价操作(便于自动化;JWT 令牌后续 API 调用统一携带):

# 默认密码登录
# curl -sk -X POST 'https://127.0.0.1:4443/api/v1/users/login' \
      -H 'Content-Type: application/json' \
      -d '{"usr":"admin","pwd":"#Passw0rd"}'
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRtaW4iLCJyb2xlIjowLCJleHAiOjE3OTI1NjQ4OTl9.xxxxxx"}

⚠️ 注意:产品强制密码复杂度(8 位以上且含大小写字母、数字、特殊字符),并带登录失败锁定(实测连错提示「用户名或密码错误,还剩N次机会」)。默认密码 #Passw0rd 虽合规,但属于公开默认值,首次登录后必须修改。本篇实测改为 Q1w2e3r4#(满足复杂度的演示值,生产请另用强随机密码)。改密需携带旧密码字段 old_pwd 全量提交:

# TOKEN=$(curl -sk -X POST 'https://127.0.0.1:4443/api/v1/users/login' \
      -H 'Content-Type: application/json' -d '{"usr":"admin","pwd":"#Passw0rd"}' \
      | python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
# curl -sk -X PUT 'https://127.0.0.1:4443/api/v1/users' \
      -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
      -d '{"id":1,"usr":"admin","old_pwd":"#Passw0rd","pwd":"Q1w2e3r4#","role":0,"pwd_expiration":0,"enable_otp":false,"otp":"","otp_url":""}'
"OK"
# 新密码复登验证
# curl -sk -X POST 'https://127.0.0.1:4443/api/v1/users/login' \
      -H 'Content-Type: application/json' -d '{"usr":"admin","pwd":"Q1w2e3r4#"}' | head -c 60
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsInVzZXJuYW1lIjoiYWRta

💡 说明:管理台同时支持 TOTP 两步验证(用户对象含 enable_otp/otp/otp_url 字段,用户列表接口回显 otp_url),生产建议开启。

4.5 添加防护站点

在管理台"站点管理"添加:域名 wafdemo.example.com,网站服务器(源站)IP 127.0.0.1、端口 8139。REST API 等价操作(必须全字段提交,原因见 4.6 与第十一章):

# TOKEN=<按 4.4 方式登录新密码获取>
# curl -sk -X POST 'https://127.0.0.1:4443/api/v1/sites' \
      -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -d '{
        "hosts":["wafdemo.example.com"],"description":"WAF Demo","mode":true,
        "type":"roundrobin","scheme":"http","ruleset_id":1,
        "ip_whitelist":[],"url_whitelist":[],"custom_host":"","deny_page":"",
        "is_websocket":true,"is_ml":false,"is_cache":false,"force_ssl":false,
        "ip_source":0,"ip_order":2,"ip_header":"",
        "servers":[{"ip":"127.0.0.1","port":8139,"weight":1}]}'
"OK"
# 查询确认
# curl -sk "https://127.0.0.1:4443/api/v1/sites" -H "Authorization: Bearer $TOKEN" \
      | python3 -c "import sys,json;[print(s['id'],s['hosts'],s['servers']) for s in json.load(sys.stdin)['sites']]"
1 ['*'] [{'ip': '76.76.21.21', 'port': 443, 'weight': 1}]
2 ['wafdemo.example.com'] [{'ip': '127.0.0.1', 'port': 8139, 'weight': 1}]

站点字段速查(实测 GET /sites 回显归纳):hosts 域名列表(可多个);servers 源站列表(ip/port/weight);scheme 回源协议 http/https;type 负载均衡方式(roundrobin 等);mode 站点启用开关;is_cache/is_ml/is_websocket/force_ssl 分别为缓存加速/机器学习/Websocket/强制 HTTPS 开关;ip_whitelist/url_whitelist 为 IP 与 URL 白名单;ruleset_id 绑定的规则集(1 为内置 Default);ip_source/ip_order/ip_header 控制真实客户端 IP 取值来源。

4.6 正常回源验证

# curl -s --resolve wafdemo.example.com:8133:127.0.0.1 'http://wafdemo.example.com:8133/' -D -
HTTP/1.1 200 OK
Server: uuWAF
Date: Tue, 20 Oct 2026 18:39:50 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Waf-Cache: BYPASS

(响应体为源站页面 WAF Demo Origin Server,实测照抄)

验证要点(官方 Quick Start 同款判据):响应头 Server: uuWAF 证明流量经 WAF 转发;X-Waf-Cache: BYPASS 表示该请求未命中 CDN 缓存(动态请求直回源,命中时为 HIT);响应体为源站内容证明回源成功。HTTPS 同理:

# curl -sk --resolve wafdemo.example.com:443:127.0.0.1 'https://wafdemo.example.com/' -o /dev/null -w '%{http_code}\n'
200
# 站点未配置证书时 WAF 默认证书(实测):
# echo | openssl s_client -connect 127.0.0.1:443 -servername wafdemo.example.com 2>/dev/null | openssl x509 -noout -subject -issuer
subject=O = UUSEC, OU = UUSEC Tech, CN = *
issuer=O = UUSEC, OU = IT Dept, CN = UUSEC Root CA

生产上站点应上传正式证书(管理台"证书管理",支持 Let's Encrypt 自动申请与续期),自签名默认证书仅兜底。

4.7 攻击拦截验证

# SQL 注入特征请求
# curl -s --resolve wafdemo.example.com:8133:127.0.0.1 \
      'http://wafdemo.example.com:8133/?id=1%20union%20select%20*%20from%20users' -D - | head -8
HTTP/1.1 403 Forbidden
Server: uuWAF
Date: Tue, 20 Oct 2026 18:39:57 GMT
Content-Type: text/html; charset=utf-8
...

返回 403,拦截页面(实测节选):

<html lang="zh"><head><meta charset="UTF-8"><title>南墙WAF</title></head>
...
<body><div class="lock"></div><div class="message"><h1>禁止访问</h1>
<p>请求存在威胁,已被南墙拦截</p><p class="rule">规则ID:45</p></div></body></html>
# XSS 特征请求
# curl -s --resolve wafdemo.example.com:8133:127.0.0.1 \
      'http://wafdemo.example.com:8133/?x=<script>alert(1)</script>' -o /dev/null -w '%{http_code}\n'
403
# 拦截统计(仪表盘接口)
# curl -sk "https://127.0.0.1:4443/api/v1/logs/top?date=2026-10-21" -H "Authorization: Bearer $TOKEN"
{"attackers":[{"id":0,"ct":3,"nm":"127.0.0.1"}],
 "sites":[{"id":0,"ct":3,"nm":"wafdemo.example.com"}],
 "types":[{"id":45,"ct":2,"nm":"常规sql注入检测"},{"id":56,"ct":1,"nm":"XSS跨站脚本攻击"}]}

全链路打通:SQL 注入命中内置规则 45(常规sql注入检测),XSS 命中规则 56(XSS跨站脚本攻击),攻击源、站点与规则类型统计均出现在仪表盘。

五、数据持久化说明

部署目录下自动生成的持久化目录(实测清单):

目录容器内路径内容与用途
waf_config//uuwaf/web/conf管理面配置 config.json(含管理台监听地址、DSN、JWT 密钥、api_token、语言、版本),管理台证书 server.crt/server.key,自签根证书 rootCA.crt/rootCA.key,服务日志 waf-service.log
waf_conf//uuwaf/conf数据面 nginx 配置(本篇新增挂载;官方默认不挂载,见第八章)
waf_acme//uuwaf/acmeLet's Encrypt 证书与账号(未申请证书前为空目录)
waf_logs//uuwaf/logs数据面运行日志 error.log 与 uuwaf.pid
waf_data//var/lib/mysqlMySQL 数据目录(站点/规则/日志库,含 ibdata1、ib_logfile* 等)

备份策略建议:日常备份 waf_config/(管理面配置与证书)与 waf_data/(业务数据)两个目录即可完整还原;waf_logs//waf_acme/ 可按需保留。

六、环境变量表

变量作用域默认/示例说明
MYSQL_PASSWORDwafdb、uuwaf(经 DSN)官方安装随机 32 位;本篇演示 q1w2e3r4元数据库 root 密码,首次启动初始化后修改需同步 MySQL 侧
UUWAF_DB_DSNuuwafroot:${MYSQL_PASSWORD}@tcp(127.0.0.1:6612)/uuwaf?charset=utf8mb4&parseTime=true&loc=Local数据库连接串,写在 compose 环境变量中,主机端口须与 wafdb 映射一致

七、配置参数说明(compose 层)

  • network_mode: host:uuwaf 使用宿主网络,数据面以原生性能监听 80/443 等端口;这也是"WAF 需独占端口"的原因。修改站点监听端口见第八章,而不是改 compose 端口映射。
  • wafnet 桥接网络:仅 wafdb 使用(子网 172.31.254.0/24、固定 IP 172.31.254.3、桥名 wafnet)。与宿主已有 172.31.x 网段冲突时需改 subnet;docker compose down 会删除该网络,up 时重建。
  • ulimits:nproc 65535、nofile 102400,WAF 流量场景的文件句柄与进程数配置,无需调整。
  • healthcheck:mysqladmin ping 每 5 秒一次、超时 3 秒、重试 10 次;uuwaf 依赖其 healthy 才启动。
  • --max_connections=512:MySQL 连接上限;low-memory-my.cnf 模板面向 1-2 GB 小内存机器(官方文档提及),启用方式为取消 compose 中对应卷挂载的注释后 up -d 重建。
  • restart: always:两个服务均开机与异常自拉起。

八、配置文件挂载(数据面端口调整实测)

数据面 nginx 配置在容器 /uuwaf/conf/(uuwaf.conf 主配置、listen.conf 监听端口、proxy.conf、ssl.conf、cache.conf、log.conf 等)。官方 compose 未挂载该目录,直接 docker exec 改文件在容器重建后丢失。本篇实测做法(见 4.2 第二处改编):

# 从运行中的实例拷出默认配置(首次启动后)
# docker cp uuwaf:/uuwaf/conf ./waf_conf
# 改 HTTP 监听端口:listen.conf 中
#   listen 80 default_server reuseport;  →  listen 8133 default_server reuseport;
# (HTTPS 443 保持默认,生产 80 空闲时无需本步)
# compose 增加挂载 "- ./waf_conf:/uuwaf/conf" 后
# docker compose up -d
# docker compose ps --format '{{.Name}} {{.Status}}'
uuwaf Up 12 seconds
wafdb Up 15 seconds (healthy)
# 验证数据面已按新端口启动
# ss -ltn | grep ':8133 '
LISTEN 0 511 0.0.0.0:8133 0.0.0.0:*

实测踩坑记录(重要):若只改配置不挂载目录,docker compose down && up 后端口回退默认 80,数据面 nginx 因绑定失败无法启动,且 waf_logs/error.log 出现 bind() to 0.0.0.0:80 failed (98: Address already in use)。将 waf_conf 挂出后再改,配置跨重建持久。

九、等价 docker run(实测)

compose 两个服务可等价拆为两条 docker run(本篇实测:停掉 compose 栈后以该方式拉起,管理台登录、回源 200、SQLi 403 全部复现,再还原 compose):

# 元数据库(等价 wafdb 服务)
# docker run -d --name uusec-waf-726-wafdb --restart always \
      -p 6612:3306 -v ./waf_data:/var/lib/mysql \
      -e MYSQL_ROOT_PASSWORD=q1w2e3r4 mysql:5.7
# 引擎(等价 uuwaf 服务,宿主网络 + 全部数据目录挂载)
# docker run -d --name uusec-waf-726-uuwaf --network host --restart always \
      -v /etc/localtime:/etc/localtime:ro \
      -v ./waf_config:/uuwaf/web/conf -v ./waf_acme:/uuwaf/acme \
      -v ./waf_logs:/uuwaf/logs -v ./waf_conf:/uuwaf/conf \
      uusec/waf:latest
# 实测复现验证:
#   管理台登录(新密码)→ 200 携带 token
#   curl 正常请求 → 200,Server: uuWAF
#   SQLi 请求 → 403 拦截页

⚠️ 注意:UUWAF_DB_DSN 由 config.json 中的 dsn 字段承载(compose 里仅作为初始化写入源),等价启动时若首次初始化,需保证 config.json 的 dsn 与 MySQL 密码一致;日常切换 MySQL 密码可经管理台"系统设置"同步修改(对应 PUT /api/v1/setting)。

十、常用运维命令

10.1 官方管理脚本 manager.sh(菜单 1-7)

# bash /opt/waf/manager.sh
=========================
UUSEC WAF Management
=========================
1. Start
2. Stop
3. Restart
4. Upgrade
5. Repair
6. Uninstall
7. Exit
Please enter the number:

实测结论(重要):

  • 选项 1/2/3 内部即 docker compose down 与 docker compose up -d --remove-orphans;启动前有端口预检,实测要求 80/443/777/4443/4447 全部空闲,任一占用直接中止(实测回显:One or more of ports 80, 443, 777, 4443, 4447 are occupied. Please shutdown the corresponding service or modify its port)。因此像本实验环境这种"80 被其他服务占用、数据面已改 8133"的场景,必须改用 docker compose 命令直管(预检对非默认端口场景过于严格,不影响引擎实际运行);
  • 选项 4 升级:重新下载官方 docker-compose2.yml 覆盖 compose 文件后 pull + up——注意这会覆盖本篇的两处改编(项目名与 waf_conf 挂载),改编部署不要直接用选项 4,改为手动 docker compose pull && docker compose up -d;
  • 选项 6 卸载:down 后删除 uuwaf/wafdb 容器、wafnet 网络、镜像名含 waf 的所有镜像、卷名含 waf 的所有卷,并 rm -rf 安装目录——多组件共用宿主时慎用(可能误删其他 WAF 相关镜像/卷)。

10.2 docker compose 常用命令(本篇改编部署的主线)

# docker compose ps --format '{{.Name}} {{.Status}}'   # 状态(wafdb 应为 healthy)
# docker compose logs -f --tail 100 uuwaf              # 跟踪引擎日志
# docker compose restart uuwaf                          # 重启引擎(元数据库无需动)
# docker compose pull && docker compose up -d           # 升级到最新稳定版(保留改编配置)
# docker compose down                                   # 停栈并删网络(数据目录保留)
# docker compose down -v                                # 停栈并删卷(彻底清库,慎用)

十一、常见问题

Q1:80 或 443 被占用,能否与既有 Web 服务同机共存? 数据面监听端口可改(第八章方法),HTTP 改成任意空闲端口不影响 WAF 功能与回源(本篇实测 8133 全链路正常)。但注意三点:① 管理台升级入口与官方 manager.sh 预检仍按 80/443 口径检查,非默认端口场景用 compose 命令直管;② 生产更推荐按官方口径用一台纯净服务器独占 80/443,避免长期偏离默认;③ 改了 HTTP 端口后,源站回源与 DNS 接入口径不变,仅"HTTP 直连访问 WAF"的入口端口变化。

Q2:通过 API 添加站点后,站点不生效且 error.log 持续刷 failed to update sites: attempt to get length of a userdata value? 实测定位:REST API 提交站点时缺字段(如漏掉 ip_whitelist/url_whitelist/is_cache 等)会让站点落库为 NULL,管理面下发给数据面的 JSON 含 null 值,Lua 侧解析崩溃导致站点配置同步失败。解决:按 4.5 的全字段模板提交。管理台页面添加不受影响(前端总是提交全字段)。修复后 error.log 立即停止刷错,站点秒级生效。

Q3:访问未被任何站点匹配的域名/直接访问 IP 会发生什么? 命中内置 Default 站点(hosts 为 *,源站默认指向官方演示地址 76.76.21.21:443),实测返回 HTTP/1.1 402 Payment Required(上游 Vercel 的拒绝响应)+ X-Vercel-Error 头。生产应把 Default 站点的源站改为自有地址或禁用该站点,避免兜底流量外发到官方演示源站。

Q4:管理台自签名证书告警、站点 HTTPS 证书怎么配? 管理台 4443 使用部署时自动生成的自签名证书(waf_config 下 server.crt/key,可替换为正式证书);站点证书走管理台"证书管理",支持上传或 Let's Encrypt 自动申请续期,未配置证书前 443 端口由内置默认通配证书(CN=*,UUSEC Root CA 签发)兜底。

Q5:忘记了 admin 密码怎么办? 可经元数据库重置(连 6612 端口,用 .env 中的 MYSQL_PASSWORD),或重部署 waf_config 之外的思路:删除 waf_data 后重建会连站点规则一起清空,务必先备份。管理台还支持 TOTP 两步验证,开启后登录需附加 otp 字段。

Q6:社区版站点数量有上限吗? 有。v7.2.5 起社区版上限 16 个站点(此前为 10),更多站点与集群管理、数据脱敏等能力需商业授权(详见 《UUSEC WAF 7.2.6 介绍与选型指南》)。

十二、参考链接