上周有个用户能登录 VPN,却还是落在一个什么都解析不了的网络上。客户端显示已连接,网关日志写着 Access-Accept,身份团队则说账号没问题。登录本身成功了;它背后的授权没有成功。当 VPN 登录失败时,我会沿着请求实际经过的路径走一遍——客户端、网关、RADIUS 服务器、身份提供方——并在第一个与下一跳答复不一致的环节停下。

客户端从不直接说 RADIUS

无论笔记本上的应用显示什么,它的第一跳都是 VPN 协议:IKEv2、OpenVPN、WireGuard 或基于 TLS 的客户端。RADIUS 并不出现在那次交换中。客户端用证书、用户名和密码,或隧道建立过程中携带的 EAP 方法向网关完成认证。

读日志时这一点很重要,因为用户看到的通用认证错误,是网关在与别的东西通信之后才产生的。如果客户端根本没有到达网关,就不存在可调试的 RADIUS 请求,花在 RADIUS 服务器上的一小时也就白费了。在动后端之前,先确认隧道到底有没有建立。

网关就是 RADIUS 客户端

一旦隧道建立走到必须校验凭据的环节,网关就变成了网络接入服务器。它构造一个 Access-Request:User-Name、密码或 EAP 载荷、NAS-IP-Address 或 NAS-Identifier,以及方法需要时的 Message-Authenticator。请求默认发往 UDP 1812,计费发往 1813。较旧的部署仍在使用 1645 和 1646,所以一条只为其中一对端口写的防火墙规则能解释许多无声失败。

双方共享一个密钥,它不是用户凭据。它给这次交换签名,每个应答都要用它来验证。两端密钥配得不一样,服务器不会回一句密钥错误——它会丢弃请求,或者应答验签失败,于是网关报告超时。密钥错误和服务器死掉,从网关看完全一样,所以我会先用客户端工具测试这一跳,再去怪目录。

这个协议很小、很老——RFC 2865 定义了认证交换——但它携带的属性正是大多数 VPN 策略的立足点。

# ask the RADIUS server directly, from the gateway host
radtest alice 'test-password' 127.0.0.1 0 testing123

# watch the exchange the gateway actually sends
tcpdump -ni any -c 20 'udp port 1812'

RADIUS 服务器可能只是身份提供方的前台

人们说 RADIUS 和身份提供方,好像它们是同一个盒子。很多时候并不是。RADIUS 服务器收到 Access-Request,然后在应答之前去问别的东西——通过 LDAP 或 Kerberos 查 Active Directory、本地用户文件,或外部服务。带 LDAP 或 krb5 模块的 FreeRADIUS、Windows NPS 和 Cisco ISE 都处在这个位置。

这个区别决定了你该往哪里看。密码被拒是身份提供方的答复,由 RADIUS 转达。超时通常出在 RADIUS 到目录这一段:绑定账号过期、目录不可达,或请求被路由到错误的后端。如果用户名带域名后缀,服务器可能据此路由,同一个账号以 CORP\alice 和 [email protected] 发送就可能落到不同地方。在 Windows NPS 上,Security 日志在允许时记 6272、拒绝时记 6273,这能说明判断到底是不是 NPS 做的。

在产生失败的环节读失败

一条连不上的消息覆盖四种不同的失败。在改动任何东西之前,先把症状对应到产生它的环节。

What you seeWhere it comes fromFirst check
Gateway timeout, no replyShared secret mismatch, UDP 1812 blocked, unknown NAS, wrong server addresstcpdump at the gateway; radtest from the gateway host
Immediate rejectCredentials, account state, domain suffix, RADIUS policyNPS 6273 or the FreeRADIUS auth log; test the account directly
Repeated challenge or MFA loopAccess-Challenge state not returned, or a token that expired mid-flowClient prompt timing and the State attribute in debug output
Accept, then no accessAuthorization attributes unmapped, wrong pool, route or ACL policyGateway policy and the attributes in the Access-Accept

最后一行才是把人送去错误团队的那一行。Access-Accept 只意味着凭据被接受;并不意味着网关把用户放进了正确的地址池,也不意味着推送了路由。只有网关策略读取组属性时,它们才重要。我见过正确的登录落进访客池,因为 RADIUS 侧的组映射配的是另一个属性,而网关检查的是这个属性。

从头到尾追踪一次登录

选一个测试账号和一个网关,然后在四个点上观察同一次尝试。在 RADIUS 侧启动调试——freeradius -X 会打印请求和它接触到的每个模块——跟踪网关的认证日志,并对 UDP 交换运行 tcpdump。连接一次,按顺序读这四条轨迹。

你想看到的是吻合:网关询问的是你预期的用户,RADIUS 服务器选的是你预期的后端,那个后端返回了判断,应答里的属性与网关应用的策略一致。轨迹第一次对不上的地方,就是你的故障分界。如果应答里没有组属性,问题在 RADIUS 侧,不在 VPN 配置里;如果属性在而网关忽略它,问题就是网关策略。

在那里时顺便记一条安全事项。共享密钥保护这次交换,但它并不加密大多数属性。如果网关和 RADIUS 服务器位于不同网段,就把这一跳放到 TLS 上的 RADIUS 或私有路径上。加密的用户隧道并不能说明后端链路如何。

关闭工单之前,确认四件事。网关能真正连到 RADIUS 服务器配置的那个端口。共享密钥在两端一致。RADIUS 服务器能解析网关发送的确切用户名形式。接受应答带有网关策略需要的属性。这四条都成立时,仍然失败的登录就是网关策略问题,而不是认证问题。

相关文章