CoreDNS 测速插件 speedcheck
Name
coredns 上游可用性探测插件返回最快IP
speedcheck - 对上游返回的多个 IP 做探测并返回最快的一个 IP。
Description
speedcheck 会对上游返回的多个 A/AAAA 记录做连通性/速度探测,然后把应答收敛为“最快的一个 IP”。
当 speed-check-mode 包含 ping 时,排序依据使用 ping 延迟;否则使用第一个成功探测项的耗时。
Syntax
1 2 3 4 5 6 7 8 9 10 11
| speedcheck { speed-check-mode ping,tcp:80,tcp:443 speed-timeout-mode 3s speed-check-parallel off speed-cache-ttl 30s speed-ip-mode ipv4,ipv6 speed-ip-parallel off speed-host-override www.google.com|tcp:443,http:443|ipv4,ipv6 check_http_send "HEAD / HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n" check_http_expect_alive http_2xx http_3xx http_4xx }
|
speed-check-mode:探测模式(none / ping / tcp:<port> / http:<port>)
- 如果包含
ping:先做一次 ping;如果 ping 成功则该 IP 成功(会继续尝试 tcp/http,但 tcp/http 全失败时仍会按 ping 成功处理);如果 ping 不通,则继续按配置顺序尝试 tcp/http,其中任意一个成功即短路;如果 ping 与所有 tcp/http 都失败则该 IP 失败
- 如果仅配置
ping(没有任何 tcp/http):就只做 ping 探测
- 如果不包含
ping:直接按配置顺序尝试 tcp/http,其中任意一个成功即短路
speed-timeout-mode:探测超时时间,默认 2s
speed-check-parallel:是否并发执行同一 IP 的 tcp/http 探测(on / off),默认 off;开启后会在任意一个 tcp/http 成功时短路返回
speed-cache-ttl:缓存探测结果的时间(按域名与查询类型缓存),默认 0(关闭)
speed-ip-mode:IP 家族优先级(ipv4,ipv6 / ipv6,ipv4 / ipv4 / ipv6 / 不配置默认 ipv6,ipv4)
speed-ip-parallel:是否并发竞速 v4/v6(on / off),默认 off;开启后忽略 speed-ip-mode 的家族优先级,返回最先探测成功的 IP;当查询类型为 AAAA 且 v4 获胜时会返回空 AAAA(促使客户端回落使用 A)
- 回落:当所有 IP 的探测都失败时,如果同时存在 IPv4/IPv6,则优先回落返回 IPv4
speed-host-override:按域名覆盖探测与 IP 家族选择(可配置多条,后写覆盖前写)
- 推荐语法(避免
<check-mode> 里包含逗号导致拆分歧义):
speed-host-override <host>|<check-mode>|<ip-mode>
- 示例:
speed-host-override www.google.com|tcp:443,http:443|ipv4,ipv6
- 兼容语法(不推荐用于多探测项):
speed-host-override <host>,<check-mode>,<ip-mode> 或 speed-host-override <host> <check-mode> <ip-mode>
- 示例:
speed-host-override rrs04.hw.gmcc.net,tcp:8088,ipv4
<check-mode>:语法与 speed-check-mode 相同(none/ping/tcp:<port>/http:<port>,可用逗号组合)
<ip-mode>:
- 仅单一 IP 家族:
ipv4 / ipv6(也支持 v4 / v6)
- 允许 v4+v6 并按顺序偏好:
ipv4,ipv6 或 ipv6,ipv4(第一个为偏好,第二个为兜底)
- 命中后会使用该域名专属的 check-mode 与 ip 家族选择,并禁用
speed-ip-parallel 的 v4/v6 竞速与 AAAA-race
- 仅
ipv4 时:对 AAAA 查询直接返回空 AAAA(促使客户端回落使用 A);仅 ipv6 时:对 A 查询返回空 A
ipv4,ipv6 或 ipv6,ipv4 时:会先按偏好家族探测;偏好家族探测成功则返回空(促使客户端用另一查询类型拿到偏好家族结果);偏好失败但兜底成功则允许回落到兜底家族
check_http_send:自定义 HTTP/1.x 探测报文;其中 {host} / {HOST} 会替换为当前 DNS 查询域名;默认 GET / HTTP/1.0\r\n\r\n
check_http_expect_alive:HTTP 探测可接受的状态码分类(http_2xx/http_3xx/http_4xx/http_5xx/http_all)
Examples
最小示例(server 可启动):
1 2 3 4 5 6 7 8 9 10 11
| . { speedcheck { speed-check-mode ping,tcp:80,tcp:443 speed-timeout-mode 3s speed-cache-ttl 30s speed-ip-mode ipv6,ipv4 check_http_send "HEAD / HTTP/1.1\r\nHost: {host}\r\nConnection: close\r\n\r\n" check_http_expect_alive http_2xx http_3xx http_4xx } whoami }
|
HTTP 探测(http:443 会并发尝试 HTTPS/1.x 与 HTTP/3,取更快的一个):
1 2 3 4 5 6 7 8
| . { speedcheck { speed-check-mode ping,http:80,http:443 speed-timeout-mode 2s check_http_expect_alive http_2xx http_3xx } whoami }
|
Build
下面以远程仓库方式把 speedcheck 模块集成进 CoreDNS 并编译。
- 拉取 CoreDNS 源码:
1 2
| git clone https://github.com/coredns/coredns.git cd coredns
|
- 在
plugin.cfg 增加一行(放在你希望的执行顺序位置;顺序会影响执行链建议放到cache:cache 前面):
1
| speedcheck:github.com/qist/speedcheck
|
- 拉取 speedcheck 模块源码(两种方式任选其一):
1 2 3
| go get github.com/qist/speedcheck@latest 更新到最新代码 go get -u github.com/qist/speedcheck@latest
|
- 方式 B:手动 clone(用于固定版本或离线环境)
1 2
| cd coredns git clone https://github.com/qist/speedcheck.git plugin/speedcheck
|
- 重新生成插件注册代码并编译:
1 2
| go generate coredns.go make
|
交叉编译(Linux arm64):
1
| CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o coredns-linux-arm64
|