Rules & Priority
概述¶
说明
- 路由器名称中不允许使用字符 @
- 如果 HTTP 路由器和 TCP 路由器监听同一个入口点,将优先应用 TCP 路由器。如果 TCP 路由器没有找到匹配路由,则由 HTTP 路由器接手。
规则¶
规则是一组配置了取值的匹配器,用于判断特定连接是否满足指定条件。规则成立时,路由器激活、调用中间件,然后将请求转发到服务。
下表列出所有可用的匹配器:
| 规则 | 说明 |
|---|---|
HostSNI(`domain`) |
检查连接的服务器名称指示是否等于 domain。支持通配符子域名匹配(如 *.example.com)。更多信息见此处。 |
HostSNIRegexp(`regexp`) |
检查连接的服务器名称指示是否匹配 regexp。使用 Go 风格的语法。 更多信息见此处。 |
ClientIP(`ip`) |
检查连接的客户端 IP 是否对应 ip。接受 IPv4、IPv6 和 CIDR 格式。更多信息见此处。 |
ALPN(`protocol`) |
检查连接的 ALPN 协议是否等于 protocol。更多信息见此处。 |
使用运算符和括号表达复杂规则¶
可以使用常见的 AND(&&)和 OR(||)逻辑运算符,并遵循通常的优先级规则,
也可以使用括号。
可以使用 NOT(!)运算符对匹配器取反。
以下规则匹配满足下列条件的连接:
- 服务器名称指示为
example.com,或者 - 服务器名称指示为
example.org,并且 ALPN 协议不是h2
HostSNI(`example.com`) || (HostSNI(`example.org`) && !ALPN(`h2`))
HostSNI 和 HostSNIRegexp¶
HostSNI 和 HostSNIRegexp 匹配器可以匹配发往指定域名的连接。
这些匹配器不支持非 ASCII 字符;要匹配此类域名,请使用 punycode 编码的值(rfc 3492)。
HostSNI 与 TLS
需要注意,服务器名称指示是 TLS 协议的一项扩展。
因此,只有 TLS 路由器能通过此规则指定域名。
不过,对于非 TLS 路由器,HostSNI 有一个特殊用法:
如果希望非 TLS 路由器匹配所有(非 TLS)请求,
应使用特定语法 HostSNI(`*`)。
通配符子域名匹配
HostSNI 匹配器支持单层通配符前缀(*.example.com),用于匹配 example.com 的任意直接子域名。
应优先于 HostSNIRegexp 使用它,因为它支持附加 TLS 选项,并且效率更高。
通配符恰好匹配一个子域标签:*.example.com 可以匹配 foo.example.com,但不能匹配 foo.bar.example.com 或 example.com 本身。
这仅适用于 v3 规则语法(默认语法)。
示例¶
匹配所有连接:
HostSNI(`*`)HostSNIRegexp(`^.*$`)匹配发送到 example.com 的 TCP 连接:
HostSNI(`example.com`)
匹配向 example.com 的任意直接子域名(如 foo.example.com)建立的 TCP 连接:
HostSNI(`*.example.com`)
使用正则表达式匹配向 example.com 的任意子域名(包括嵌套子域名)建立的 TCP 连接:
HostSNIRegexp(`^.+\.example\.com$`)
ClientIP(客户端 IP)¶
ClientIP 匹配器可以匹配由指定 IP 客户端建立的连接。
示例¶
匹配由指定 IP 建立的连接:
ClientIP(`10.76.105.11`)ClientIP(`::1`)匹配来自指定子网的连接:
ClientIP(`192.168.1.0/24`)ClientIP(`fe80::/10`)ALPN(应用层协议协商)¶
ALPN 匹配器可以匹配使用指定协议的连接。
如果允许用户自定义的路由器截获
Traefik 先前发起的 ACME TLS 质询响应,就会产生安全问题。
因此,ALPN 匹配器不允许匹配 ACME-TLS/1
协议;尝试这样做时 Traefik 会返回错误。
示例¶
匹配使用 ALPN 协议 h2 的连接:
ALPN(`h2`)
优先级计算¶
默认优先级的计算方式
tcp:
routers:
Router-1:
rule: "ClientIP(`192.168.0.12`)"
entryPoints:
- "web"
service: service-1
priority: 2
Router-2:
rule: "ClientIP(`192.168.0.0/24`)"
entryPoints:
- "web"
priority: 1
service: service-2[tcp.routers]
[tcp.routers.Router-1]
rule = "ClientIP(`192.168.0.12`)"
entryPoints = ["web"]
service = "service-1"
priority = 2
[tcp.routers.Router-2]
rule = "ClientIP(`192.168.0.0/24`)"
entryPoints = ["web"]
priority = 1
service = "service-2" labels:
- 'traefik.tcp.routers.Router-1.rule=ClientIP(`192.168.0.12`)'
- "traefik.tcp.routers.Router-1.entryPoints=web"
- "traefik.tcp.routers.Router-1.service=service-1"
- "traefik.tcp.routers.Router-1.priority=2"
- 'traefik.tcp.routers.Router-2.rule=ClientIP(`192.168.0.0/24`)'
- "traefik.tcp.routers.Router-2.entryPoints=web"
- "traefik.tcp.routers.Router-2.service=service-2"
- "traefik.tcp.routers.Router-2.priority=1" {
//...
"Tags": [
"traefik.tcp.routers.Router-1.rule=ClientIP(`192.168.0.12`)",
"traefik.tcp.routers.Router-1.entryPoints=web",
"traefik.tcp.routers.Router-1.service=service-1",
"traefik.tcp.routers.Router-1.priority=2",
"traefik.tcp.routers.Router-2.rule=ClientIP(`192.168.0.0/24`)",
"traefik.tcp.routers.Router-2.entryPoints=web",
"traefik.tcp.routers.Router-2.service=service-2",
"traefik.tcp.routers.Router-2.priority=1"
]
}在上例中,优先级经过配置后,Router-1 将处理来自 192.168.0.12 的请求。
为避免路径重叠,路由默认按规则长度降序排列。
优先级直接等于规则长度,因此最长规则具有最高优先级。
优先级值为 0 时会被忽略:priority: 0 表示使用默认的规则长度排序。
支持负优先级值。
Traefik 为内部路由器保留了一个优先级范围,用户自定义路由器的最大优先级值为:
- 32 位平台为
(MaxInt32 - 1000), - 64 位平台为
(MaxInt64 - 1000)。
提供者优先顺序
来自不同提供者的两条路由具有相同数值优先级时,
Traefik 使用安装配置选项 providers.precedence 决定哪条路由优先。
在 precedence 中列在前面的提供者赢得此次平局。