给新 RD Web 装上 Duo 二次验证,装完却连不上 Duo——问题出在四个和 Duo 毫无关系的注册表键
新建的 RD Web Access 服务器要接入公司现有的 Duo 双因素认证体系。流程听起来直截了当:在 Duo 管理后台的应用目录里添加一个 “Microsoft RD Web” 类型的应用,拿到它生成的 Client ID、Client Secret、API Hostname 三件套,下载对应的 Duo for Remote Desktop Web Access 安装包,装到服务器上,安装向导里把这三件套填进去,重启,完事。
装完之后,这台服务器却没办法正常和 Duo 的云端服务握手。
症状和 Duo 本身没有直接关系
Duo 的安装本身没有报错——客户端 ID、密钥、API 主机名都填对了,安装向导一路走到 Finish。问题出在这台服务器本身能不能用现代 TLS 协议跟 Duo 的云端 API 建立连接这件更底层的事情上。
这里的关键背景是:Duo for RD Web Access 这类基于 .NET Framework 的组件,走网络请求时使用的加密协议版本,取决于 .NET Framework 自身的一组注册表设置,而不是 Duo 软件自己的配置项。老版本的 .NET Framework 默认倾向于用比较旧的协议协商方式,如果服务器的操作系统层面已经关闭了旧版 TLS(这是当前的安全基线常态),.NET 应用又没有被明确告知”请优先用系统支持的最新协议”,握手就会在两边都没有明显报错的情况下悄悄失败。
修复:四个注册表键,跟 Duo 的界面毫无关系
微软自己给出的标准修复方式,是让 .NET Framework 使用系统当前支持的最强加密套件,而不是它自己内置的旧偏好——这需要同时改 32 位和 64 位两套注册表路径:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
SchUseStrongCrypto 让 .NET Framework 应用停止使用它内置的一批已经过时、不安全的加密套件;SystemDefaultTlsVersions 则让应用不再自己决定用哪个 TLS 版本,转而遵循操作系统层面配置好的协议策略——两者合起来,效果是”让这个基于旧版 .NET Framework 写的程序,用起当前系统认可的现代 TLS”。这四个键分别对应 32 位/64 位注册表视图各一套,缺一套,跑在对应位数下的进程就还是老行为。
改完注册表,需要重启服务器这条改动才会对已经加载的 .NET Framework 运行时生效。重启之后,Duo for RD Web Access 才能正常和云端完成认证握手,RD Web 登录页面开始正确弹出 Duo 的二次验证提示。
Duo 的安装界面里没有一个选项跟这四个注册表键有关——但它们决定了这次安装能不能真正工作
教训
- 一款软件”安装成功”和”能正常工作”之间,可能隔着一层它自己界面里完全看不到的系统级前提——尤其是基于较老运行时(.NET Framework、Java 等)构建的组件,走 TLS 连接时是否遵循系统当前的安全基线,往往是运行时层面的全局设置决定的,而不是这款软件自己的配置项;
SchUseStrongCrypto+SystemDefaultTlsVersions这两组键,是让老版本 .NET Framework 应用”追上”系统当前 TLS 策略的标准动作——任何一个基于 .NET Framework、需要对外发起 HTTPS 请求的老组件在新加固过的服务器上表现异常时,都值得先检查这四个键,而不是急着去重装或者怀疑软件本身有问题;- 32 位和 64 位注册表视图要分别设置——同一个逻辑设置在 Windows 上物理上存在两份(
SOFTWARE\...和SOFTWARE\WOW6432Node\...),只改一套,另一位数的进程行为不会跟着变; - 这类底层运行时设置的改动,几乎都需要重启才生效——.NET Framework 的加密策略是进程/系统启动时读取的,不会对已经在跑的服务生效,动手之前预留好重启窗口。