跳到正文

配置 Header ACL 访问规则

访问规则基于 HTTP 请求头做准入控制,支持三级作用域:全局、密钥组、访问密钥。规则按 sort_order 升序匹配,首条命中决定 allow/deny。

入口:控制台 → 访问密钥Access Rules 页签。

注意:访问规则同时作用于推理路由/v1/chat/completions/v1/messages 等)和模型列表路由/v1/models/v1beta/models)。拒绝某个 header 模式时,模型列表查询也会被拦截。运维人员需知晓此行为,避免误配导致客户端无法获取模型列表。

规则字段

字段说明
Rule Name规则唯一标识,全局唯一。建议使用作用域前缀(如 key:mykey__rule1)避免命名冲突。创建后不可修改。
Order排序权重,升序匹配,数值越小越先评估。相同 order 的规则按作用域 全局 → 密钥组 → 访问密钥 的顺序评估(即同 order 下全局规则先命中);因此密钥级或组级规则若要覆盖同 order 的全局规则,必须填更小的 order。
Header Name要匹配的 HTTP 请求头名称(如 User-AgentX-Forwarded-For)。大小写不敏感。Match Type 为 any留空(该类型不检查请求头)。
Match Type匹配方式,见下表。
Match Value匹配值。exists / absent / any 类型不需要填。
Actionallow(放行)或 deny(拒绝,返回 403)。
Scope作用域:Global(所有请求)、Key(指定一个或多个 access key)、Group(指定一个或多个密钥组)。Key 和 Group 互斥,支持多选。
Scope value当 Scope 为 Key 或 Group 时,从下拉列表选择目标密钥或密钥组。
Enabled规则开关。禁用后规则在加载时被忽略,不影响其他规则。

表里是控制台 UI 标签,下文配置示例用底层字段名,对应:Header Name = condition_key、Match Type = condition_type、Match Value = condition_value、Action = action、Scope = scope、Order = sort_order

匹配类型

