فهرست منبع

增加dns端口占用进程检测

xljiulang 4 سال پیش
والد
کامیت
6e0e64c69d
3فایلهای تغییر یافته به همراه103 افزوده شده و 1 حذف شده
  1. 8 1
      FastGithub.Dns/DnsServerHostedService.cs
  2. 1 0
      FastGithub.Dns/FastGithub.Dns.csproj
  3. 94 0
      FastGithub.Dns/UdpTable.cs

+ 8 - 1
FastGithub.Dns/DnsServerHostedService.cs

@@ -3,6 +3,7 @@ using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
 using System;
+using System.Diagnostics;
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
@@ -46,7 +47,13 @@ namespace FastGithub.Dns
         /// <returns></returns>
         public override Task StartAsync(CancellationToken cancellationToken)
         {
-            this.socket.Bind(new IPEndPoint(IPAddress.Any, 53));
+            const int DNS_PORT = 53;
+            if (OperatingSystem.IsWindows() && UdpTable.TryGetOwnerProcessId(DNS_PORT, out var processId))
+            {
+                Process.GetProcessById(processId).Kill();
+            }
+
+            this.socket.Bind(new IPEndPoint(IPAddress.Any, DNS_PORT));
             if (OperatingSystem.IsWindows())
             {
                 const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C);

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

@@ -2,6 +2,7 @@
 
 	<PropertyGroup>
 		<TargetFramework>net5.0</TargetFramework>
+		<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
 	</PropertyGroup> 
 
 	<ItemGroup>

+ 94 - 0
FastGithub.Dns/UdpTable.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Buffers.Binary;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace FastGithub.Dns
+{
+    /// <summary>
+    /// windows iphlpapi
+    /// </summary>
+    [SupportedOSPlatform("windows")]
+    unsafe static class UdpTable
+    {
+        private const int ERROR_INSUFFICIENT_BUFFER = 122;
+
+        [DllImport("iphlpapi.dll", SetLastError = true)]
+        private static extern uint GetExtendedUdpTable(void* pUdpTable, ref int pdwSize, bool bOrder, AddressFamily ulAf, UDP_TABLE_CLASS tableClass, uint reserved = 0);
+
+        /// <summary>
+        /// 获取udp端口的占用进程id
+        /// </summary>
+        /// <param name="port"></param>
+        /// <param name="processId"></param>
+        /// <returns></returns>
+        public static bool TryGetOwnerProcessId(int port, out int processId)
+        {
+            processId = 0;
+            var pdwSize = 0;
+            var result = GetExtendedUdpTable(null, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
+            if (result != ERROR_INSUFFICIENT_BUFFER)
+            {
+                return false;
+            }
+
+            var buffer = new byte[pdwSize];
+            fixed (byte* pUdpTable = &buffer[0])
+            {
+                result = GetExtendedUdpTable(pUdpTable, ref pdwSize, false, AddressFamily.InterNetwork, UDP_TABLE_CLASS.UDP_TABLE_OWNER_PID);
+                if (result != 0)
+                {
+                    return false;
+                }
+
+                var table = Marshal.PtrToStructure<MIB_UDPTABLE_OWNER_PID>(new IntPtr(pUdpTable));
+                foreach (var row in table.rows)
+                {
+                    if (row.LocalPort == port)
+                    {
+                        processId = row.ProcessId;
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+
+        private enum UDP_TABLE_CLASS
+        {
+            UDP_TABLE_BASIC,
+            UDP_TABLE_OWNER_PID,
+            UDP_TABLE_OWNER_MODULE
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct MIB_UDPTABLE_OWNER_PID
+        {
+            public uint dwNumEntries;
+
+            [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
+            public MIB_UDPROW_OWNER_PID[] rows;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        private struct MIB_UDPROW_OWNER_PID
+        {
+            public uint localAddr;
+
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
+            public byte[] localPort;
+
+            public int owningPid;
+
+            public int ProcessId => owningPid;
+
+            public IPAddress LocalAddress => new(localAddr);
+
+            public ushort LocalPort => BinaryPrimitives.ReadUInt16BigEndian(this.localPort);
+        }
+    }
+}