DPD 在 RadSec 里的等价物是 Status-Server ;开它就有保活/判死能力。 动态发现优先用 SRV 就能跑,NAPTR 是“SRV 的上一层”,需要时再加。 最小可行:本机起个 dnsmasq 写 SRV 记录 → radsecproxy 用 DynamicLookupCommand srv:_radsec._tcp → StatusServer auto。 生产化关键:证书主机名匹配(CN/SAN)、阻塞首包(BlockingStartup)、避免重复 include。
0️⃣ 背景:为什么要把 DPD 和动态发现绑在一起? RADIUS/UDP 天生“无连接”,上游死了就换一个; 而 RADIUS/TLS(RadSec)是长连接 :需要你自己探测对端(DPD)、断开重连,并且当你启用了动态对端发现(DNS NAPTR/SRV)时,上游 peer 可能随时间变化。
所以要做的是:
用 DNS(NAPTR/SRV)发现谁可用;
用 Status-Server 做 DPD,发现谁“死了”;
配合 LB/Fail-over,把请求发给“当前最健康”的那个。
1️⃣ NAPTR / SRV:一句话原理 + 示例 SRV: 直接告诉客户端“某服务在哪个主机名、哪个端口、优先级/权重是多少”。 例如:
1 _radsec._tcp.edu.test → radius-a.edu.test:2083, radius-b.edu.test:2083
NAPTR: 再高一层的“指路牌”。 它先返回“服务类型 + 下一跳域名”,通常把你引导到 SRV 名称,然后再走 SRV。 适合多协议/多传输的选择(如 radius.tls / radius.udp)。
1.1 SRV 最小示例(建议先用它跑通) 1 2 3 4 5 6 7 _radsec._tcp.edu.test. 3600 IN SRV 50 10 2083 radius-a.edu.test. _radsec._tcp.edu.test. 3600 IN SRV 50 20 2083 radius-b.edu.test. radius-a.edu.test. 3600 IN A 192.168.8.228 radius-b.edu.test. 3600 IN A 192.168.8.179
1.2 NAPTR 示例(可选再加) 1 2 edu.test. 3600 IN NAPTR 100 10 "s" "x-eduroam:radius.tls" "" _radsec._tcp.edu.test.
流程: 客户端(这里是 radsecproxy)查 NAPTR edu.test → 得到 _radsec._tcp.edu.test → 再查 SRV → 解析到主机与端口。
2️⃣ 最小可行环境:用 dnsmasq 在本机出 SRV 1 2 3 4 5 6 7 8 9 10 sudo apt-get install -y dnsmasqsudo tee /etc/dnsmasq.d/edu-test.conf >/dev/null <<'EOF' domain=edu.test srv-host=_radsec._tcp.edu.test,radius-a.edu.test,2083,10,50 srv-host=_radsec._tcp.edu.test,radius-b.edu.test,2083,20,50 address=/radius-a.edu.test/192.168.8.228 address=/radius-b.edu.test/192.168.8.179 EOF
1 2 3 4 5 6 sudo tee /etc/dnsmasq.d/01-upstream.conf >/dev/null <<'EOF' no-resolv server=1.1.1.1 server=8.8.8.8 EOF
1 2 3 sudo sed -i 's/^#\?DNSStubListener=.*/DNSStubListener=no/' /etc/systemd/resolved.confsudo systemctl restart systemd-resolved
1 2 3 4 5 6 sudo tee /etc/dnsmasq.d/00-listen.conf >/dev/null <<'EOF' listen-address=127.0.0.1 bind-interfaces EOF sudo systemctl restart dnsmasq
1 2 echo -e "nameserver 127.0.0.1\noptions edns0" | sudo tee /etc/resolv.conf >/dev/null
验证:
1 2 dig +short _radsec._tcp.edu.test SRV dig +short radius-a.edu.test A
3️⃣ radsecproxy:把“动态发现 + DPD”接进去 3.1 目录结构(分片加载一次就行) 1 2 3 4 5 6 7 8 9 10 /usr/local/etc/radsecproxy.conf /usr/local/etc/radsecproxy.d/ 00-logging.conf 10-listen.conf 20-tls.conf 30-clients.conf 40-radius-a.conf 41-radius-b.conf 42-dynamic.conf 50-realms.conf
主配置:
1 include /usr/local/etc/radsecproxy.d/*.conf
3.2 TLS 基础(20-tls.conf) 1 2 3 4 5 tls myradsec { CACertificateFile /etc/radsecproxy/certs/ca.pem CertificateFile /etc/radsecproxy/certs/client.pem CertificateKeyFile /etc/radsecproxy/certs/client.key }
3.3 动态模板(42-dynamic.conf)——关键! 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 server dyn-radsec { type tls tls myradsec DynamicLookupCommand srv:_radsec._tcp StatusServer auto BlockingStartup on secret radsec1234567890 CertificateNameCheck on TCPKeepalive on }
3.4 静态回退(可选) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 server radius-a { type tls host 192.168.8.228 port 2083 secret radsec1234567890 tls myradsec TCPKeepalive on } server radius-b { type tls host 192.168.8.179 port 2083 secret radsec1234567890 tls myradsec TCPKeepalive on }
3.5 realm 选路(50-realms.conf) 1 2 3 4 5 6 realm * { server dyn-radsec server radius-a server radius-b }
4️⃣ 启动 & 验证 1 radsecproxy -f -c /usr/local/etc/radsecproxy.conf -d 4
期望日志关键字:
1 2 3 4 5 dynamicconfigsrv: starting SRV lookup ... using SRV target radius-a.edu.test:2083 ... TLS connection to dynamic:edu.test (...) up sending Status-Server / got status server response Access-Accept/Challenge ... from dynamic:edu.test
发送一个测试请求触发动态解析:
1 2 echo 'User-Name = "[email protected] ", User-Password = "pass"' \| radclient -x 127.0.0.1:1812 auth testing123
4.1 证书名校验的坑(今天真遇到了) 启用 CertificateNameCheck on 后,radsecproxy 会用“要连接的主机名”(SRV 返回的 FQDN)匹配证书 CN/SAN。 如果日志出现:
1 certnamecheck: cn not matching host radius-a.edu.test
说明证书里没有这个 FQDN。三种修法:
A(推荐): 给上游证书加 SAN: DNS:radius-a.edu.test / DNS:radius-b.edu.test。B: 把 SRV 目标换成证书已有的名字,并给它配 A 记录。C(过渡): 先关 CertificateNameCheck on → off,或用 MatchCertificateAttribute CN:/^radius-server-(1|2)$/ 钉死可接受证书。
5️⃣ DPD(Status-Server)到底帮了啥?
空闲心跳: 空闲后发 Code 12(Status-Server),对端回包则认为活着;
判死/重连: 不回包就标记为 down,触发 Fail-over;
动态发现组合: 判死后重查 SRV/NAPTR,连接新的 peer。
在测试日志里出现:
1 replyh: got status server response
代表 DPD 已启用成功。
6️⃣ 今天踩过的坑 & 一键诊断清单
🚫 重复 include → 只保留一行 include /usr/local/etc/radsecproxy.d/*.conf。
🌀 53 端口被占用 → 设置 DNSStubListener=no + 只监听 127.0.0.1。
🔑 动态模板没写 secret → 上游不回包。
⏳ 首包回退 → 开 BlockingStartup on。
❌ 证书主机名不匹配 → 按 4.1 的 A/B/C 修。
验证命令:
1 2 3 dig +short _radsec._tcp.edu.test SRV radsecproxy -f -c /usr/local/etc/radsecproxy.conf -d 4 echo 'User-Name="[email protected] ",User-Password="pass"' | radclient -x 127.0.0.1:1812 auth testing123
7️⃣ 进阶与生产化建议
🎯 只对特定 realm 启用动态:realm /@.*\.edu\.test$/ { server dyn-radsec; ... }
🧩 保留静态回退:SRV 解不出或目标 down 时不致中断。
⚖️ 健康度与权重:SRV 自带优先级/权重,可结合本地统计优化。
📈 可观测性:记录 Status-Server RTT、失败次数、重连次数。
🔐 TLS 与 PKI:证书写全 SAN,保持 CertificateNameCheck on。
🧠 8️⃣ 结语 RadSec 的“难点”不是哪个指令,而是**连接生命周期(DPD)与对端发现(NAPTR/SRV)**的组合。 这篇的最小方案(dnsmasq + SRV + DynamicLookupCommand + StatusServer auto)已经足以落地; 之后再把 NAPTR、证书 SAN、LB 策略慢慢完善,就是一套“能跑、可观测、可维护”的生产配置。
评论区可以贴日志/配置片段,我帮你一起看。