n8n-workflows 的 FastAPI 服务如何安全加固?配置 ADMIN_TOKEN、限流与 CORS 白名单
【免费下载链接】n8n-workflowsall of the workflows of n8n i could find (also from the site itself)项目地址: https://gitcode.com/GitHub_Trending/n8nworkflo/n8n-workflows
把 n8n-workflows 的 FastAPI 服务(api_server.py)暴露到局域网或公网之前,需要做三件事:设置ADMIN_TOKEN让/api/reindex重建索引接口不再向任何人敞开;确认按 IP 的限流在敏感端点上生效;把 CORS 白名单从“仅本机开发端口”改成你自己的域名。本文按这三项给出配置命令、行为对照和逐条验证方式,全部依据仓库内的 SECURITY.md、api_server.py 和 test_security.sh。
启动服务,确认加固基线
服务依赖在 requirements.txt 中(FastAPI 0.109.0、uvicorn 0.27.0 等,注释标明兼容 Python 3.9–3.12)。README.md 要求 Python 3.9+,而 DEPLOYMENT.md 的直跑一节写的是 Python 3.11+,两处口径不一致,按较高的 3.11+ 准备环境最稳妥。
pip install -r requirements.txt python run.pyrun.py默认绑定127.0.0.1:8000,启动时会检查依赖、创建database/static/workflows目录并建立 SQLite 索引。服务起来后先确认基线可用:
curl http://localhost:8000/health返回{"status": "healthy", "message": "N8N Workflow API is running"}表示服务正常。后续所有验证命令都以本机http://localhost:8000为目标。
配置 ADMIN_TOKEN:/api/reindex 的鉴权开关
/api/reindex是唯一需要认证的写操作入口,其鉴权逻辑在 api_server.py:从环境变量读取ADMIN_TOKEN,请求通过查询参数admin_token携带令牌,两者必须一致。
在启动服务的同一 shell 里设置令牌(替换为你自己生成的随机字符串,SECURITY.md 明确不要把令牌提交进仓库):
export ADMIN_TOKEN="your-secure-random-token" python run.py三种状态与返回的对照关系(均由源码行为决定):
| 条件 | 返回 | detail |
|---|---|---|
未设置ADMIN_TOKEN环境变量 | 503 | Reindexing endpoint is disabled. Set ADMIN_TOKEN environment variable to enable. |
已设置,但admin_token缺失或与令牌不一致 | 401 | Invalid authentication token(服务端同时打印Security: Unauthorized reindex attempt from {client_ip}) |
| 令牌一致 | 200 | {"message": "Reindexing started in background", "requested_by": "<client_ip>"} |
验证 503 与 401 不需要触发真实重建:
# 未设置 ADMIN_TOKEN 启动的服务 curl -i -X POST "http://localhost:8000/api/reindex" # 已设置 ADMIN_TOKEN,但令牌错误或不带令牌 curl -i -X POST "http://localhost:8000/api/reindex?admin_token=wrong-token"副作用提示:令牌正确的调用会在后台执行db.index_all_workflows()全量重建索引,会写入数据库。因此“令牌正确返回 200”这条验证请留到你确实需要重建索引时再做,不要当作日常探活手段。
SECURITY.md的部署清单还要求:使用强ADMIN_TOKEN、定期轮换令牌。
限流:60 次/分钟/IP 在哪些端点生效
限流实现位于 api_server.py:模块级变量MAX_REQUESTS_PER_MINUTE = 60,check_rate_limit()按客户端 IP 维护一个 60 秒滑动窗口内的请求时间戳列表,超限返回 HTTP 429(Rate limit exceeded. Please try again later.)。
check_rate_limit只在四个端点被调用,其余接口(如/api/workflows搜索、/api/stats)不受限流:
GET /api/workflows/{filename}GET /api/workflows/{filename}/downloadGET /api/workflows/{filename}/diagramPOST /api/reindex
验证限流:用test_security.sh中出现过的真实文件名连发 61 次请求,前 60 次应返回 200/404,之后应开始出现 429:
for i in $(seq 1 61); do curl -s -o /dev/null -w "%{http_code}\n" \ "http://localhost:8000/api/workflows/0720_Schedule_Filter_Create_Scheduled.json/download" done两点注意:
- 限流阈值没有环境变量入口。SECURITY.md 的示例里把
MAX_REQUESTS_PER_MINUTE=60写成了可选环境变量,但api_server.py中该值是硬编码常量,代码并未读取同名环境变量——两处口径不一致。想调整阈值,需要修改 api_server.py 第 34 行的常量后重启服务。 - 限流状态是进程内内存。计数存在模块级
defaultdict中,DEPLOYMENT.md 推荐的gunicorn -w 4 ... api_server:app多 worker 部署下,每个进程各自独立计数,单 IP 的实际放行量会高于 60/分钟,文档未给出跨进程共享方案。
收紧 CORS 白名单:把你的域名加进 ALLOWED_ORIGINS
CORS 中间件在 api_server.py 中配置,默认白名单与 SECURITY.md 中“已修复 CORS 配置”一节一致:
ALLOWED_ORIGINS = [ "http://localhost:3000", "http://localhost:8000", "http://localhost:8080", "https://zie619.github.io", "https://n8n-workflows-1-xxgm.onrender.com", ]同时限制:allow_methods仅GET、POST;allow_headers仅Content-Type、Authorization;allow_credentials=True。
如果你的前端部署在别的域名,按SECURITY.md的说明修改api_server.py里的ALLOWED_ORIGINS列表,追加生产域名(例如https://your-domain.com),重启服务生效。
用 OPTIONS 预检请求验证白名单行为:
# 白名单外的 Origin:响应头中不应出现 Access-Control-Allow-Origin curl -i -X OPTIONS "http://localhost:8000/api/workflows" \ -H "Origin: https://not-allowed.example.com" \ -H "Access-Control-Request-Method: GET" | head -n 20 # 白名单内的本地开发 Origin:响应头中应出现 Access-Control-Allow-Origin curl -i -X OPTIONS "http://localhost:8000/api/workflows" \ -H "Origin: http://localhost:3000" \ -H "Access-Control-Request-Method: GET" | head -n 20判断标准就是一条:Origin 不在ALLOWED_ORIGINS中时,FastAPI 的 CORSMiddleware 不会在响应上放行该来源的跨域访问,浏览器侧会因缺少Access-Control-Allow-Origin而拦截请求。
用 test_security.sh 批量验证文件访问端点
除上述三项外,文件访问端点(/api/workflows/{filename}、/download、/diagram)内置了路径穿越防护:validate_filename()会多次解码 URL 编码,拒绝..、反斜杠、绝对路径、通配符等模式,只放行匹配^[a-zA-Z0-9_\-]+\.json$的文件名,并用Path.resolve().relative_to()二次确认文件确实落在workflows/目录内。
test_security.sh 把这套防护做成了可直接运行的检查脚本:它对本地http://localhost:8000发送 10 个路径穿越攻击向量(如../../etc/passwd、..%2F..%2Fapi_server.py),期望每个都返回 400 或 404;再请求一个合法文件名,期望返回 200。脚本只发 GET 请求,不改写任何文件,可以在服务运行时直接执行:
bash test_security.sh输出按行标注 ✅ Blocked / ❌ FAILED TO BLOCK。只要出现一行❌ FAILED TO BLOCK,说明对应向量未被拦截,需要回到validate_filename()检查规则。注意合法文件名(如0720_Schedule_Filter_Create_Scheduled.json)必须已存在于workflows/子目录中,否则最后一步会以 404 报“Valid download failed”。
部署前对照安全清单
SECURITY.md 给出的部署清单,与本文操作直接相关的条目:
- 设置强
ADMIN_TOKEN环境变量(本文已完成,令牌不要提交进仓库); - 按你的实际域名配置 CORS 来源(本文已完成);
- 生产环境使用 HTTPS(HTTP 仅限本地开发);
- 配置防火墙规则限制访问、开启监控告警;
- 定期审查并轮换管理员令牌;
- 若挂在反向代理之后,
SECURITY.md推荐追加X-Frame-Options、X-Content-Type-Options、Strict-Transport-Security等响应头(示例为 nginxadd_header配置)。
完成上述配置后,服务的暴露面是:搜索/统计类接口公开只读,文件访问接口受文件名白名单 + 限流保护,重建索引接口需要ADMIN_TOKEN且受同一限流约束。需要进一步收敛时,SECURITY.md还建议保持 Python 与依赖更新、用 Trivy 等扫描器跟进依赖漏洞(仓库根目录已有 trivy.yaml)。
【免费下载链接】n8n-workflowsall of the workflows of n8n i could find (also from the site itself)项目地址: https://gitcode.com/GitHub_Trending/n8nworkflo/n8n-workflows
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考