Unity使用IP连接WSS服务报TlsException证书不受信任错误
问题复现
连接代码如下:
// _url = wss://test.com:8080/action // _url = wss//127.0.0.1:8080/action await _connectCws.ConnectAsync(_uri, _connectCts.Token).ConfigureAwait(false);
连接现象:
- 使用域名地址
wss://test.com:8080/action可正常建立连接 - 使用IP格式的wss地址连接时抛出TLS握手异常:
TlsException: Handshake failed - error code: UNITYTLS_INTERNAL_ERROR, verify result: UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED
环境与前置信息:
test.com已通过hosts映射指向127.0.0.1本地地址- 服务端基于Node.js ws库搭建,使用OpenSSL生成的自签名证书
- 需求为优先使用IP地址连接,支持访问其他设备部署的服务端
- 已尝试添加如下全局配置跳过证书校验,未生效:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
根因分析
- 全局证书回调不生效的原因:Unity 2018+版本默认使用原生UnityTLS栈处理TLS握手,不会响应
ServicePointManager挂载的全局证书校验回调,该回调仅在Player Settings中手动切换为Mono托管TLS实现时才会触发,默认配置下完全不执行。 - 域名可连、IP不可连的原因:生成自签名证书时,主题备用名称(SAN)字段仅配置了
test.com域名,未添加对应的IP地址条目。TLS握手阶段会校验访问目标地址(域名/IP)是否存在于证书的信任列表中,使用IP访问时因匹配不到对应条目,直接触发不信任标记,即使域名和IP指向同一服务也不会通过校验。
解决方案
方案1:生成带IP条目的自签名证书(推荐,安全性更高)
生成自签名证书时将需要支持的IP地址加入SAN列表,从根源解决地址匹配问题:
- 新建OpenSSL配置文件
cert.conf,按需修改alt_names段的域名、IP列表:
[req] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn req_extensions = req_ext [dn] CN = test.com [req_ext] subjectAltName = @alt_names [alt_names] DNS.1 = test.com IP.1 = 127.0.0.1 IP.2 = 192.168.31.120 # 替换为实际需要支持的局域网设备IP,可追加多条
- 执行命令生成有效期10年的证书与私钥:
openssl req -x509 -newkey rsa:2048 -sha256 -nodes -keyout server.key -out server.crt -days 3650 -config cert.conf
- 用新生成的
server.crt、server.key替换Node.js服务端原有的证书文件,重启服务后即可正常用IP连接。
方案2:挂载WebSocket实例级别的证书校验回调(适合内网测试,不建议生产环境使用)
直接给ClientWebSocket实例配置证书回调,该回调在UnityTLS栈下可正常触发,跳过所有证书校验逻辑:
// 调用ConnectAsync前添加如下配置 _connectCws.Options.RemoteCertificateValidationCallback = (_, _, _, _) => true; await _connectCws.ConnectAsync(_uri, _connectCts.Token).ConfigureAwait(false);
生产环境使用时不要直接返回true,可将自签名证书的公钥/指纹内置到客户端,在回调中对比服务端返回的证书信息,避免中间人攻击风险。
避坑提示
- 代码中注释的IP地址存在笔误:
wss//127.0.0.1:8080/action缺少冒号,正确格式为wss://127.0.0.1:8080/action - 若发布目标为WebGL平台,所有跳过证书校验的逻辑均不生效,WebGL下WebSocket走浏览器原生TLS栈,必须使用浏览器信任的证书,或由终端用户手动信任自签名证书
- 若需要兼容旧版Unity,可在Player Settings -> Other Settings中将TLS版本配置调整为支持TLS1.2及以上
内容的提问来源于stack exchange,提问作者twowind
相关产品推荐
相关产品推荐

