diff --git a/FastGithub.Dns/UdpTable.cs b/FastGithub.Dns/UdpTable.cs index 73ec7f1..8657c96 100644 --- a/FastGithub.Dns/UdpTable.cs +++ b/FastGithub.Dns/UdpTable.cs @@ -43,14 +43,19 @@ namespace FastGithub.Dns return false; } - var table = Marshal.PtrToStructure(new IntPtr(pUdpTable)); - foreach (var row in table.rows) + var prt = new IntPtr(pUdpTable); + var table = Marshal.PtrToStructure(prt); + prt += sizeof(int); + for (var i = 0; i < table.dwNumEntries; i++) { + var row = Marshal.PtrToStructure(prt); if (row.LocalPort == port) { processId = row.ProcessId; return true; } + + prt += Marshal.SizeOf(); } } @@ -69,9 +74,6 @@ namespace FastGithub.Dns 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)] diff --git a/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj b/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj index 2a1696b..a2f248c 100644 --- a/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj +++ b/FastGithub.ReverseProxy/FastGithub.ReverseProxy.csproj @@ -2,6 +2,7 @@ net5.0 + true diff --git a/FastGithub.ReverseProxy/ReverseProxyHostedService.cs b/FastGithub.ReverseProxy/ReverseProxyHostedService.cs new file mode 100644 index 0000000..324ccbc --- /dev/null +++ b/FastGithub.ReverseProxy/ReverseProxyHostedService.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; + +namespace FastGithub.ReverseProxy +{ + /// + /// 反向代理端口检测后台服务 + /// + sealed class ReverseProxyHostedService : IHostedService + { + private readonly ILogger logger; + + /// + /// 反向代理端口检测后台服务 + /// + /// + public ReverseProxyHostedService(ILogger logger) + { + this.logger = logger; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + if (OperatingSystem.IsWindows()) + { + const int HTTPSPORT = 443; + if (TcpTable.TryGetOwnerProcessId(HTTPSPORT, out var pid)) + { + var process = Process.GetProcessById(pid); + this.logger.LogError($"由于进程{process.ProcessName}({pid})占用了{HTTPSPORT}端口,{nameof(FastGithub)}的反向代理无法工作"); + } + } + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + } +} diff --git a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs index b027f57..c65faef 100644 --- a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs +++ b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs @@ -20,7 +20,8 @@ namespace FastGithub .AddHttpForwarder() .AddHttpClient() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddHostedService(); } } } diff --git a/FastGithub.ReverseProxy/TcpTable.cs b/FastGithub.ReverseProxy/TcpTable.cs new file mode 100644 index 0000000..fcf0033 --- /dev/null +++ b/FastGithub.ReverseProxy/TcpTable.cs @@ -0,0 +1,109 @@ +using System; +using System.Buffers.Binary; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace FastGithub.ReverseProxy +{ + /// + /// windows iphlpapi + /// + [SupportedOSPlatform("windows")] + unsafe static class TcpTable + { + private const int ERROR_INSUFFICIENT_BUFFER = 122; + + [DllImport("iphlpapi.dll", SetLastError = true)] + private static extern uint GetExtendedTcpTable(void* pTcpTable, ref int pdwSize, bool bOrder, AddressFamily ulAf, TCP_TABLE_CLASS tableClass, uint reserved = 0); + + /// + /// 获取tcp端口的占用进程id + /// + /// + /// + /// + public static bool TryGetOwnerProcessId(int port, out int processId) + { + processId = 0; + var pdwSize = 0; + var result = GetExtendedTcpTable(null, ref pdwSize, false, AddressFamily.InterNetwork, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER); + if (result != ERROR_INSUFFICIENT_BUFFER) + { + return false; + } + + var buffer = new byte[pdwSize]; + fixed (byte* pTcpTable = &buffer[0]) + { + result = GetExtendedTcpTable(pTcpTable, ref pdwSize, false, AddressFamily.InterNetwork, TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_LISTENER); + if (result != 0) + { + return false; + } + + var prt = new IntPtr(pTcpTable); + var table = Marshal.PtrToStructure(prt); + prt += sizeof(int); + for (var i = 0; i < table.dwNumEntries; i++) + { + var row = Marshal.PtrToStructure(prt); + if (row.LocalPort == port) + { + processId = row.ProcessId; + return true; + } + + prt += Marshal.SizeOf(); + } + } + + return false; + } + + + private enum TCP_TABLE_CLASS + { + TCP_TABLE_BASIC_LISTENER, + TCP_TABLE_BASIC_CONNECTIONS, + TCP_TABLE_BASIC_ALL, + TCP_TABLE_OWNER_PID_LISTENER, + TCP_TABLE_OWNER_PID_CONNECTIONS, + TCP_TABLE_OWNER_PID_ALL, + TCP_TABLE_OWNER_MODULE_LISTENER, + TCP_TABLE_OWNER_MODULE_CONNECTIONS, + TCP_TABLE_OWNER_MODULE_ALL + } + + [StructLayout(LayoutKind.Sequential)] + private struct MIB_TCPTABLE_OWNER_PID + { + public uint dwNumEntries; + } + + [StructLayout(LayoutKind.Sequential)] + private struct MIB_TCPROW_OWNER_PID + { + public uint state; + + public uint localAddr; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] localPort; + + public uint remoteAddr; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] remotePort; + + public int owningPid; + + public int ProcessId => owningPid; + + public IPAddress LocalAddress => new(localAddr); + + public ushort LocalPort => BinaryPrimitives.ReadUInt16BigEndian(this.localPort); + } + } +} diff --git a/FastGithub/Program.cs b/FastGithub/Program.cs index d001c4b..794216a 100644 --- a/FastGithub/Program.cs +++ b/FastGithub/Program.cs @@ -42,9 +42,9 @@ namespace FastGithub .ConfigureServices((ctx, services) => { services.AddDnsServer(); - services.AddReverseProxy(); services.AddDnscryptProxy(); services.AddAppUpgrade(); + services.AddReverseProxy(); services.AddSingleton(); services.Configure(ctx.Configuration.GetSection(nameof(FastGithub))); })