SystemDnsUtil.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. using FastGithub.Configuration;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.NetworkInformation;
  8. using System.Runtime.InteropServices;
  9. using System.Runtime.Versioning;
  10. namespace FastGithub.Dns
  11. {
  12. /// <summary>
  13. /// 系统域名服务工具
  14. /// </summary>
  15. static class SystemDnsUtil
  16. {
  17. /// <summary>
  18. /// 刷新DNS缓存
  19. /// </summary>
  20. [SupportedOSPlatform("windows")]
  21. [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)]
  22. private static extern void DnsFlushResolverCache();
  23. /// <summary>
  24. /// 刷新DNS缓存
  25. /// </summary>
  26. public static void FlushResolverCache()
  27. {
  28. if (OperatingSystem.IsWindows())
  29. {
  30. DnsFlushResolverCache();
  31. }
  32. }
  33. /// <summary>
  34. /// 设置为主dns
  35. /// </summary>
  36. /// <exception cref="FastGithubException"></exception>
  37. public static void SetAsPrimitiveDns()
  38. {
  39. var @interface = GetOutboundNetworkInterface();
  40. if (@interface == null)
  41. {
  42. throw new FastGithubException($"找不到匹配的网络适配器来设置主DNS");
  43. }
  44. var dnsAddresses = @interface.GetIPProperties().DnsAddresses;
  45. var firstRecord = dnsAddresses.FirstOrDefault();
  46. if (firstRecord == null || LocalMachine.ContainsIPAddress(firstRecord) == false)
  47. {
  48. var primitive = IPAddress.Loopback;
  49. var nameServers = dnsAddresses.Prepend(primitive);
  50. if (OperatingSystem.IsWindows())
  51. {
  52. SetNameServers(@interface, nameServers);
  53. }
  54. else if (OperatingSystem.IsLinux())
  55. {
  56. throw new FastGithubException($"不支持自动设置本机DNS,请手工添加{primitive}做为/etc/resolv.conf的第一条记录");
  57. }
  58. else if (OperatingSystem.IsMacOS())
  59. {
  60. throw new FastGithubException($"不支持自动设置本机DNS,请手工添加{primitive}做为连接网络的DNS的第一条记录");
  61. }
  62. }
  63. }
  64. /// <summary>
  65. /// 从主dns移除
  66. /// </summary>
  67. /// <exception cref="FastGithubException"></exception>
  68. public static void RemoveFromPrimitiveDns()
  69. {
  70. var @interface = GetOutboundNetworkInterface();
  71. if (@interface == null)
  72. {
  73. throw new FastGithubException($"找不到匹配的网络适配器来移除主DNS");
  74. }
  75. var dnsAddresses = @interface.GetIPProperties().DnsAddresses;
  76. var firstRecord = dnsAddresses.FirstOrDefault();
  77. if (firstRecord != null && LocalMachine.ContainsIPAddress(firstRecord))
  78. {
  79. var nameServers = dnsAddresses.Skip(1);
  80. if (OperatingSystem.IsWindows())
  81. {
  82. SetNameServers(@interface, nameServers);
  83. }
  84. else if (OperatingSystem.IsLinux())
  85. {
  86. throw new FastGithubException($"不支持自动移除本机主DNS,请手工移除/etc/resolv.conf的第一条记录");
  87. }
  88. else if (OperatingSystem.IsMacOS())
  89. {
  90. throw new FastGithubException($"不支持自动移除本机主DNS,请手工移除连接网络的DNS的第一条记录");
  91. }
  92. }
  93. }
  94. /// <summary>
  95. /// 查找出口的网络适器
  96. /// </summary>
  97. /// <returns></returns>
  98. private static NetworkInterface? GetOutboundNetworkInterface()
  99. {
  100. var remoteEndPoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 53);
  101. var address = LocalMachine.GetLocalIPAddress(remoteEndPoint);
  102. if (address == null)
  103. {
  104. return default;
  105. }
  106. return NetworkInterface
  107. .GetAllNetworkInterfaces()
  108. .Where(item => item.GetIPProperties().UnicastAddresses.Any(a => a.Address.Equals(address)))
  109. .FirstOrDefault();
  110. }
  111. /// <summary>
  112. /// 设置网口的dns
  113. /// </summary>
  114. /// <param name="interface"></param>
  115. /// <param name="nameServers"></param>
  116. [SupportedOSPlatform("windows")]
  117. private static void SetNameServers(NetworkInterface @interface, IEnumerable<IPAddress> nameServers)
  118. {
  119. Netsh($@"interface ipv4 delete dns ""{@interface.Name}"" all");
  120. foreach (var address in nameServers)
  121. {
  122. Netsh($@"interface ipv4 add dns ""{@interface.Name}"" {address} validate=no");
  123. }
  124. static void Netsh(string arguments)
  125. {
  126. var netsh = new ProcessStartInfo
  127. {
  128. FileName = "netsh.exe",
  129. Arguments = arguments,
  130. CreateNoWindow = true,
  131. UseShellExecute = false,
  132. WindowStyle = ProcessWindowStyle.Hidden
  133. };
  134. Process.Start(netsh)?.WaitForExit();
  135. }
  136. }
  137. }
  138. }