跳到正文
Træfɪk

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。
更多信息见此处。

反引号还是引号?

设置规则取值时,请使用反引号 ` 或转义双引号 \"。

不接受单引号 ',因为取值采用 Go 字符串字面量。

使用运算符和括号表达复杂规则

可以使用常见的 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 中列在前面的提供者赢得此次平局。


版权所有 © 头文件软件工作室

文档由 HeadFile Studio 翻译。

Traefik v3.7 中文快照 · 原文版权归 Traefik Labs 及贡献者所有 · MIT 许可证