我正在尝试将。net 6应用程序连接到使用自签名服务器证书的SQL Server 2016实例。使用默认连接字符串设置,这会导致错误
A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)
该错误在技术上是正确的,因为证书是自签名的,而不是由受信任的机构颁发的。因为这是一个内部的私有数据库,所以不能让受信任的权威机构对证书进行签名。编辑:我们也没有一个已经在我们的网络中受信任的内部CA。
我知道Encrypt=False
设置,但我们希望对连接进行加密。我也知道TrustServerCertificate=True
设置,但如果攻击者也使用自签名证书,那么这将使我们容易受到中间人攻击。理想情况下,我想自定义证书验证,并允许连接,如果证书拇指指纹匹配我所期望的。
如果这是一个HTTP请求,我可以执行以下操作
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, errors) => {
if (errors == SslPolicyErrors.None) return true;
if (errors == SslPolicyErrors.RemoteCertificateChainErrors)
return cert.Thumbprint == "MyTrustedThumbprint";
return false;
};
var client = new HttpClient(handler);
这个解决方案避免了中间人攻击(因为他们不能复制指纹),它避免了我们的团队必须在我们网络中的每台机器上安装一个自签名证书。
在Microsoft.Data.SqlClient
生态系统中是否存在与ServerCertificateCustomValidationCallback
相似的东西?如果该解决方案还可以与更高级别的数据库访问(如Entity Framework或Dapper)一起工作,则加分。
因为这是一个内部的私有数据库,所以不能让一个受信任的权威机构对证书进行签名。
那不是真的。仍然有两种途径可以获得由可信机构签名的证书:
-
让您的服务器加入以您真正控制的公共域命名的Active Directory域。在这种情况下,您可以从信誉良好的(受信任的)CA供应商处购买证书,该证书将被您的客户端接受。
注意,这并不一定意味着让你的AD域使用与你的面向公众的服务相同的名称(当然,这是不推荐的);只是将其设置为使用可以为公共的域名,并且您可以向可信CA证明您拥有该名称。您通常可以通过以下方式通过此检查:拨打您实际接听的WHOIS注册表中的号码,以及一组DNS TXT和CAA记录,这意味着使用此域的服务器甚至不必从互联网可访问。
还要注意应该是但我知道很多地方没有这样做,或者AD环境早于本指南。如果是这样的话,我明白要求你的组织做出改变是件大事。这让我想到了第二条路……
-
运行您自己的CA,将您的客户端设置为信任CA。这在AD环境中相当直接。如果您在域上正确设置了AD证书服务,那么您的域加入客户端将相信它是理所当然的。
与第一个选项不同,如果您还没有CA并且无法遵循路径1,那么期望组织使此工作以支持与数据库的安全通信是合理的,因为还有其他好处。
如果这两个路径都不可行(即,客户端不是AD的一部分),那么您必须将证书发布到您的客户端,以便将其添加到他们的证书存储中。
值得一提的是,在客户端代码中没有绕过的方法。唯一的选择是未加密的与数据库服务器的通信。这是因为本地sql客户端绝对会而不是让你自定义证书检查,Sql Server从第一天起就被。net支持,使用本地客户端,因此没有人认为有必要做一个替代品,无论是商业的,开源的,还是介于两者之间的东西。