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,ipv6ipv6,ipv4(第一个为偏好,第二个为兜底)
    • 命中后会使用该域名专属的 check-mode 与 ip 家族选择,并禁用 speed-ip-parallel 的 v4/v6 竞速与 AAAA-race
    • ipv4 时:对 AAAA 查询直接返回空 AAAA(促使客户端回落使用 A);仅 ipv6 时:对 A 查询返回空 A
    • ipv4,ipv6ipv6,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 并编译。

  1. 拉取 CoreDNS 源码:
1
2
git clone https://github.com/coredns/coredns.git
cd coredns
  1. plugin.cfg 增加一行(放在你希望的执行顺序位置;顺序会影响执行链建议放到cache:cache 前面):
1
speedcheck:github.com/qist/speedcheck
  1. 拉取 speedcheck 模块源码(两种方式任选其一):
  • 方式 A:让 Go 自动拉取(推荐)
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. 重新生成插件注册代码并编译:
1
2
go generate coredns.go
make

交叉编译(Linux arm64):

1
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o coredns-linux-arm64

WSL DNS PATH 配置

本文档用于说明 WSL(Windows Subsystem for Linux)中 /etc/wsl.conf 文件内各配置项的作用及影响。

配置如下:

1
2
3
4
5
[network]
generateResolvConf = false

[interop]
appendWindowsPath = false

一、[network] 网络相关配置

generateResolvConf = false

作用:
禁止 WSL 在启动时自动生成 /etc/resolv.conf 文件。

默认行为(true):

  • WSL 启动时会根据 Windows 当前网络状态自动生成 /etc/resolv.conf
  • 通常使用 Windows 的 DNS(例如 VPN 或公司内网 DNS)

设置为 false 后:

  • 不再自动覆盖 /etc/resolv.conf
  • DNS 完全由用户手动维护
  • 适用于代理、IPTV、Docker、服务器等场景

示例:

1
2
nameserver 1.1.1.1
nameserver 8.8.8.8

二、[interop] Windows 与 Linux 互操作

appendWindowsPath = false

作用:
禁止将 Windows 的 PATH 环境变量追加到 WSL 的 PATH 中。

默认行为(true):

  • Windows 的可执行程序会出现在 WSL 的 PATH 中
  • 可能导致命令冲突(如 curl、git)

设置为 false 后:

  • 仅使用 Linux 自身的 PATH
  • 环境更干净、稳定
  • 适合开发与服务器运行环境

三、配置生效

修改 /etc/wsl.conf 后执行:

1
wsl --shutdown

重新进入 WSL 后配置生效。

本文档介绍如何在 Linux 系统上编译支持 HTTP/3 的 cURL,依赖 quictls OpenSSL、nghttp3 和 ngtcp2。


0. 编译环境准备

在开始之前,需要安装一些基础编译工具和依赖库(以 Ubuntu/Debian 为例):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo apt update
sudo apt install -y \
build-essential \
autoconf \
automake \
libtool \
pkg-config \
cmake \
git \
curl \
wget \
make \
gcc \
g++ \
libssl-dev \
zlib1g-dev

说明:

  • build-essential:包含 gcc、g++、make 等基础编译工具

  • autoconf、automake、libtool:用于生成配置文件和构建工具

  • pkg-config:用于检测依赖库路径

  • libssl-dev:OpenSSL 开发库

  • zlib1g-dev:压缩库,部分库可能依赖

  • git:拉取源码

CentOS/RHEL:

1
2
sudo yum groupinstall "Development Tools" -y
sudo yum install -y autoconf automake libtool pkgconfig cmake git wget openssl-devel zlib-devel

1. 编译 quictls OpenSSL

1
2
3
4
5
6
7
8
9
10
git clone --depth=1 --recursive -b openssl-3.3.0-quic1 https://github.com/quictls/openssl.git
cd openssl
./Configure linux-x86_64 no-shared enable-tls1_3 --prefix=/usr/local/openssl-quic
make -j$(nproc)
make install

export PATH=/usr/local/openssl-quic/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/openssl-quic/lib64:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/usr/local/openssl-quic/lib64/pkgconfig:$PKG_CONFIG_PATH
cd ..

2. 编译 nghttp3

