using FastGithub.Configuration;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace FastGithub.Dns
{
///
/// 系统域名服务工具
///
static class SystemDnsUtil
{
///
/// www.baidu.com的ip
///
private static readonly IPAddress www_baidu_com = IPAddress.Parse("183.232.231.172");
///
/// 刷新DNS缓存
///
[SupportedOSPlatform("windows")]
[DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)]
private static extern void DnsFlushResolverCache();
///
/// 刷新DNS缓存
///
public static void FlushResolverCache()
{
if (OperatingSystem.IsWindows())
{
DnsFlushResolverCache();
}
}
///
/// 设置主dns
///
///
///
public static void SetPrimitiveDns(IPAddress primitive)
{
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);
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的第一条记录");
}
}
}
///
/// 移除主dns
///
///
///
public static void RemovePrimitiveDns(IPAddress primitive)
{
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);
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");
foreach (var address in nameServers)
{
Netsh($@"interface ipv4 add dns ""{@interface.Name}"" {address} validate=no");
}
static void Netsh(string arguments)
{
var netsh = new ProcessStartInfo
{
FileName = "netsh.exe",
Arguments = arguments,
CreateNoWindow = true,
UseShellExecute = false,
WindowStyle = ProcessWindowStyle.Hidden
};
Process.Start(netsh)?.WaitForExit();
}
}
}
}