From 49ac53e8af58d9a412120fbc694ffcb3f6d6f2ec Mon Sep 17 00:00:00 2001 From: Shreyas Zare Date: Sat, 21 Dec 2024 15:49:16 +0530 Subject: [PATCH] DnsWebService: fixed but in admin web service ssl cert reloading. Updated SelfSignedCertCheck() to include subject alternative name entry for configured unicast local addresses for the web service. Updated config code to add support for new options. --- DnsServerCore/DnsWebService.cs | 133 ++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 53 deletions(-) diff --git a/DnsServerCore/DnsWebService.cs b/DnsServerCore/DnsWebService.cs index ec918020..798d19ab 100644 --- a/DnsServerCore/DnsWebService.cs +++ b/DnsServerCore/DnsWebService.cs @@ -84,6 +84,7 @@ namespace DnsServerCore WebApplication _webService; X509Certificate2Collection _webServiceCertificateCollection; + SslServerAuthenticationOptions _webServiceSslServerAuthenticationOptions; DnsServer _dnsServer; DhcpServer _dhcpServer; @@ -357,65 +358,20 @@ namespace DnsServerCore //https if (!safeMode && _webServiceEnableTls && (_webServiceCertificateCollection is not null)) { - X509Certificate2 serverCertificate = null; - - foreach (X509Certificate2 certificate in _webServiceCertificateCollection) - { - if (certificate.HasPrivateKey) - { - serverCertificate = certificate; - break; - } - } - - if (serverCertificate is null) - throw new DnsWebServiceException("Web Service TLS certificate file must contain a certificate with private key."); - - bool isSupportedHttp2 = _webServiceEnableHttp3; - if (!isSupportedHttp2) - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.Win32NT: - isSupportedHttp2 = Environment.OSVersion.Version.Major >= 10; //http/2 supported on Windows Server 2016/Windows 10 or later - break; - - case PlatformID.Unix: - isSupportedHttp2 = true; //http/2 supported on Linux with OpenSSL 1.0.2 or later (for example, Ubuntu 16.04 or later) - break; - } - } - - List applicationProtocols = new List(); - - if (_webServiceEnableHttp3) - applicationProtocols.Add(new SslApplicationProtocol("h3")); - - if (isSupportedHttp2) - applicationProtocols.Add(new SslApplicationProtocol("h2")); - - applicationProtocols.Add(new SslApplicationProtocol("http/1.1")); - - SslServerAuthenticationOptions webServiceSslServerAuthenticationOptions = new SslServerAuthenticationOptions - { - ApplicationProtocols = applicationProtocols, - ServerCertificateContext = SslStreamCertificateContext.Create(serverCertificate, _webServiceCertificateCollection, false) - }; - foreach (IPAddress webServiceLocalAddress in webServiceLocalAddresses) { serverOptions.Listen(webServiceLocalAddress, webServiceTlsPort, delegate (ListenOptions listenOptions) { if (_webServiceEnableHttp3) listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3; - else if (isSupportedHttp2) + else if (IsHttp2Supported()) listenOptions.Protocols = HttpProtocols.Http1AndHttp2; else listenOptions.Protocols = HttpProtocols.Http1; listenOptions.UseHttps(delegate (SslStream stream, SslClientHelloInfo clientHelloInfo, object state, CancellationToken cancellationToken) { - return ValueTask.FromResult(webServiceSslServerAuthenticationOptions); + return ValueTask.FromResult(_webServiceSslServerAuthenticationOptions); }, null); }); } @@ -487,6 +443,24 @@ namespace DnsServerCore } } + private bool IsHttp2Supported() + { + if (_webServiceEnableHttp3) + return true; + + switch (Environment.OSVersion.Platform) + { + case PlatformID.Win32NT: + return Environment.OSVersion.Version.Major >= 10; //http/2 supported on Windows Server 2016/Windows 10 or later + + case PlatformID.Unix: + return true; //http/2 supported on Linux with OpenSSL 1.0.2 or later (for example, Ubuntu 16.04 or later) + + default: + return false; + } + } + private void ConfigureWebServiceRoutes() { _webService.UseExceptionHandler(WebServiceExceptionHandler); @@ -881,6 +855,22 @@ namespace DnsServerCore _webServiceCertificateCollection = certificateCollection; _webServiceTlsCertificateLastModifiedOn = fileInfo.LastWriteTimeUtc; + List applicationProtocols = new List(); + + if (_webServiceEnableHttp3) + applicationProtocols.Add(new SslApplicationProtocol("h3")); + + if (IsHttp2Supported()) + applicationProtocols.Add(new SslApplicationProtocol("h2")); + + applicationProtocols.Add(new SslApplicationProtocol("http/1.1")); + + _webServiceSslServerAuthenticationOptions = new SslServerAuthenticationOptions + { + ApplicationProtocols = applicationProtocols, + ServerCertificateContext = SslStreamCertificateContext.Create(serverCertificate, _webServiceCertificateCollection, false) + }; + _log.Write("Web Service TLS certificate was loaded: " + tlsCertificatePath); } @@ -925,6 +915,22 @@ namespace DnsServerCore { RSA rsa = RSA.Create(2048); CertificateRequest req = new CertificateRequest("cn=" + _dnsServer.ServerDomain, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + + SubjectAlternativeNameBuilder san = new SubjectAlternativeNameBuilder(); + bool sanAdded = false; + + foreach (IPAddress localAddress in _webServiceLocalAddresses) + { + if (localAddress.Equals(IPAddress.IPv6Any) || localAddress.Equals(IPAddress.Any)) + continue; + + san.AddIpAddress(localAddress); + sanAdded = true; + } + + if (sanAdded) + req.CertificateExtensions.Add(san.Build()); + X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(5)); File.WriteAllBytes(selfSignedCertificateFilePath, cert.Export(X509ContentType.Pkcs12, null as string)); @@ -1266,7 +1272,7 @@ namespace DnsServerCore int version = bR.ReadByte(); - if ((version >= 28) && (version <= 39)) + if ((version >= 28) && (version <= 40)) { ReadConfigFrom(bR, version); } @@ -1277,6 +1283,7 @@ namespace DnsServerCore //new default settings DnsClientConnection.IPv4SourceAddresses = null; DnsClientConnection.IPv6SourceAddresses = null; + _dnsServer.MaxConcurrentResolutionsPerCore = 100; _appsApi.EnableAutomaticUpdate = true; _webServiceEnableHttp3 = _webServiceEnableTls && IsQuicSupported(); _dnsServer.EnableDnsOverHttp3 = _dnsServer.EnableDnsOverHttps && IsQuicSupported(); @@ -1284,6 +1291,8 @@ namespace DnsServerCore _dnsServer.DnsOverHttpRealIpHeader = "X-Real-IP"; _dnsServer.ResponsiblePersonInternal = null; _dnsServer.AuthZoneManager.UseSoaSerialDateScheme = false; + _dnsServer.AuthZoneManager.MinSoaRefresh = 300; + _dnsServer.AuthZoneManager.MinSoaRetry = 300; _dnsServer.ZoneTransferAllowedNetworks = null; _dnsServer.NotifyAllowedNetworks = null; _dnsServer.EDnsClientSubnet = false; @@ -1439,16 +1448,26 @@ namespace DnsServerCore } if (version >= 33) - { _dnsServer.AuthZoneManager.UseSoaSerialDateScheme = bR.ReadBoolean(); - _dnsServer.ZoneTransferAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR); + else + _dnsServer.AuthZoneManager.UseSoaSerialDateScheme = false; + + if (version >= 40) + { + _dnsServer.AuthZoneManager.MinSoaRefresh = bR.ReadUInt32(); + _dnsServer.AuthZoneManager.MinSoaRetry = bR.ReadUInt32(); } else { - _dnsServer.AuthZoneManager.UseSoaSerialDateScheme = false; - _dnsServer.ZoneTransferAllowedNetworks = null; + _dnsServer.AuthZoneManager.MinSoaRefresh = 300; + _dnsServer.AuthZoneManager.MinSoaRetry = 300; } + if (version >= 33) + _dnsServer.ZoneTransferAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR); + else + _dnsServer.ZoneTransferAllowedNetworks = null; + if (version >= 34) _dnsServer.NotifyAllowedNetworks = AuthZoneInfo.ReadNetworkAddressesFrom(bR); else @@ -1525,6 +1544,11 @@ namespace DnsServerCore _dnsServer.ListenBacklog = 100; } + if (version >= 40) + _dnsServer.MaxConcurrentResolutionsPerCore = bR.ReadUInt16(); + else + _dnsServer.MaxConcurrentResolutionsPerCore = 100; + //optional protocols if (version >= 32) { @@ -2504,7 +2528,7 @@ namespace DnsServerCore private void WriteConfigTo(BinaryWriter bW) { bW.Write(Encoding.ASCII.GetBytes("DS")); //format - bW.Write((byte)39); //version + bW.Write((byte)40); //version //web service { @@ -2559,6 +2583,8 @@ namespace DnsServerCore bW.WriteShortString(_dnsServer.ResponsiblePersonInternal.Address); bW.Write(_dnsServer.AuthZoneManager.UseSoaSerialDateScheme); + bW.Write(_dnsServer.AuthZoneManager.MinSoaRefresh); + bW.Write(_dnsServer.AuthZoneManager.MinSoaRetry); AuthZoneInfo.WriteNetworkAddressesTo(_dnsServer.ZoneTransferAllowedNetworks, bW); AuthZoneInfo.WriteNetworkAddressesTo(_dnsServer.NotifyAllowedNetworks, bW); @@ -2607,6 +2633,7 @@ namespace DnsServerCore bW.Write(_dnsServer.QuicIdleTimeout); bW.Write(_dnsServer.QuicMaxInboundStreams); bW.Write(_dnsServer.ListenBacklog); + bW.Write(_dnsServer.MaxConcurrentResolutionsPerCore); //optional protocols bW.Write(_dnsServer.EnableDnsOverUdpProxy);