1
2
3
4
5
6
7
8
9
10
# 克隆 nghttp3 仓库
git clone --depth=1 --recursive https://github.com/ngtcp2/nghttp3.git
cd nghttp3

# 自动生成配置文件并编译
autoreconf -i
./configure
make -j$(nproc)
make install
cd ..

3. 编译 ngtcp2

1
2
3
4
5
6
7
8
9
10
# 克隆 ngtcp2 仓库
git clone --depth=1 --recursive https://github.com/ngtcp2/ngtcp2.git
cd ngtcp2

# 自动生成配置文件并编译,仅编译库文件
autoreconf -i
./configure --enable-lib-only
make -j$(nproc)
make install
cd ..

4. 编译 cURL(官方 master 分支)

1
2
3
4
5
6
7
8
9
10
11
12
13
# 克隆 cURL 仓库
git clone --depth=1 --recursive https://github.com/curl/curl.git
cd curl

# 生成构建配置
./buildconf

# 配置并编译 cURL,启用 OpenSSL、nghttp3、ngtcp2 和 HTTP/3
PKG_CONFIG_PATH=/usr/local/openssl-quic/lib64/pkgconfig \
./configure --with-ssl=/usr/local/openssl-quic --with-nghttp3 --with-ngtcp2 --enable-alt-svc --enable-shared
make -j$(nproc)
make install
cd ..

5. 测试 HTTP/3 支持

1
2
3
使用以下命令测试是否成功支持 HTTP/3:
curl -v --http3 https://example.com
如果输出中包含 Using HTTP/3 或类似信息,则表示编译成功,cURL 已支持 HTTP/3 协议。

6. 环境变量持久化(可选)

可以将以下内容添加到 ~/.bashrc, ~/.zshrc 或ld.so.conf.d 目录 中,方便每次登录自动生效:

1
2
3
4
5
6
7
8
export PATH=/usr/local/openssl-quic/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/openssl-quic/lib64:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/usr/local/openssl-quic/lib64/pkgconfig:$PKG_CONFIG_PATH
vim /etc/ld.so.conf.d/openssl.conf
/usr/local/lib
/usr/local/lib64
/usr/local/openssl-quic/lib64
ldconfig #生效

Linux 环境中构建启用 QUIC 与 Open Quantum Safe (OQS) 算法支持的 OpenSSL 3.3.0。


📦 依赖安装


📦 RHEL/CentOS 系列依赖安装

适用于 RHEL, CentOS, RockyLinux, AlmaLinux 等:

1
2
sudo dnf groupinstall -y "Development Tools"
sudo dnf install -y git cmake ninja-build perl-core python3 openssl-devel perl-CPAN

如使用 CentOS 7,建议使用 devtoolset 安装 GCC 9+:

1
2
3
4
sudo yum install -y perl-CPAN
sudo yum install -y centos-release-scl
sudo yum install -y devtoolset-9
scl enable devtoolset-9 bash
1
2
3
# Ubuntu/Debian 系统
sudo apt update
sudo apt install -y git cmake ninja-build build-essential perl python3 cpanminus

🧱 准备工作目录

1
2
export BUILD_PATH=$HOME/build-openssl-oqs
mkdir -p $BUILD_PATH && cd $BUILD_PATH

🔧 步骤一:构建带 QUIC 支持的 OpenSSL

1
2
3
4
5
6
7
8
9
10
perl -MCPAN -e shell
install IPC/Cmd.pm

cd $BUILD_PATH
git clone --depth=1 --recursive -b openssl-3.3.0-quic1 https://github.com/quictls/openssl.git
cd openssl

./config --prefix=/usr/local/quictls
make -j$(nproc)
make -j$(nproc) install

🔒 步骤二:构建并安装 liboqs(量子加密算法)

1
2
3
4
5
6
7
8
9
10
11
cd $BUILD_PATH
git clone --depth=1 --recursive https://github.com/open-quantum-safe/liboqs
mkdir liboqs/build && cd liboqs/build

cmake -G"Ninja" .. \
-DCMAKE_INSTALL_PREFIX=/usr/local/oqs \
-DBUILD_SHARED_LIBS=ON \
-DOPENSSL_ROOT_DIR=/usr/local/quictls

ninja
ninja install

🧩 步骤三:构建并安装 oqs-provider 插件

