Browse Source

增加是否设置本机使用此dns的功能

xljiulang 4 years ago
parent
commit
b486f551cf

+ 1 - 1
Directory.Build.props

@@ -1,6 +1,6 @@
 <Project>
 	<PropertyGroup>
-		<Version>1.0.0-rc2</Version>
+		<Version>1.0.0</Version>
 		<Nullable>enable</Nullable>
 		<Description>github定制版的dns服务,解析github最优的ip</Description>
 		<Copyright>https://github.com/xljiulang/FastGithub</Copyright>

+ 29 - 0
FastGithub.Dns/DnsHostedService.cs

@@ -2,6 +2,8 @@
 using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
+using System;
+using System.Net;
 using System.Threading;
 using System.Threading.Tasks;
 
@@ -13,6 +15,7 @@ namespace FastGithub.Dns
     sealed class DnsHostedService : IHostedService
     {
         private readonly DnsServer dnsServer;
+        private readonly IOptions<DnsOptions> options;
         private readonly ILogger<DnsHostedService> logger;
 
         /// <summary>
@@ -27,6 +30,7 @@ namespace FastGithub.Dns
             ILogger<DnsHostedService> logger)
         {
             this.dnsServer = new DnsServer(githubRequestResolver, options.Value.UpStream);
+            this.options = options;
             this.logger = logger;
         }
 
@@ -39,6 +43,8 @@ namespace FastGithub.Dns
         {
             this.dnsServer.Listen();
             this.logger.LogInformation("dns服务启用成功");
+            this.SetNameServers(IPAddress.Loopback, this.options.Value.UpStream);
+
             return Task.CompletedTask;
         }
 
@@ -51,7 +57,30 @@ namespace FastGithub.Dns
         {
             this.dnsServer.Dispose();
             this.logger.LogInformation("dns服务已终止");
+            this.SetNameServers();
+
             return Task.CompletedTask;
         }
+
+        /// <summary>
+        /// 设备dns
+        /// </summary>
+        /// <param name="nameServers"></param>
+        private void SetNameServers(params IPAddress[] nameServers)
+        {
+            var action = nameServers.Length == 0 ? "清除" : "设置";
+            if (this.options.Value.SetToLocalMachine && OperatingSystem.IsWindows())
+            {
+                try
+                {
+                    NameServiceUtil.SetNameServers(nameServers);
+                    this.logger.LogInformation($"{action}本机dns成功");
+                }
+                catch (Exception ex)
+                {
+                    this.logger.LogWarning($"{action}本机dns失败:{ex.Message}");
+                }
+            }
+        }
     }
 }

+ 5 - 0
FastGithub.Dns/DnsOptions.cs

@@ -18,5 +18,10 @@ namespace FastGithub.Dns
         /// 获取或设置github相关域名的ip存活时长
         /// </summary>
         public TimeSpan GithubTTL { get; set; } = TimeSpan.FromMinutes(10d);
+
+        /// <summary>
+        /// 是否设置本机使用此dns
+        /// </summary>
+        public bool SetToLocalMachine { get; set; } = true;
     }
 }

+ 4 - 0
FastGithub.Dns/FastGithub.Dns.csproj

@@ -4,6 +4,10 @@
 		<TargetFramework>net5.0</TargetFramework>
 	</PropertyGroup>
 
+	<ItemGroup>
+	  <None Remove="DnsOptions.cs~RF5dfc81de.TMP" />
+	</ItemGroup>
+
 	<ItemGroup>
 		<ProjectReference Include="..\FastGithub.Scanner\FastGithub.Scanner.csproj" />
 	</ItemGroup>

+ 84 - 0
FastGithub.Dns/NameServiceUtil.cs

