korean-law-mcp安全与限流实践:API密钥隔离、令牌桶配额、对抗性输入防护完整清单
【免费下载链接】korean-law-mcp법제처 국가법령정보를 LLM에서 바로 조회하는 MCP 서버. 법령·판례·조례 검색과 인용 검증 | MCP server for Korean law — search statutes, precedents, and ordinances, and verify citations项目地址: https://gitcode.com/gh_mirrors/ko/korean-law-mcp
korean-law-mcp 是一个让大语言模型直接查询韩国国家法令信息的 MCP 服务器,覆盖法令、判例、条例检索与引用验证。这篇文章把它的完整安全清单拆开讲透:API 密钥隔离、令牌桶限流、对抗性输入防护三大板块,每个机制配对应源码路径,部署自己的 MCP 服务时可直接对照。
为什么一个"查询工具"也需要安全设计
korean-law-mcp 本质是一个转发代理:客户端把自然语言交给 AI,AI 调用 MCP 工具,服务器再向法制处 Open API 发起数十次上游请求。这个结构天然放大三类风险:
- 密钥泄露:法制处 API 密钥(OC)可能出现在日志、错误信息甚至响应链接里
- 配额耗尽:AI 一次对话就可能扇出几十次上游调用,无预算约束会打爆配额
- 恶意输入:一个精心构造的字符串就能让正则引擎卡死十几秒(reDoS 攻击)
项目用约 1,000 个测试用例覆盖了这些路径(见 src/lib/rate-limit.test.ts),下面是完整机制清单。
API 密钥隔离:从请求到日志的三层防护
1. 请求级隔离,密钥不落磁盘。法制处 API 密钥通过 HTTP 请求头传入(apikey、law-oc、x-api-key、Authorization: Bearer均可),服务端用AsyncLocalStorage做请求粒度隔离——每个并发请求各自持有自己的密钥,彻底避免多用户共享服务器时的竞态串号(实现见 src/server/http-server.ts)。
2. 日志与错误信息强制脱敏。上游请求 URL 中的密钥参数(OC、apikey等 6 种命名)在写入日志或错误消息前统一替换为OC=***,由 src/lib/fetch-with-retry.ts 中的maskSensitiveUrl完成。
3. 响应中的密钥剥离。一个真实发生过的漏洞:法制处的判例"详细链接"字段里会原样携带本次请求使用的 OC 密钥,若直接透传,无密钥用户就能偷用服务器自身的配额绕过限流。v4.14.1 起响应渲染前的密钥值全部被剥离(见 CHANGELOG.md)。
💡 经验值:只要你的 MCP 服务器替用户持有第三方密钥,就要假设密钥一定会出现在某个字符串里,在"入站参数 → 出站响应 → 日志"三条路径上各设一道脱敏闸。
令牌桶限流 + 滚动日配额:完整配额体系
为什么不用固定窗口?MCP 的典型用法是"一轮对话连调 5 次工具"。固定窗口(fixed window)下,窗口开头被几个用户打满后,其余用户要干等整个窗口结束。实测中公开服务器上2/3 的无密钥请求直接收到 429。
项目改用令牌桶(src/lib/rate-limit.ts):令牌按分钟匀速连续补充,桶满即止。平均处理率不变,但突发流量只消耗桶里的存量——用完后等几秒就有令牌补上,体感 429 大幅下降。配套细节:
- 429 响应带
Retry-After头和retry in Ns文案,让客户端知道等多久 - 滚动 24 小时日配额(
FALLBACK_DAILY_CAP)兜底:分分钟桶再宽松,一天总量有顶,保护服务器自身密钥在法制处的日配额 - 被拒绝的请求不消耗配额,24 小时整点滚动重置(测试见 src/lib/rate-limit.test.ts)
配额参数一览(均在启动时校验,非法值直接拒绝启动而非静默失效,见 src/server/http-config.ts):
| 环境变量 | 默认值 | 作用 |
|---|---|---|
RATE_LIMIT_RPM | 60 | 每 IP 每分钟请求上限 |
FALLBACK_RATE_LIMIT_RPM | 120 | 服务器兜底密钥的每分钟配额 |
FALLBACK_RATE_LIMIT_BURST | 同 RPM | 令牌桶容量(突发吸收量) |
FALLBACK_DAILY_CAP | 0(关闭) | 滚动 24 小时总量上限 |
MCP_MAX_UPSTREAM_REQUESTS | 48 | 单个请求允许的上游 HTTP 次数(含重试) |
MCP_MAX_BATCH_CALLS | 20 | 单个 JSON-RPC 批处理中的工具调用数 |
TRUST_PROXY | false | 仅接受 1~10 的显式整数,防 X-Forwarded-For 伪造绕限 |
单请求执行预算是另一道关键闸门(src/lib/execution-limits.ts):一个 MCP 请求内部无论扇出多少上游调用(重试、反爬跳转都算),共享同一份预算——默认最多 48 次上游请求、单响应体 8 MiB、累计 24 MiB、工具输出 5 万字符。任何一项越界立即抛出显式ExecutionLimitError,而不是让请求无限膨胀。
对抗性输入防护:拒绝"一个请求卡死整个服务器"
法律文本解析天然重度依赖正则,这正是 reDoS 攻击的温床。v4.14.1 记录了一个真实案例:长空格/逗号/数字重复的输入曾让正则引擎卡住 12~24 秒,且对抗样本最长可达 45.9 秒。修复策略是双管齐下:
- 正则线性化:把指数级回溯的模式改写为线性时间路径
- 入口长度上限:普通参数 2,000 字符、正文参数 50,000 字符,超长直接拒绝——恶意载荷连解析器都到不了
更隐蔽的一类攻击是上游重定向劫持:服务器要跟随法制处反爬页面的跳转时,若攻击者能控制跳转目标,一次响应就能诱导服务器请求任意主机(SSRF)。src/lib/law-antibot.ts 的处理方式是:解析跳转路径后强制校验目标主机与原 URL 一致,不一致立即终止;跳转最多 3 跳,且只探测响应前 4 KB 做判定,避免被恶意大响应拖慢。
网络层还有两道默认即安全的配置:
- HTTP 绑定默认
127.0.0.1。监听非回环地址而未设置MCP_AUTH_TOKEN时,服务器启动即报错(fail-fast),不会带着裸奔的配置跑起来 - 取消信号全链路传播:客户端断开连接后,工具链、上游 fetch、退避等待全部中止——断连不再消耗服务器资源(v4.11.0 起)
部署前安全自查清单 📋
| 检查项 | korean-law-mcp 的做法 |
|---|---|
| 密钥如何传入 | 仅请求头,不落盘、不进命令行参数 |
| 多用户并发 | AsyncLocalStorage请求级隔离 |
| 日志脱敏 | OC=***全量掩码 |
| 响应脱敏 | 出站链接中的密钥值剥离 |
| 限流算法 | 令牌桶 +Retry-After提示 |
| 总量兜底 | 滚动 24 小时日配额 |
| 单请求放大 | 上游调用/字节数执行预算 |
| reDoS | 正则线性化 + 入参长度上限 |
| 重定向劫持 | 同主机校验 + 跳数上限 |
| 监听面 | 默认回环地址,公网需显式令牌 |
| 断连资源 | 取消信号传播到全部下游 |
完整配置项说明可查 docs/API.md 与 docs/ARCHITECTURE.md,限流测试场景值得对照阅读:src/lib/rate-limit.test.ts。
两分钟上手体验
korean-law-mcp 以 npm 包发布,无需自建服务器也能感受上述安全设计——Claude 客户端通过npx korean-law-mcp方式运行最新版,程序化集成时用请求头apikey: 你的密钥携带法制处 API 密钥(法制处 Open API 页面免费申请)。
一句话总结:把"密钥一定会泄露、配额一定会被打爆、输入一定会带恶意"当作默认假设,在入站参数、出站响应、日志三条路径上各设一道闸——这就是 korean-law-mcp 给所有 MCP 服务作者的安全模板。
【免费下载链接】korean-law-mcp법제처 국가법령정보를 LLM에서 바로 조회하는 MCP 서버. 법령·판례·조례 검색과 인용 검증 | MCP server for Korean law — search statutes, precedents, and ordinances, and verify citations项目地址: https://gitcode.com/gh_mirrors/ko/korean-law-mcp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考