VPN 登录如何到达 RADIUS 和你的身份提供方
追踪一次 VPN 登录,从客户端到网关的 RADIUS 请求、其背后的身份提供方,以及接受之后所应用的策略。
上周有个用户能登录 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 see | Where it comes from | First check |
|---|---|---|
| Gateway timeout, no reply | Shared secret mismatch, UDP 1812 blocked, unknown NAS, wrong server address | tcpdump at the gateway; radtest from the gateway host |
| Immediate reject | Credentials, account state, domain suffix, RADIUS policy | NPS 6273 or the FreeRADIUS auth log; test the account directly |
| Repeated challenge or MFA loop | Access-Challenge state not returned, or a token that expired mid-flow | Client prompt timing and the State attribute in debug output |
| Accept, then no access | Authorization attributes unmapped, wrong pool, route or ACL policy | Gateway policy and the attributes in the Access-Accept |
最后一行才是把人送去错误团队的那一行。Access-Accept 只意味着凭据被接受;并不意味着网关把用户放进了正确的地址池,也不意味着推送了路由。只有网关策略读取组属性时,它们才重要。我见过正确的登录落进访客池,因为 RADIUS 侧的组映射配的是另一个属性,而网关检查的是这个属性。
从头到尾追踪一次登录
选一个测试账号和一个网关,然后在四个点上观察同一次尝试。在 RADIUS 侧启动调试——freeradius -X 会打印请求和它接触到的每个模块——跟踪网关的认证日志,并对 UDP 交换运行 tcpdump。连接一次,按顺序读这四条轨迹。
你想看到的是吻合:网关询问的是你预期的用户,RADIUS 服务器选的是你预期的后端,那个后端返回了判断,应答里的属性与网关应用的策略一致。轨迹第一次对不上的地方,就是你的故障分界。如果应答里没有组属性,问题在 RADIUS 侧,不在 VPN 配置里;如果属性在而网关忽略它,问题就是网关策略。
在那里时顺便记一条安全事项。共享密钥保护这次交换,但它并不加密大多数属性。如果网关和 RADIUS 服务器位于不同网段,就把这一跳放到 TLS 上的 RADIUS 或私有路径上。加密的用户隧道并不能说明后端链路如何。
关闭工单之前,确认四件事。网关能真正连到 RADIUS 服务器配置的那个端口。共享密钥在两端一致。RADIUS 服务器能解析网关发送的确切用户名形式。接受应答带有网关策略需要的属性。这四条都成立时,仍然失败的登录就是网关策略问题,而不是认证问题。