类型说明示例
exact请求头值与 Match Value 完全相等User-Agent = BadBot/1.0
prefix请求头值以 Match Value 开头User-Agentpython-requests/ 开头
regex请求头值匹配正则表达式User-Agent 匹配 `(?i)curl
exists请求头存在(不论值)检查 X-Custom-Header 是否存在
absent请求头不存在检查 Authorization 是否缺失
any条件恒真,不检查任何请求头,规则仅靠作用域(Scope)生效对某 key「全部放行/拒绝」:Match Type=any + Scope=Key,Header Name 留空

字段语义、匹配类型、regex 匹配语义和评估逻辑的完整参考见 Header ACL 规则字段

常见用法

  • 屏蔽爬虫condition_key = User-Agentcondition_type = regexcondition_value = (?i)scrapy|crawl|spideraction = denyscope = Global
  • 限制特定 IP 段condition_key = X-Forwarded-Forcondition_type = prefixcondition_value = 192.168.action = denyscope = Global
  • 仅允许带自定义头的请求condition_key = X-Api-Tokencondition_type = absentaction = denyscope = Global(缺少该头则拒绝)。
  • 针对特定密钥组限制:设置 scope = Group,选择目标密钥组,规则仅对该组内的密钥生效。
  • 对某个密钥全部放行/拒绝(无需 header 条件):设置 Match Type = any、Scope = Key 并选择目标密钥,Header Name 留空——该规则对此密钥的所有请求生效。若要用它覆盖一条全局 deny,把它的 order 设得比全局规则更小(同 order 时全局优先)。

复杂配置示例

下面几个例子演示如何用 regex 与 first-match-wins 语义组合出更复杂的策略。字段以 key = value 行内给出,order 越小越先评估。

示例 1:一条规则表达「包含 A 或 包含 B 或以 C 开头」

text
condition_key   = User-Agent
condition_type  = regex
condition_value = aaaa|bbb|^aaa
action          = deny
scope           = Global
  • aaaa 段:值包含 aaaa(不锚定 = contains)。
  • bbb 段:值包含 bbb
  • ^aaa 段:值 aaa 开头(首锚只作用于本分支)。
  • 三段用 | 连接,命中任一段即 deny。等价于把三条规则合并成一条。

示例 2:大小写不敏感的多关键词包含

text
condition_key   = User-Agent
condition_type  = regex
condition_value = (?i:scrapy|crawl|spider|bot)
action          = deny
scope           = Global

(?i:...) 让括号内的 alternation 忽略大小写,ScrapyCRAWLSpider 均命中。注意 (?i) 只作用于其包裹的范围,不影响规则其他部分。

示例 3:多值精确匹配(exact 做不到的场景)

exact 一次只能比对一个值。要「值恰好是 v1、v2、v3 之一」,用首尾双锚的 alternation:

text
condition_key   = X-Api-Version
condition_type  = regex
condition_value = ^(v1|v2|v3)$
action          = allow
scope           = Global

^...$ 把搜索语义收紧为完全匹配,v1v2v3 命中,v10xv1x 不命中。

示例 4:用 contains 语义拦截含特定子串的值

引擎没有独立的 contains 类型,但不锚定的 regex 本身就是 contains。要拦截「X-Debug 头值里含 debug 子串」:

text
condition_key   = X-Debug
condition_type  = regex
condition_value = debug
action          = deny
scope           = Global

例如 debug 命中 debugmy-debug-flag,但不命中 DEBUG(值匹配区分大小写);需忽略大小写时写 (?i)debug

示例 5:白名单模式(default_action 兜底拒绝 + 单条放行)

需求:某密钥组只允许带受信前缀的客户端,其余一律拒绝。利用「无规则命中时回退到 default_action」:

  1. 把该密钥组(或全局)的 acl_default_action 设为 Deny
  2. 加一条放行规则:
text
order           = 10
condition_key   = User-Agent
condition_type  = regex
condition_value = ^trusted-
action          = allow
scope           = Group   (选中目标密钥组)

效果:值以 trusted- 开头 → 命中规则 → allow;其余值无规则命中 → 落到 default_action → deny。无需写一条「拒绝一切」的兜底规则。

示例 6:放行优先于拒绝(order 编排)

需求:拒绝常见爬虫,但放行自家的监控探针(其 UA 也含 bot 字样,会被爬虫规则误伤)。靠 first-match-wins,放行规则的 order 必须更小

text
# 规则 A:先放行自家探针
order           = 10
condition_key   = User-Agent
condition_type  = regex
condition_value = ^health-probe/
action          = allow
scope           = Global

# 规则 B:再拒绝爬虫
order           = 20
condition_key   = User-Agent
condition_type  = regex
condition_value = (?i:scrapy|crawl|spider|bot)
action          = deny
scope           = Global

health-probe/bot-1 先被规则 A 命中 → allow,不再评估规则 B;普通爬虫 UA 不命中 A,落到 B → deny。若把两条 order 写反,探针会被 B 先拦下。

示例 7:「不含某子串」需反向编排

正则引擎不支持 lookahead,「值不含 internal 才放行」写不成单条正则。反向编排:

  1. acl_default_action = Deny
  2. 加一条「含 internal 则放行」:condition_type = regexcondition_value = internalaction = allow

语义即「含 internal → allow;否则(含其他值或不含)→ 无命中 → default deny」。若需求是「含 internal 反而拒绝、其余放行」,则把 default_action 设 Allow,再加一条 internaldeny 即可。

评估逻辑

  1. 合并当前请求作用域内的所有规则:全局规则 + 当前 key 的 per-key 规则 + 当前 group 的 per-group 规则。
  2. sort_order 升序排列(数值越小越先评估;相同 order 时按作用域 全局 → 密钥组 → 访问密钥 顺序),跳过 enabled = false 的规则。
  3. 逐条评估:按 condition_type 匹配(any 不读请求头,条件恒真;其余类型取请求头 condition_key 的值匹配)。
  4. 首条命中的规则决定结果:deny → 立即返回 403;allow → 放行到下一层。
  5. 无规则命中时,按 default_action 链回退:per-key acl_default_action → per-group acl_default_action → 全局 Allow

常见问题

Q:客户端报 403 但密钥是对的? 检查是否被 Header ACL 拦下。规则同时作用于推理路由和模型列表路由,可能客户端先调 /v1/models 时就被拦截。临时禁用相关规则或调高 order 排查。

Q:规则改了不生效? 规则编译失败时被跳过并记录告警。检查 condition_value 是否符合语法(不支持 lookahead / 回溯引用)。condition_value 长度上限 1024 字节。

Q:怎么让某密钥组的规则覆盖全局规则? 同 order 下全局先命中。要覆盖必须填更小的 order,或把全局规则改成 enabled = false

Q:怎么对某个密钥「无条件放行/拒绝」? Match Type=any + Scope=Key + Header Name 留空。规则仅靠作用域生效,对此密钥的所有请求生效。

Q:模型列表调用也被拦截? 是的,规则同时作用于 /v1/models/v1beta/models。运维需知晓此行为,避免误配导致客户端无法获取模型列表。

下一步Header ACL 规则字段 看 regex 语义和表达力边界的完整参考;访问密钥与密钥组字段 看密钥组维度;审计与安全配置 看限流与 IP 封禁。