1
2
3
4
5
6
7
8
9
10
11
cd $BUILD_PATH
git clone --depth=1 --recursive https://github.com/open-quantum-safe/oqs-provider.git
mkdir oqs-provider/build && cd oqs-provider/build

cmake .. \
-DOPENSSL_ROOT_DIR=/usr/local/quictls \
-DCMAKE_INSTALL_PREFIX=/usr/local/oqs-provider \
-DCMAKE_PREFIX_PATH=/usr/local/oqs

make -j$(nproc)
make install

⚙️ 步骤四:配置 OpenSSL 加载 oqs provider

创建配置文件 /etc/ssl/openssl-quic.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect
ssl_conf = ssl_sect

[provider_sect]
default = default_sect
oqs = oqs_sect

[default_sect]
activate = 1

[oqs_sect]
activate = 1
module = /usr/local/quictls/lib64/ossl-modules/oqsprovider.so

[ssl_sect]
system_default = system_default_sect

[system_default_sect]

🧪 验证安装

设置环境变量

1
2
3
export OPENSSL_CONF=/etc/ssl/openssl-quic.cnf
export OPENSSL_MODULES=/usr/local/quictls/lib64/ossl-modules
export LD_LIBRARY_PATH=/usr/local/quictls/lib64:$LD_LIBRARY_PATH

验证 provider 是否加载

1
2
3
OPENSSL_CONF=/etc/ssl/openssl-quic.cnf \
LD_LIBRARY_PATH=/usr/local/quictls/lib64:$LD_LIBRARY_PATH \
/usr/local/quictls/bin/openssl list -providers

输出应包含:

1
2
3
Providers:
default
oqs

查看支持的算法:

1
2
3
OPENSSL_CONF=/etc/ssl/openssl-quic.cnf \
LD_LIBRARY_PATH=/usr/local/quictls/lib64:$LD_LIBRARY_PATH \
/usr/local/quictls/bin/openssl list -public-key-algorithms

🧹 卸载(可选)

1
2
sudo rm -rf /usr/local/quictls /usr/local/oqs /usr/local/oqs-provider
sudo rm /etc/ssl/openssl-quic.cnf

📌 附录:自动配置环境(可选)

将以下内容添加到 .bashrc.zshrc

1
2
3
export OPENSSL_CONF=/etc/ssl/openssl-quic.cnf
export OPENSSL_MODULES=/usr/local/quictls/lib64/ossl-modules
export LD_LIBRARY_PATH=/usr/local/quictls/lib64:$LD_LIBRARY_PATH

本指南适用于开发和测试基于 OpenSSL + OQS 的后量子加密通信(例如 TLS/QUIC)。


🛠️ Systemd 服务配置示例(环境变量)

如果你希望使用带 OQS 的 OpenSSL 与 NGINX 或其他服务集成,需在 systemd unit 文件中配置环境变量:

例如编辑 /etc/systemd/system/nginx.service.d/openssl-oqs.conf

例如编辑 /lib/systemd/system/nginx.service.d/openssl-oqs.conf

1
2
3
4
[Service]
Environment="OPENSSL_CONF=/etc/ssl/openssl-quic.cnf"
Environment="OPENSSL_MODULES=/usr/local/quictls/lib64/ossl-modules"
Environment="LD_LIBRARY_PATH=/usr/local/quictls/lib64:$LD_LIBRARY_PATH"

然后重新加载并重启:

1
2
3
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl restart nginx

🌐 NGINX TLS 配置:支持 OQS KEM Group(ssl_ecdh_curve)

编辑 nginx.conf 或对应 TLS server 配置段:

1
ssl_ecdh_curve X25519MLKEM768:SecP384r1MLKEM1024:SecP256r1MLKEM768:X25519:P-384:P-256;

确保 NGINX 启动环境带有正确的 OpenSSL 路径与配置。

注意:需使用编译时链接 quictls OpenSSL 的 NGINX 版本,或者通过动态链接指定库路径。


Centos7 内核编译及 RPM 包的制作

源码编译安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
yum -y groups install "Development Tools"
yum install ncurses-devel make gcc bc openssl-devel

wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.14.105.tar.gz

tar zxvf linux-4.14.105.tar.gz

