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");