非windows平台dns检测

This commit is contained in:
陈国伟 2021-08-27 16:47:23 +08:00
parent 58ebb1e756
commit 8e8ad9f69e
2 changed files with 81 additions and 69 deletions

View File

@ -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());
}
/// <summary>
@ -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);

View File

@ -12,8 +12,7 @@ namespace FastGithub.Dns
{
/// <summary>
/// 系统域名服务工具
/// </summary>
[SupportedOSPlatform("windows")]
/// </summary>
static class SystemDnsUtil
{
/// <summary>
@ -21,54 +20,53 @@ namespace FastGithub.Dns
/// </summary>
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);
/// <summary>
/// 刷新DNS缓存
/// </summary>
[SupportedOSPlatform("windows")]
[DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)]
private static extern void DnsFlushResolverCache();
/// <summary>
/// 刷新DNS缓存
/// </summary>
[DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)]
public static extern void DnsFlushResolverCache();
/// <summary>
/// 通过远程地址查找匹配的网络适接口
/// </summary>
/// <param name="remoteAddress"></param>
/// <returns></returns>
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");
}
/// <summary>
/// 设置主dns
/// </summary>
/// <param name="primitive"></param>
/// <exception cref="NetworkInformationException"></exception>
/// <exception cref="NotSupportedException"></exception>
public static void DnsSetPrimitive(IPAddress primitive)
/// <exception cref="FastGithubException"></exception>
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
/// </summary>
/// <param name="primitive"></param>
/// <exception cref="NetworkInformationException"></exception>
/// <exception cref="NotSupportedException"></exception>
public static void DnsRemovePrimitive(IPAddress primitive)
/// <exception cref="FastGithubException"></exception>
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);
}
}
}
/// <summary>
/// 查找出口的网络适器
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 设置网口的dns
/// </summary>
/// <param name="interface"></param>
/// <param name="nameServers"></param>
[SupportedOSPlatform("windows")]
private static void SetNameServers(NetworkInterface @interface, IEnumerable<IPAddress> nameServers)
{
Netsh($@"interface ipv4 delete dns ""{@interface.Name}"" all");