cp /boot/config-`uname -r` ./linux-4.14.105/.config

cd linux-4.14.105

make menuconfig #进入后直接保存保存配置
make oldconfig

make kernelversion
make INSTALL_MOD_STRIP=1 all -j32

make INSTALL_MOD_STRIP=1 modules_install
# ls -lh /lib/modules

make INSTALL_MOD_STRIP=1 install
# ls -lh /boot

通过以上命令可以完成内核的编译。

Use the INSTALL_MOD_STRIP option for removing debugging symbols:

1
make INSTALL_MOD_STRIP=1 modules_install

打包 ——RPM

1
yum -y install rpm-build 
1
make rpm-pkg -j32 

编译完成在 ~/rpmbuild/RPMS/x86_64/ 目录下生成 rpm 安装包:

1
2
3
4
ls -lh ~/rpmbuild/RPMS/x86_64/
-rw-r--r-- 1 root root 515M 10月 10 06:28 /root/rpmbuild/RPMS/x86_64/kernel-4.14.105-1.x86_64.rpm
-rw-r--r-- 1 root root 135M 10月 10 06:30 /root/rpmbuild/RPMS/x86_64/kernel-devel-4.14.105-1.x86_64.rpm
-rw-r--r-- 1 root root 1.2M 10月 10 06:28 /root/rpmbuild/RPMS/x86_64/kernel-headers-4.14.105-1.x86_64.rpm

为啥 rpm 包这么大,官方 rpm 包一般五六十兆大小???

主要是编译生成的 ko 文件增大所致,应该包含了 debug 信息和符号表
make INSTALL_MOD_STRIP=1 rpm-pkg

安装

1
rpm -iUv ~/rpmbuild/RPMS/x86_64/kernel-*.rpm
1
yum install ~/rpmbuild/RPMS/x86_64/kernel-*.rpm

内核编译命令

编译内核生成 centos rpm 或 ubuntu deb 包

1
2
3
4
5
make rpm          #生成带源码的RPM包
make rpm-pkg #生成带源码的RPM包,同上
make binrpm-pkg #生成包含内核和驱动的RMP包
make deb-pkg #生成带源码的debian包
make bindeb-pkg #生成包含内核和驱动的debian包

rpm-pkg: 每次编译前会先 clean, 重复编译会很慢

linux 内核 make help:

1
2
3
4
5
6
7
8
9
10
11
12
13
Kernel packaging:
rpm-pkg - Build both source and binary RPM kernel packages
binrpm-pkg - Build only the binary kernel RPM package
deb-pkg - Build both source and binary deb kernel packages
bindeb-pkg - Build only the binary kernel deb package
tar-pkg - Build the kernel as an uncompressed tarball
targz-pkg - Build the kernel as a gzip compressed tarball
tarbz2-pkg - Build the kernel as a bzip2 compressed tarball
tarxz-pkg - Build the kernel as a xz compressed tarball
perf-tar-src-pkg - Build perf-4.14.105.tar source tarball
perf-targz-src-pkg - Build perf-4.14.105.tar.gz source tarball
perf-tarbz2-src-pkg - Build perf-4.14.105.tar.bz2 source tarball
perf-tarxz-src-pkg - Build perf-4.14.105.tar.xz source tarball
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
make clean            #删除编译中间文件,但是保留配置
make mrproper #删除包括配置文件的所有构建文件
make distclean #执行mrproper所做的一切,并删除备份文件

make menuconfig #文本图形方式配置内核
make oldconfig #基于当前的.config文件提示更新内核
make defconfig #生成默认的内核配置
make allmodconfig #所有的可选的选项构建成模块
make allyesconfig #生成全部选择是内核配置
make noconfig #生成全部选择否的内核配置

make all #构建所有目标
make bzImage #构建内核映像
make modules #构建所有驱动
make dir/ #构建指定目录
make dir/file.[s|o|i] #构建指定文件
make dir/file.ko #构建指定驱动

make install #安装内核
make modules_install #安装驱动

make xmldocs #生成xml文档
make pdfdocs #生成pdf文档
maek htmldocs #生成html文档

参考

我需要内核的源代码

我需要创建一个自设的内核

Building Source RPM as non-root under CentOS*

kernel 4.18.18 rpm 制作

Linux kernel 编译指南