From 8e8ad9f69ee0e9dac2d2e9605d09fb1316ddc312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Fri, 27 Aug 2021 16:47:23 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=9Ewindows=E5=B9=B3=E5=8F=B0dns=E6=A3=80?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.Dns/DnsOverUdpHostedService.cs | 49 ++++------- FastGithub.Dns/SystemDnsUtil.cs | 101 ++++++++++++++-------- 2 files changed, 81 insertions(+), 69 deletions(-) diff --git a/FastGithub.Dns/DnsOverUdpHostedService.cs b/FastGithub.Dns/DnsOverUdpHostedService.cs index 2a1c8c0..2edc2b2 100644 --- a/FastGithub.Dns/DnsOverUdpHostedService.cs +++ b/FastGithub.Dns/DnsOverUdpHostedService.cs @@ -38,13 +38,7 @@ namespace FastGithub.Dns this.options = options; this.logger = logger; - options.OnChange(opt => - { - if (OperatingSystem.IsWindows()) - { - SystemDnsUtil.DnsFlushResolverCache(); - } - }); + options.OnChange(opt => SystemDnsUtil.FlushResolverCache()); } /// @@ -58,31 +52,22 @@ namespace FastGithub.Dns this.dnsOverUdpServer.Bind(IPAddress.Any, dnsPort); this.logger.LogInformation("DNS服务启动成功"); - const int DNS_PORT = 53; - if (dnsPort != DNS_PORT) - { - this.logger.LogWarning($"由于使用了非标准DNS端口{dnsPort},你需要将{nameof(FastGithub)}设置为标准DNS的上游"); - } - else if (OperatingSystem.IsWindows()) + const int STANDARD_DNS_PORT = 53; + if (dnsPort == STANDARD_DNS_PORT) { try { - SystemDnsUtil.DnsSetPrimitive(IPAddress.Loopback); - SystemDnsUtil.DnsFlushResolverCache(); - this.logger.LogInformation($"设置成本机主DNS成功"); + SystemDnsUtil.SetPrimitiveDns(IPAddress.Loopback); + SystemDnsUtil.FlushResolverCache(); } catch (Exception ex) { - this.logger.LogWarning($"设置成本机主DNS为{IPAddress.Loopback}失败:{ex.Message}"); + this.logger.LogWarning(ex.Message); } } - else if (OperatingSystem.IsLinux()) - { - this.logger.LogWarning($"不支持自动设置本机DNS,手工添加{IPAddress.Loopback}做为/etc/resolv.conf的第一条记录"); - } else { - this.logger.LogWarning($"不支持自动设置本机DNS,请手工添加{IPAddress.Loopback}做为连接网络的DNS的第一条记录"); + this.logger.LogWarning($"由于使用了非标准DNS端口{dnsPort},你需要将{nameof(FastGithub)}设置为标准DNS的上游"); } foreach (var item in this.conflictValidators) @@ -113,17 +98,17 @@ namespace FastGithub.Dns this.dnsOverUdpServer.Dispose(); this.logger.LogInformation("DNS服务已停止"); - if (OperatingSystem.IsWindows()) + try { - try - { - SystemDnsUtil.DnsFlushResolverCache(); - SystemDnsUtil.DnsRemovePrimitive(IPAddress.Loopback); - } - catch (Exception ex) - { - this.logger.LogWarning($"恢复DNS记录失败:{ex.Message}"); - } + SystemDnsUtil.RemovePrimitiveDns(IPAddress.Loopback); + } + catch (Exception ex) + { + this.logger.LogWarning(ex.Message); + } + finally + { + SystemDnsUtil.FlushResolverCache(); } return base.StopAsync(cancellationToken); diff --git a/FastGithub.Dns/SystemDnsUtil.cs b/FastGithub.Dns/SystemDnsUtil.cs index 67a5cc2..4fba8e2 100644 --- a/FastGithub.Dns/SystemDnsUtil.cs +++ b/FastGithub.Dns/SystemDnsUtil.cs @@ -12,8 +12,7 @@ namespace FastGithub.Dns { /// /// 系统域名服务工具 - /// - [SupportedOSPlatform("windows")] + /// static class SystemDnsUtil { /// @@ -21,54 +20,53 @@ namespace FastGithub.Dns /// private static readonly IPAddress www_baidu_com = IPAddress.Parse("183.232.231.172"); - [DllImport("iphlpapi")] - private static extern int GetBestInterface(uint dwDestAddr, ref uint pdwBestIfIndex); + /// + /// 刷新DNS缓存 + /// + [SupportedOSPlatform("windows")] + [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)] + private static extern void DnsFlushResolverCache(); /// /// 刷新DNS缓存 /// - [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)] - public static extern void DnsFlushResolverCache(); - - - /// - /// 通过远程地址查找匹配的网络适接口 - /// - /// - /// - private static NetworkInterface GetBestNetworkInterface(IPAddress remoteAddress) + public static void FlushResolverCache() { - var dwBestIfIndex = 0u; - var dwDestAddr = BitConverter.ToUInt32(remoteAddress.GetAddressBytes()); - var errorCode = GetBestInterface(dwDestAddr, ref dwBestIfIndex); - if (errorCode != 0) + if (OperatingSystem.IsWindows()) { - throw new NetworkInformationException(errorCode); + DnsFlushResolverCache(); } - - var @interface = NetworkInterface - .GetAllNetworkInterfaces() - .Where(item => item.GetIPProperties().GetIPv4Properties().Index == dwBestIfIndex) - .FirstOrDefault(); - - return @interface ?? throw new FastGithubException("找不到网络适配器用来设置dns"); } - /// /// 设置主dns /// /// - /// - /// - public static void DnsSetPrimitive(IPAddress primitive) + /// + public static void SetPrimitiveDns(IPAddress primitive) { - var @interface = GetBestNetworkInterface(www_baidu_com); + var @interface = GetOutboundNetworkInterface(); + if (@interface == null) + { + throw new FastGithubException($"找不到匹配的网络适配器来设置主DNS值:{primitive}"); + } + var dnsAddresses = @interface.GetIPProperties().DnsAddresses; if (primitive.Equals(dnsAddresses.FirstOrDefault()) == false) { var nameServers = dnsAddresses.Prepend(primitive); - SetNameServers(@interface, nameServers); + if (OperatingSystem.IsWindows()) + { + SetNameServers(@interface, nameServers); + } + else if (OperatingSystem.IsLinux()) + { + throw new FastGithubException($"不支持自动设置本机DNS,请手工添加{primitive}做为/etc/resolv.conf的第一条记录"); + } + else if (OperatingSystem.IsMacOS()) + { + throw new FastGithubException($"不支持自动设置本机DNS,请手工添加{primitive}做为连接网络的DNS的第一条记录"); + } } } @@ -76,24 +74,53 @@ namespace FastGithub.Dns /// 移除主dns /// /// - /// - /// - public static void DnsRemovePrimitive(IPAddress primitive) + /// + public static void RemovePrimitiveDns(IPAddress primitive) { - var @interface = GetBestNetworkInterface(www_baidu_com); + var @interface = GetOutboundNetworkInterface(); + if (@interface == null) + { + throw new FastGithubException($"找不到匹配的网络适配器来移除主DNS值:{primitive}"); + } + var dnsAddresses = @interface.GetIPProperties().DnsAddresses; if (primitive.Equals(dnsAddresses.FirstOrDefault())) { var nameServers = dnsAddresses.Skip(1); - SetNameServers(@interface, nameServers); + if (OperatingSystem.IsWindows()) + { + SetNameServers(@interface, nameServers); + } } } + + /// + /// 查找出口的网络适器 + /// + /// + private static NetworkInterface? GetOutboundNetworkInterface() + { + var remoteEndPoint = new IPEndPoint(www_baidu_com, 443); + var address = LocalMachine.GetLocalIPAddress(remoteEndPoint); + if (address == null) + { + return default; + } + + return NetworkInterface + .GetAllNetworkInterfaces() + .Where(item => item.GetIPProperties().UnicastAddresses.Any(a => a.Address.Equals(address))) + .FirstOrDefault(); + } + + /// /// 设置网口的dns /// /// /// + [SupportedOSPlatform("windows")] private static void SetNameServers(NetworkInterface @interface, IEnumerable nameServers) { Netsh($@"interface ipv4 delete dns ""{@interface.Name}"" all");