C# 如何在不同网络上创建和使用基于DNS的自签名证书

C# 如何在不同网络上创建和使用基于DNS的自签名证书,c#,ssl,x509certificate,C#,Ssl,X509certificate,我有以下代码来创建自签名证书: SubjectAlternativeNameBuilder subjectAlternativeNameBuilder = new SubjectAlternativeNameBuilder(); subjectAlternativeNameBuilder.AddDnsName("TestSRV01); X500DistinguishedName x500DistinguishedName = new X500DistinguishedName($"CN=Self

我有以下代码来创建自签名证书:

SubjectAlternativeNameBuilder subjectAlternativeNameBuilder = new SubjectAlternativeNameBuilder();
subjectAlternativeNameBuilder.AddDnsName("TestSRV01);
X500DistinguishedName x500DistinguishedName = new X500DistinguishedName($"CN=Self-Signed-Test");
using (RSA rsa = RSA.Create(2048))
{
    var certificateRequest = new CertificateRequest(x500DistinguishedName, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
    certificateRequest.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature, false));        
    certificateRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("2.5.29.32.0"), new Oid("1.3.6.1.5.5.7.3.1") }, false));
    certificateRequest.CertificateExtensions.Add(subjectAlternativeNameBuilder.Build());
    var certificate = certificateRequest.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow.AddDays(-1)), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
    return new X509Certificate2(certificate.Export( X509ContentType.Cert, pw), pw, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
}
我只添加服务器的DNS名称,以避免绑定到当前IP地址(测试机器在不同的网络中移动)

事实证明,当我从客户端连接时,我需要使用IP地址(DNS解析在测试站点上不可靠)

不幸的是,SSL连接失败,并显示以下消息:

(主机名192.168.0.***未验证: 证书:sha256/UUOTTTQTCB2WU************************ DN:CN=

我不能将证书绑定到此地址,但我也不能将域名用作连接参数


我可以围绕这个问题创建一个可用的证书吗?或者我应该在计算机启动时修改证书值,并将当前IP地址添加到is
SubjectAlternativeName
列表中吗?

根据评论,处理这种情况的最佳方法似乎是在客户端提供自定义证书验证,以分钟为单位d Patrick Mevzek评论中的警告

自定义证书验证涉及编写自己的代码来验证证书中的某些方面
ServerCertificateCustomValidationCallback
属性,您可以使用自己的回调设置该属性

证书首先由.NET计算,然后此验证的结果作为枚举与证书一起传递给回调。您有几个选项可用于更正验证错误。有关提示,请参阅示例。在回调中,您可以检查提示中的subject alt name,并确保其为“TestSRV01”


方法只能用于检索主题备选名称列表中的第一个DNS名称,因此,如果要检查的主机名不是第一个,则必须与.NET进行斗争以获取所需信息。

根据注释,处理此情况的最佳方法似乎是提供自定义证书验证考虑到Patrick Mevzek评论中的注意事项,在客户中进行调整

自定义证书验证涉及编写自己的代码来验证证书中的某些方面
ServerCertificateCustomValidationCallback
属性,您可以使用自己的回调设置该属性

证书首先由.NET计算,然后此验证的结果作为枚举与证书一起传递给回调。您有几个选项可用于更正验证错误。有关提示,请参阅示例。在回调中,您可以检查提示中的subject alt name,并确保其为“TestSRV01”


方法只能用于检索主题备选名称列表中的第一个DNS名称,因此,如果要检查的主机名不是第一个,则您必须与.NET进行斗争以获取所需的信息。

如果在网络上使用DCHP,则您的代码将更不可靠,因为IP地址通常会随时间变化DCHP.IP地址使用IP路由,如果掩码配置不正确,您将找不到主机。为什么您认为DNS不可靠?@jdweng DNS现场解析往往会失败(DHCP在服务器上而不是路由器上运行),所以我尝试使用当前的IP地址。有没有比更新证书更好的解决方案?DCHP应该在服务器上运行。通常与网络密码服务器相同。它可能由于超时而失败。证书应该在代理服务器上,IP只设置一次。@jdweng这是一种特殊情况,证书是在测试机器上,它有很多IP更改。因此我必须找出如何绕过IP并建立连接。@JamesKPolk URL不包含任何主机名,它们现在由IP地址组成。这是主要问题,因为服务器证书不包含这些地址。如果在网络y上使用DCHP我们的代码将更加不可靠,因为IP地址通常随DCHP更改。IP地址使用IP路由,如果掩码配置不正确,您将无法找到主机。为什么您认为DNS不可靠?@jdweng DNS现场解析往往会失败(DHCP在服务器上而不是路由器上运行),所以我尝试使用当前的IP地址。有没有比更新证书更好的解决方案?DCHP应该在服务器上运行。通常与网络密码服务器相同。它可能由于超时而失败。证书应该在代理服务器上,IP只设置一次。@jdweng这是一种特殊情况,证书是在测试机器上,它有很多IP更改。因此我必须找出如何绕过IP并建立连接。@JamesKPolk URL不包含任何主机名,它们现在由IP地址组成。这是主要问题,因为服务器证书不包含这些地址。这意味着什么?如果我根据自定义主机名检查从回调返回
true
,SSL连接已建立?或者这是否意味着未建立SSL连接,但忽略错误并建立常规连接?如果返回true,则SSL连接已建立,如果返回false,则未建立。没有“常规”连接,使用https url,要么全是,要么什么都不是,要么连接成功,您有ssl,要么连接不成功,您什么都没有。我想我同意这个解决方案,因为我可以检查主机名是否是客户端存储的。不幸的是,我使用了自定义的
HttpMessageHandler
及其
ServerCertificateCustomValidationCallback
从未被点击,因此我使用全局
System.Net.ServicePointManager.ServerCertificateValidationCallback
。奇怪的是,
cert
参数总是空的,我只得到