@@ -0,0 +1,84 @@
+using System;
+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>
+    [SupportedOSPlatform("windows")]
+    static class NameServiceUtil
+    {
+        /// <summary>
+        /// www.baidu.com的ip
+        /// </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>
+        /// 通过远程地址查找匹配的网络适接口
+        /// </summary>
+        /// <param name="remoteAddress"></param>
+        /// <returns></returns>
+        private static NetworkInterface? GetBestNetworkInterface(IPAddress remoteAddress)
+        {
+            var dwBestIfIndex = 0u;
+            var dwDestAddr = BitConverter.ToUInt32(remoteAddress.GetAddressBytes());
+            var errorCode = GetBestInterface(dwDestAddr, ref dwBestIfIndex);
+            if (errorCode != 0)
+            {
+                throw new NetworkInformationException(errorCode);
+            }
+
+            return NetworkInterface
+                .GetAllNetworkInterfaces()
+                .Where(item => item.GetIPProperties().GetIPv4Properties().Index == dwBestIfIndex)
+                .FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 设置域名服务
+        /// </summary>
+        /// <param name="nameServers"></param>
+        /// <exception cref="NetworkInformationException"></exception>
+        /// <exception cref="NotSupportedException"></exception>
+        public static void SetNameServers(params IPAddress[] nameServers)
+        {
+            var networkIF = GetBestNetworkInterface(www_baidu_com);
+            if (networkIF == null)
+            {
+                throw new NotSupportedException("找不到网络适配器用来设置dns");
+            }
+
+            Netsh($@"interface ipv4 delete dns ""{networkIF.Name}"" all");
+            foreach (var address in nameServers)
+            {
+                Netsh($@"interface ipv4 add dns ""{networkIF.Name}"" {address} validate=no");
+            }
+        }
+
+        /// <summary>
+        /// 执行Netsh
+        /// </summary>
+        /// <param name="arguments"></param>
+        private 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();
+        }
+    }
+}

+ 5 - 0
FastGithub/FastGithub.csproj

@@ -4,12 +4,17 @@
 		<OutputType>Exe</OutputType>
 		<TargetFrameworks>net5.0;net6.0</TargetFrameworks>
 		<PackageLicenseExpression>MIT</PackageLicenseExpression>
+		<ApplicationIcon>app.ico</ApplicationIcon>
 	</PropertyGroup>
 
 	<PropertyGroup Condition="'$(TargetFramework)' == 'net6.0'">
 		<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
 	</PropertyGroup>
 
+	<PropertyGroup Condition="'$(Configuration)' == 'Release'">
+		<ApplicationManifest>app.manifest</ApplicationManifest>
+	</PropertyGroup>
+
 	<ItemGroup>
 		<PackageReference Include="PInvoke.AdvApi32" Version="0.7.104" />
 		<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />

BIN
FastGithub/app.ico


+ 75 - 0
FastGithub/app.manifest

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <!-- UAC 清单选项
+             如果想要更改 Windows 用户帐户控制级别,请使用
+             以下节点之一替换 requestedExecutionLevel 节点。n
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
+        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
+
+            指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
+            如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
+            元素。
+        -->
+        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
+           Windows 版本的列表。取消评论适当的元素,
+           Windows 将自动选择最兼容的环境。 -->
+
+      <!-- Windows Vista -->
+      <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
+
+      <!-- Windows 7 -->
+      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
+
+      <!-- Windows 8 -->
+      <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
+
+      <!-- Windows 8.1 -->
+      <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
+
+      <!-- Windows 10 -->
+      <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
+
+    </application>
+  </compatibility>
+
+  <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
+       自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
+       选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
+       在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
+  <!--
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+    </windowsSettings>
+  </application>
+  -->
+
+  <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
+  <!--
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity
+          type="win32"
+          name="Microsoft.Windows.Common-Controls"
+          version="6.0.0.0"
+          processorArchitecture="*"
+          publicKeyToken="6595b64144ccf1df"
+          language="*"
+        />
+    </dependentAssembly>
+  </dependency>
+  -->
+
+</assembly>

+ 2 - 1
FastGithub/appsettings.json

@@ -1,7 +1,8 @@
 {
   "Dns": {
     "UpStream": "114.114.114.114", // 上游dns
-    "GithubTTL": "00:10:00" // github相关域名解析结果的存活时长
+    "GithubTTL": "00:10:00", // github相关域名解析结果的存活时长
+    "SetToLocalMachine": true // 是否设置本机使用此dns(仅支持windows)
   },
   "Github": {
     "Lookup": { // ip查找