FastGithub/FastGithub.Dns/SystemDnsUtil.cs
2021-08-27 16:47:23 +08:00

146 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
/// <summary>
/// 系统域名服务工具
/// </summary>
static class SystemDnsUtil
{
/// <summary>
/// www.baidu.com的ip
/// </summary>
private static readonly IPAddress www_baidu_com = IPAddress.Parse("183.232.231.172");
/// <summary>
/// 刷新DNS缓存
/// </summary>
[SupportedOSPlatform("windows")]
[DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)]
private static extern void DnsFlushResolverCache();
/// <summary>
/// 刷新DNS缓存
/// </summary>
public static void FlushResolverCache()
{
if (OperatingSystem.IsWindows())
{
DnsFlushResolverCache();
}
}
/// <summary>
/// 设置主dns
/// </summary>
/// <param name="primitive"></param>
/// <exception cref="FastGithubException"></exception>
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的第一条记录");
}
}
}
/// <summary>
/// 移除主dns
/// </summary>
/// <param name="primitive"></param>
/// <exception cref="FastGithubException"></exception>
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);
}
}
}
/// <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");
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();
}
}
}
}