配置 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-Agent、X-Forwarded-For)。大小写不敏感。Match Type 为 any 时留空(该类型不检查请求头)。 |
| Match Type | 匹配方式,见下表。 |
| Match Value | 匹配值。exists / absent / any 类型不需要填。 |
| Action | allow(放行)或 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-Agent 以 python-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-Agent,condition_type = regex,condition_value = (?i)scrapy|crawl|spider,action = deny,scope = Global。 - 限制特定 IP 段:
condition_key = X-Forwarded-For,condition_type = prefix,condition_value = 192.168.,action = deny,scope = Global。 - 仅允许带自定义头的请求:
condition_key = X-Api-Token,condition_type = absent,action = deny,scope = 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 开头」
condition_key = User-Agent
condition_type = regex
condition_value = aaaa|bbb|^aaa
action = deny
scope = Globalaaaa段:值包含aaaa(不锚定 = contains)。bbb段:值包含bbb。^aaa段:值以aaa开头(首锚只作用于本分支)。- 三段用
|连接,命中任一段即 deny。等价于把三条规则合并成一条。
示例 2:大小写不敏感的多关键词包含
condition_key = User-Agent
condition_type = regex
condition_value = (?i:scrapy|crawl|spider|bot)
action = deny
scope = Global(?i:...) 让括号内的 alternation 忽略大小写,Scrapy、CRAWL、Spider 均命中。注意 (?i) 只作用于其包裹的范围,不影响规则其他部分。
示例 3:多值精确匹配(exact 做不到的场景)
exact 一次只能比对一个值。要「值恰好是 v1、v2、v3 之一」,用首尾双锚的 alternation:
condition_key = X-Api-Version
condition_type = regex
condition_value = ^(v1|v2|v3)$
action = allow
scope = Global^...$ 把搜索语义收紧为完全匹配,v1、v2、v3 命中,v10、xv1x 不命中。
示例 4:用 contains 语义拦截含特定子串的值
引擎没有独立的 contains 类型,但不锚定的 regex 本身就是 contains。要拦截「X-Debug 头值里含 debug 子串」:
condition_key = X-Debug
condition_type = regex
condition_value = debug
action = deny
scope = Global例如 debug 命中 debug、my-debug-flag,但不命中 DEBUG(值匹配区分大小写);需忽略大小写时写 (?i)debug。
示例 5:白名单模式(default_action 兜底拒绝 + 单条放行)
需求:某密钥组只允许带受信前缀的客户端,其余一律拒绝。利用「无规则命中时回退到 default_action」:
- 把该密钥组(或全局)的
acl_default_action设为Deny。 - 加一条放行规则:
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 必须更小:
# 规则 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 = Globalhealth-probe/bot-1 先被规则 A 命中 → allow,不再评估规则 B;普通爬虫 UA 不命中 A,落到 B → deny。若把两条 order 写反,探针会被 B 先拦下。
示例 7:「不含某子串」需反向编排
正则引擎不支持 lookahead,「值不含 internal 才放行」写不成单条正则。反向编排:
acl_default_action = Deny。- 加一条「含
internal则放行」:condition_type = regex,condition_value = internal,action = allow。
语义即「含 internal → allow;否则(含其他值或不含)→ 无命中 → default deny」。若需求是「含 internal 反而拒绝、其余放行」,则把 default_action 设 Allow,再加一条 internal → deny 即可。
评估逻辑
- 合并当前请求作用域内的所有规则:全局规则 + 当前 key 的 per-key 规则 + 当前 group 的 per-group 规则。
- 按
sort_order升序排列(数值越小越先评估;相同 order 时按作用域 全局 → 密钥组 → 访问密钥 顺序),跳过enabled = false的规则。 - 逐条评估:按
condition_type匹配(any不读请求头,条件恒真;其余类型取请求头condition_key的值匹配)。 - 首条命中的规则决定结果:
deny→ 立即返回 403;allow→ 放行到下一层。 - 无规则命中时,按 default_action 链回退:per-key
acl_default_action→ per-groupacl_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 封禁。
