diff --git a/Directory.Build.props b/Directory.Build.props index a51c7e1..c1ac4ba 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 1.2.1 + 2.0.0 enable github加速神器 https://github.com/dotnetcore/FastGithub diff --git a/FastGithub.Configuration/LocalMachine.cs b/FastGithub.Configuration/LocalMachine.cs index bb8c842..a872f8e 100644 --- a/FastGithub.Configuration/LocalMachine.cs +++ b/FastGithub.Configuration/LocalMachine.cs @@ -58,27 +58,40 @@ namespace FastGithub.Configuration public static bool ContainsIPAddress(IPAddress address) { return GetAllIPAddresses().Contains(address); - } + } + /// - /// 获取与远程节点通讯的的本机IP地址 + /// 获取可用的随机Tcp端口 /// - /// 远程地址 + /// + /// 最小值 /// - public static IPAddress? GetLocalIPAddress(EndPoint remoteEndPoint) + public static int GetAvailableTcpPort(AddressFamily addressFamily, int min = 1025) { - try + var hashSet = new HashSet(); + var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(); + + foreach (var item in tcpListeners) { - using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - socket.Connect(remoteEndPoint); - return socket.LocalEndPoint is IPEndPoint localEndPoint ? localEndPoint.Address : default; + if (item.AddressFamily == addressFamily) + { + hashSet.Add(item.Port); + } } - catch (Exception) + + for (var port = min; port < ushort.MaxValue; port++) { - return default; + if (hashSet.Contains(port) == false) + { + return port; + } } + + throw new FastGithubException("当前无可用的端口"); } + /// /// 获取可用的随机端口 /// @@ -128,16 +141,5 @@ namespace FastGithub.Configuration var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(); return tcpListeners.Any(item => item.Port == port) == false; } - - /// - /// 是否可以监听指定udp端口 - /// - /// - /// - public static bool CanListenUdp(int port) - { - var udpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners(); - return udpListeners.Any(item => item.Port == port) == false; - } } } diff --git a/FastGithub.Dns/DnsDnsPoisoningHostedService.cs b/FastGithub.Dns/DnsInterceptHostedService.cs similarity index 57% rename from FastGithub.Dns/DnsDnsPoisoningHostedService.cs rename to FastGithub.Dns/DnsInterceptHostedService.cs index cbb6bda..29baf14 100644 --- a/FastGithub.Dns/DnsDnsPoisoningHostedService.cs +++ b/FastGithub.Dns/DnsInterceptHostedService.cs @@ -1,5 +1,4 @@ using Microsoft.Extensions.Hosting; -using System; using System.Collections.Generic; using System.Runtime.Versioning; using System.Threading; @@ -8,24 +7,24 @@ using System.Threading.Tasks; namespace FastGithub.Dns { /// - /// dns投毒后台服务 + /// dns拦截后台服务 /// [SupportedOSPlatform("windows")] - sealed class DnsDnsPoisoningHostedService : BackgroundService + sealed class DnsInterceptHostedService : BackgroundService { - private readonly DnsPoisoningServer dnsPoisoningServer; + private readonly DnsInterceptor dnsInterceptor; private readonly IEnumerable conflictValidators; /// - /// dns后台服务 + /// dns拦截后台服务 /// - /// + /// /// - public DnsDnsPoisoningHostedService( - DnsPoisoningServer dnsPoisoningServer, + public DnsInterceptHostedService( + DnsInterceptor dnsInterceptor, IEnumerable conflictValidators) { - this.dnsPoisoningServer = dnsPoisoningServer; + this.dnsInterceptor = dnsInterceptor; this.conflictValidators = conflictValidators; } @@ -37,15 +36,11 @@ namespace FastGithub.Dns protected override async Task ExecuteAsync(CancellationToken stoppingToken) { await Task.Yield(); - - if (OperatingSystem.IsWindows()) + foreach (var item in this.conflictValidators) { - foreach (var item in this.conflictValidators) - { - await item.ValidateAsync(); - } - this.dnsPoisoningServer.DnsPoisoning(stoppingToken); + await item.ValidateAsync(); } + this.dnsInterceptor.Intercept(stoppingToken); } } } diff --git a/FastGithub.Dns/DnsPoisoningServer.cs b/FastGithub.Dns/DnsInterceptor.cs similarity index 93% rename from FastGithub.Dns/DnsPoisoningServer.cs rename to FastGithub.Dns/DnsInterceptor.cs index ee1414f..c970c55 100644 --- a/FastGithub.Dns/DnsPoisoningServer.cs +++ b/FastGithub.Dns/DnsInterceptor.cs @@ -14,14 +14,14 @@ using WinDivertSharp; namespace FastGithub.Dns { /// - /// dns投毒服务 + /// dns拦截器 /// [SupportedOSPlatform("windows")] - sealed class DnsPoisoningServer + sealed class DnsInterceptor { const string DNS_FILTER = "udp.DstPort == 53"; private readonly FastGithubConfig fastGithubConfig; - private readonly ILogger logger; + private readonly ILogger logger; private readonly TimeSpan ttl = TimeSpan.FromSeconds(10d); /// @@ -35,19 +35,19 @@ namespace FastGithub.Dns /// /// /// - public DnsPoisoningServer( + public DnsInterceptor( FastGithubConfig fastGithubConfig, - ILogger logger) + ILogger logger) { this.fastGithubConfig = fastGithubConfig; this.logger = logger; } /// - /// DNS投毒 + /// DNS拦截 /// /// - public void DnsPoisoning(CancellationToken cancellationToken) + public void Intercept(CancellationToken cancellationToken) { var handle = WinDivert.WinDivertOpen(DNS_FILTER, WinDivertLayer.Network, 0, WinDivertOpenFlags.None); if (handle == IntPtr.Zero) diff --git a/FastGithub.Dns/ServiceCollectionExtensions.cs b/FastGithub.Dns/ServiceCollectionExtensions.cs index 8725e49..80dff07 100644 --- a/FastGithub.Dns/ServiceCollectionExtensions.cs +++ b/FastGithub.Dns/ServiceCollectionExtensions.cs @@ -11,17 +11,17 @@ namespace FastGithub public static class ServiceCollectionExtensions { /// - /// 注册dns投毒服务 + /// 注册dns拦截器 /// /// /// [SupportedOSPlatform("windows")] - public static IServiceCollection AddDnsPoisoning(this IServiceCollection services) - { - services.TryAddSingleton(); + public static IServiceCollection AddDnsInterceptor(this IServiceCollection services) + { + services.TryAddSingleton(); services.AddSingleton(); services.AddSingleton(); - return services.AddHostedService(); + return services.AddHostedService(); } } } diff --git a/FastGithub.DomainResolve/DnscryptProxyHostedService.cs b/FastGithub.DomainResolve/DnscryptProxyHostedService.cs index 95872a9..5ddd071 100644 --- a/FastGithub.DomainResolve/DnscryptProxyHostedService.cs +++ b/FastGithub.DomainResolve/DnscryptProxyHostedService.cs @@ -37,7 +37,7 @@ namespace FastGithub.DomainResolve try { await this.dnscryptProxy.StartAsync(cancellationToken); - this.logger.LogInformation($"已监听端口{this.dnscryptProxy.LocalEndPoint?.Port},{this.dnscryptProxy}启动完成"); + this.logger.LogInformation($"已监听dns://{this.dnscryptProxy.LocalEndPoint},{this.dnscryptProxy}启动完成"); } catch (Exception ex) { diff --git a/FastGithub.ReverseProxy/ApplicationBuilderExtensions.cs b/FastGithub.ReverseProxy/ApplicationBuilderExtensions.cs index e57b668..ae00c6b 100644 --- a/FastGithub.ReverseProxy/ApplicationBuilderExtensions.cs +++ b/FastGithub.ReverseProxy/ApplicationBuilderExtensions.cs @@ -17,7 +17,7 @@ namespace FastGithub public static IApplicationBuilder UseHttpProxy(this IApplicationBuilder app) { var middleware = app.ApplicationServices.GetRequiredService(); - return app.Use(next => context => middleware.InvokeAsync(context, next)); + return app.Use(next => context => middleware.InvokeAsync(context)); } /// diff --git a/FastGithub.ReverseProxy/HttpProxyMiddleware.cs b/FastGithub.ReverseProxy/HttpProxyMiddleware.cs index 9915b54..224e134 100644 --- a/FastGithub.ReverseProxy/HttpProxyMiddleware.cs +++ b/FastGithub.ReverseProxy/HttpProxyMiddleware.cs @@ -20,7 +20,6 @@ namespace FastGithub.ReverseProxy private readonly FastGithubConfig fastGithubConfig; private readonly IDomainResolver domainResolver; private readonly IHttpForwarder httpForwarder; - private readonly PortService portService; private readonly SocketsHttpHandler socketsHttpHandler = new() { UseCookies = false, UseProxy = false, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None }; /// @@ -29,26 +28,22 @@ namespace FastGithub.ReverseProxy /// /// /// - /// public HttpProxyMiddleware( FastGithubConfig fastGithubConfig, IDomainResolver domainResolver, - IHttpForwarder httpForwarder, - PortService portService) + IHttpForwarder httpForwarder) { this.fastGithubConfig = fastGithubConfig; this.domainResolver = domainResolver; this.httpForwarder = httpForwarder; - this.portService = portService; } /// /// 处理请求 /// /// - /// /// - public async Task InvokeAsync(HttpContext context, RequestDelegate next) + public async Task InvokeAsync(HttpContext context) { if (context.Request.Method != HttpMethods.Connect) { @@ -77,7 +72,6 @@ namespace FastGithub.ReverseProxy } } - /// /// 获取目标终节点 /// @@ -85,28 +79,28 @@ namespace FastGithub.ReverseProxy /// private async Task GetTargetEndPointAsync(HttpRequest request) { - var domain = request.Host.Host; - var port = request.Host.Port ?? 443; + var targetHost = request.Host.Host; + var targetPort = request.Host.Port ?? 443; - if (IPAddress.TryParse(domain, out var address) == true) + if (IPAddress.TryParse(targetHost, out var address) == true) { - return new IPEndPoint(address, port); + return new IPEndPoint(address, targetPort); } - if (this.fastGithubConfig.TryGetDomainConfig(domain, out _) == false) + if (this.fastGithubConfig.TryGetDomainConfig(targetHost, out _) == false) { - return new DnsEndPoint(domain, port); + return new DnsEndPoint(targetHost, targetPort); } // https,走反向代理中间人 - if (port == 443) + if (targetPort == 443) { - return new IPEndPoint(IPAddress.Loopback, this.portService.HttpsReverseProxyPort); + return new IPEndPoint(IPAddress.Loopback, HttpsReverseProxyPort.Value); } // dns优选 - address = await this.domainResolver.ResolveAsync(new DnsEndPoint(domain, port)); - return new IPEndPoint(address, port); + address = await this.domainResolver.ResolveAsync(new DnsEndPoint(targetHost, targetPort)); + return new IPEndPoint(address, targetPort); } } } \ No newline at end of file diff --git a/FastGithub.ReverseProxy/HttpsReverseProxyPort.cs b/FastGithub.ReverseProxy/HttpsReverseProxyPort.cs new file mode 100644 index 0000000..0fa5181 --- /dev/null +++ b/FastGithub.ReverseProxy/HttpsReverseProxyPort.cs @@ -0,0 +1,17 @@ +using FastGithub.Configuration; +using System; +using System.Net.Sockets; + +namespace FastGithub.ReverseProxy +{ + /// + /// https反向代理端口 + /// + static class HttpsReverseProxyPort + { + /// + /// 获取端口值 + /// + public static int Value { get; } = OperatingSystem.IsWindows() ? 443 : LocalMachine.GetAvailableTcpPort(AddressFamily.InterNetwork); + } +} diff --git a/FastGithub.ReverseProxy/KestrelServerOptionsExtensions.cs b/FastGithub.ReverseProxy/KestrelServerOptionsExtensions.cs index 71b7018..ad99cd4 100644 --- a/FastGithub.ReverseProxy/KestrelServerOptionsExtensions.cs +++ b/FastGithub.ReverseProxy/KestrelServerOptionsExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using System; using System.Net; @@ -30,18 +31,18 @@ namespace FastGithub /// public static void ListenHttpProxy(this KestrelServerOptions kestrel) { - var httpPort = kestrel.ApplicationServices.GetRequiredService().HttpProxyPort; - if (LocalMachine.CanListenTcp(httpPort) == false) + var httpProxyPort = kestrel.ApplicationServices.GetRequiredService>().Value.HttpProxyPort; + if (LocalMachine.CanListenTcp(httpProxyPort) == false) { - throw new FastGithubException("tcp端口{httpsPort}已经被其它进程占用,请在配置文件更换一个端口"); + throw new FastGithubException($"tcp端口{httpProxyPort}已经被其它进程占用,请在配置文件更换{nameof(FastGithubOptions.HttpProxyPort)}为其它端口"); } - kestrel.Listen(IPAddress.Any, httpPort); - kestrel.GetLogger().LogInformation($"已监听tcp端口{httpPort},http代理启动完成"); + kestrel.Listen(IPAddress.Loopback, httpProxyPort); + kestrel.GetLogger().LogInformation($"已监听http://127.0.0.1:{httpProxyPort},http代理启动完成"); } /// - /// 监听ssh反向代理 + /// 尝试监听ssh反向代理 /// /// public static void ListenSshReverseProxy(this KestrelServerOptions kestrel) @@ -49,13 +50,13 @@ namespace FastGithub const int SSH_PORT = 22; if (LocalMachine.CanListenTcp(SSH_PORT) == true) { - kestrel.Listen(IPAddress.Any, SSH_PORT, listen => listen.UseConnectionHandler()); - kestrel.GetLogger().LogInformation($"已监听tcp端口{SSH_PORT},github的ssh代理启动完成"); + kestrel.Listen(IPAddress.Loopback, SSH_PORT, listen => listen.UseConnectionHandler()); + kestrel.GetLogger().LogInformation($"已监听ssh://127.0.0.1:{SSH_PORT},ssh反向代理到github启动完成"); } } /// - /// 监听http反向代理 + /// 尝试监听http反向代理 /// /// public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel) @@ -63,8 +64,8 @@ namespace FastGithub const int HTTP_PORT = 80; if (LocalMachine.CanListenTcp(HTTP_PORT) == true) { - kestrel.Listen(IPAddress.Any, HTTP_PORT); - kestrel.GetLogger().LogInformation($"已监听tcp端口{HTTP_PORT},http反向代理启动完成"); + kestrel.Listen(IPAddress.Loopback, HTTP_PORT); + kestrel.GetLogger().LogInformation($"已监听http://127.0.0.1:{HTTP_PORT},http反向代理启动完成"); } } @@ -73,9 +74,10 @@ namespace FastGithub /// /// /// - public static void ListenHttpsReverseProxy(this KestrelServerOptions kestrel) + /// + public static int ListenHttpsReverseProxy(this KestrelServerOptions kestrel) { - var httpsPort = kestrel.ApplicationServices.GetRequiredService().HttpsReverseProxyPort; + var httpsPort = HttpsReverseProxyPort.Value; if (OperatingSystem.IsWindows()) { TcpTable.KillPortOwner(httpsPort); @@ -90,15 +92,19 @@ namespace FastGithub certService.CreateCaCertIfNotExists(); certService.InstallAndTrustCaCert(); - kestrel.Listen(IPAddress.Any, httpsPort, + kestrel.Listen(IPAddress.Loopback, httpsPort, listen => listen.UseHttps(https => https.ServerCertificateSelector = (ctx, domain) => certService.GetOrCreateServerCert(domain))); - var logger = kestrel.GetLogger(); - logger.LogInformation($"已监听tcp端口{httpsPort},https反向代理启动完成"); - } + if (httpsPort == 443) + { + var logger = kestrel.GetLogger(); + logger.LogInformation($"已监听https://127.0.0.1:{httpsPort},https反向代理启动完成"); + } + return httpsPort; + } /// /// 获取日志 diff --git a/FastGithub.ReverseProxy/PortService.cs b/FastGithub.ReverseProxy/PortService.cs deleted file mode 100644 index 31074f4..0000000 --- a/FastGithub.ReverseProxy/PortService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using FastGithub.Configuration; -using Microsoft.Extensions.Options; -using System; -using System.Net.Sockets; - -namespace FastGithub.ReverseProxy -{ - /// - /// 端口管理服务 - /// - public class PortService - { - private int httpsReverseProxyPort = -1; - - /// - /// http代理端口 - /// - public int HttpProxyPort { get; } - - /// - /// 获取https反向代理端口 - /// - public int HttpsReverseProxyPort - { - get - { - if (OperatingSystem.IsWindows()) - { - return 443; - } - if (this.httpsReverseProxyPort < 0) - { - this.httpsReverseProxyPort = LocalMachine.GetAvailablePort(AddressFamily.InterNetwork); - } - return this.httpsReverseProxyPort; - } - } - - /// - /// 端口管理服务 - /// - /// - public PortService(IOptions options) - { - this.HttpProxyPort = options.Value.HttpProxyPort; - } - } -} diff --git a/FastGithub.ReverseProxy/ServiceCollectionExtensions.cs b/FastGithub.ReverseProxy/ServiceCollectionExtensions.cs index f265b0e..92a65cb 100644 --- a/FastGithub.ReverseProxy/ServiceCollectionExtensions.cs +++ b/FastGithub.ReverseProxy/ServiceCollectionExtensions.cs @@ -4,12 +4,12 @@ using Microsoft.Extensions.DependencyInjection; namespace FastGithub { /// - /// https反向代理的服务注册扩展 + /// http反向代理的服务注册扩展 /// public static class ServiceCollectionExtensions { /// - /// 添加https反向代理 + /// 添加http反向代理 /// /// /// @@ -18,8 +18,7 @@ namespace FastGithub return services .AddMemoryCache() .AddHttpForwarder() - .AddSingleton() - .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton(); diff --git a/FastGithub/Program.cs b/FastGithub/Program.cs index 87a0fe7..62d7a22 100644 --- a/FastGithub/Program.cs +++ b/FastGithub/Program.cs @@ -52,15 +52,15 @@ namespace FastGithub webBuilder.UseKestrel(kestrel => { kestrel.NoLimit(); - kestrel.ListenHttpsReverseProxy(); - if (OperatingSystem.IsWindows()) { + kestrel.ListenHttpsReverseProxy(); kestrel.ListenHttpReverseProxy(); kestrel.ListenSshReverseProxy(); } else { + kestrel.ListenHttpsReverseProxy(); kestrel.ListenHttpProxy(); } }); diff --git a/FastGithub/Startup.cs b/FastGithub/Startup.cs index 4af2cdf..c321732 100644 --- a/FastGithub/Startup.cs +++ b/FastGithub/Startup.cs @@ -1,10 +1,9 @@ using FastGithub.Configuration; -using FastGithub.ReverseProxy; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using System; -using System.Threading.Tasks; namespace FastGithub { @@ -40,7 +39,7 @@ namespace FastGithub if (OperatingSystem.IsWindows()) { - services.AddDnsPoisoning(); + services.AddDnsInterceptor(); } } @@ -54,22 +53,16 @@ namespace FastGithub { app.UseRequestLogging(); app.UseHttpReverseProxy(); - app.UseRouting(); - app.UseEndpoints(endpoint => endpoint.MapFallback(context => - { - context.Response.Redirect("https://github.com/dotnetcore/FastGithub"); - return Task.CompletedTask; - })); } else { - var portService = app.ApplicationServices.GetRequiredService(); - app.MapWhen(context => context.Connection.LocalPort == portService.HttpProxyPort, appBuilder => + var httpProxyPort = app.ApplicationServices.GetRequiredService>().Value.HttpProxyPort; + app.MapWhen(context => context.Connection.LocalPort == httpProxyPort, appBuilder => { appBuilder.UseHttpProxy(); }); - app.MapWhen(context => context.Connection.LocalPort != portService.HttpProxyPort, appBuilder => + app.MapWhen(context => context.Connection.LocalPort != httpProxyPort, appBuilder => { appBuilder.UseRequestLogging(); appBuilder.UseHttpReverseProxy();