Sfoglia il codice sorgente

增加GithubReverseProxyOptions

陈国伟 4 anni fa
parent
commit
4d181e413c

+ 1 - 6
FastGithub.Dns/DnsOptions.cs

@@ -22,11 +22,6 @@ namespace FastGithub.Dns
         /// <summary>
         /// 是否设置本机使用此dns
         /// </summary>
-        public bool SetToLocalMachine { get; set; } = true;
-
-        /// <summary>
-        /// 是否启用反向代理
-        /// </summary>
-        public bool UseReverseProxy { get; set; } = true;
+        public bool SetToLocalMachine { get; set; } = true; 
     }
 }

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

@@ -5,6 +5,7 @@
 	</PropertyGroup> 
 
 	<ItemGroup>
+		<ProjectReference Include="..\FastGithub.ReverseProxy\FastGithub.ReverseProxy.csproj" />
 		<ProjectReference Include="..\FastGithub.Scanner\FastGithub.Scanner.csproj" />
 	</ItemGroup>
 </Project>

+ 35 - 22
FastGithub.Dns/GithubRequestResolver.cs

@@ -1,6 +1,7 @@
 using DNS.Client.RequestResolver;
 using DNS.Protocol;
 using DNS.Protocol.ResourceRecords;
+using FastGithub.ReverseProxy;
 using FastGithub.Scanner;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
@@ -21,6 +22,8 @@ namespace FastGithub.Dns
     {
         private readonly IGithubScanResults githubScanResults;
         private readonly IOptionsMonitor<DnsOptions> options;
+        private readonly IOptionsMonitor<GithubLookupFactoryOptions> lookupOptions;
+        private readonly IOptionsMonitor<GithubReverseProxyOptions> reverseProxyOptions;
         private readonly ILogger<GithubRequestResolver> logger;
 
         /// <summary>
@@ -32,10 +35,14 @@ namespace FastGithub.Dns
         public GithubRequestResolver(
             IGithubScanResults githubScanResults,
             IOptionsMonitor<DnsOptions> options,
+            IOptionsMonitor<GithubLookupFactoryOptions> lookupOptions,
+            IOptionsMonitor<GithubReverseProxyOptions> reverseProxyOptions,
             ILogger<GithubRequestResolver> logger)
         {
             this.githubScanResults = githubScanResults;
             this.options = options;
+            this.lookupOptions = lookupOptions;
+            this.reverseProxyOptions = reverseProxyOptions;
             this.logger = logger;
         }
 
@@ -50,36 +57,42 @@ namespace FastGithub.Dns
             var response = Response.FromRequest(request);
             var question = request.Questions.FirstOrDefault();
 
-            if (question != null && question.Type == RecordType.A)
+            if (question == null || question.Type != RecordType.A)
             {
-                var domain = question.Name.ToString();
-                var address = this.githubScanResults.FindBestAddress(domain);
+                return response;
+            }
+
+            var domain = question.Name.ToString();
+            if (this.lookupOptions.CurrentValue.Domains.Contains(domain) == false)
+            {
+                return response;
+            }
 
+            if (this.reverseProxyOptions.CurrentValue.Enable == false)
+            {
+                var address = this.githubScanResults.FindBestAddress(domain);
                 if (address != null)
                 {
-                    if (this.options.CurrentValue.UseReverseProxy == false)
+                    var ttl = this.options.CurrentValue.GithubTTL;
+                    var record = new IPAddressResourceRecord(question.Name, address, ttl);
+                    response.AnswerRecords.Add(record);
+                    this.logger.LogInformation(record.ToString());
+                }
+            }
+            else
+            {
+                var localhost = System.Net.Dns.GetHostName();
+                var addresses = await System.Net.Dns.GetHostAddressesAsync(localhost);
+                var ttl = TimeSpan.FromMinutes(1d);
+
+                foreach (var item in addresses)
+                {
+                    if (item.AddressFamily == AddressFamily.InterNetwork)
                     {
-                        var ttl = this.options.CurrentValue.GithubTTL;
-                        var record = new IPAddressResourceRecord(question.Name, address, ttl);
+                        var record = new IPAddressResourceRecord(question.Name, item, ttl);
                         response.AnswerRecords.Add(record);
                         this.logger.LogInformation(record.ToString());
                     }
-                    else
-                    {
-                        var localhost = System.Net.Dns.GetHostName();
-                        var addresses = await System.Net.Dns.GetHostAddressesAsync(localhost);
-                        var ttl = TimeSpan.FromMinutes(1d);
-
-                        foreach (var item in addresses)
-                        {
-                            if (item.AddressFamily == AddressFamily.InterNetwork)
-                            {
-                                var record = new IPAddressResourceRecord(question.Name, item, ttl);
-                                response.AnswerRecords.Add(record);
-                                this.logger.LogInformation(record.ToString());
-                            }
-                        }
-                    }
                 }
             }
 

+ 26 - 0
FastGithub.ReverseProxy/GithubReverseProxyOptions.cs

@@ -0,0 +1,26 @@
+using Yarp.ReverseProxy.Forwarder;
+
+namespace FastGithub.ReverseProxy
+{
+    /// <summary>
+    /// 反向代理选项
+    /// </summary>
+    [Options("ReverseProxy")]
+    public class GithubReverseProxyOptions
+    {
+        /// <summary>
+        /// 是否启用
+        /// </summary>
+        public bool Enable { get; set; } = true;
+
+        /// <summary>
+        /// 每个服务的最大代理连接数
+        /// </summary>
+        public int MaxConnectionsPerServer { get; set; } = int.MaxValue;
+
+        /// <summary>
+        /// 请求配置
+        /// </summary>
+        public ForwarderRequestConfig ForwarderRequestConfig { get; set; } = new();
+    }
+}

+ 1 - 1
FastGithub.ReverseProxy/LifetimeHttpHandler.cs

@@ -19,7 +19,7 @@ namespace FastGithub.ReverseProxy
         /// <summary>
         /// Token取消源
         /// </summary>
-        private readonly CancellationTokenSource tokenSource = new CancellationTokenSource();
+        private readonly CancellationTokenSource tokenSource = new();
 
         /// <summary>
         /// 具有生命周期的HttpHandler

+ 24 - 10
FastGithub.ReverseProxy/LifetimeHttpHandlerCleaner.cs

@@ -1,4 +1,5 @@
-using System;
+using Microsoft.Extensions.Logging;
+using System;
 using System.Collections.Concurrent;
 using System.Diagnostics;
 using System.Threading;
@@ -11,6 +12,8 @@ namespace FastGithub.ReverseProxy
     /// </summary>
     sealed class LifetimeHttpHandlerCleaner
     {
+        private readonly ILogger logger;
+
         /// <summary>
         /// 当前监视生命周期的记录的数量
         /// </summary>
@@ -27,6 +30,15 @@ namespace FastGithub.ReverseProxy
         /// </summary>
         public TimeSpan CleanupInterval { get; set; } = TimeSpan.FromSeconds(10d);
 
+        /// <summary>
+        /// LifetimeHttpHandler清理器
+        /// </summary>
+        /// <param name="logger"></param>
+        public LifetimeHttpHandlerCleaner(ILogger logger)
+        {
+            this.logger = logger;
+        }
+
         /// <summary>
         /// 添加要清除的httpHandler
         /// </summary>
@@ -52,18 +64,16 @@ namespace FastGithub.ReverseProxy
             {
                 while (true)
                 {
-                    await Task
-                        .Delay(this.CleanupInterval)
-                        .ConfigureAwait(false);
-
+                    await Task.Delay(this.CleanupInterval);
                     if (this.Cleanup() == true)
                     {
                         break;
                     }
                 }
             }
-            catch (Exception)
+            catch (Exception ex)
             {
+                this.logger.LogError(ex, "清理HttpMessageHandler出现不可预期的异常");
                 // 这是应该不可能发生的
             }
         }
@@ -76,6 +86,8 @@ namespace FastGithub.ReverseProxy
         private bool Cleanup()
         {
             var cleanCount = this.trackingEntries.Count;
+            this.logger.LogTrace($"尝试清理{cleanCount}条HttpMessageHandler");
+
             for (var i = 0; i < cleanCount; i++)
             {
                 this.trackingEntries.TryDequeue(out var entry);
@@ -87,12 +99,14 @@ namespace FastGithub.ReverseProxy
                     continue;
                 }
 
+                this.logger.LogTrace($"释放了{entry.GetHashCode()}@HttpMessageHandler");
                 entry.Dispose();
                 if (Interlocked.Decrement(ref this.trackingEntryCount) == 0)
                 {
                     return true;
                 }
             }
+
             return false;
         }
 
@@ -116,10 +130,7 @@ namespace FastGithub.ReverseProxy
             /// 获取是否可以释放资源
             /// </summary>
             /// <returns></returns>
-            public bool CanDispose
-            {
-                get => this.weakReference.IsAlive == false;
-            }
+            public bool CanDispose => this.weakReference.IsAlive == false;
 
             /// <summary>
             /// 监视生命周期的记录
@@ -131,6 +142,9 @@ namespace FastGithub.ReverseProxy
                 this.weakReference = new WeakReference(handler);
             }
 
+            /// <summary>
+            /// 释放资源
+            /// </summary>
             public void Dispose()
             {
                 try

+ 15 - 5
FastGithub.ReverseProxy/NoneSniHttpClientFactory.cs

@@ -1,6 +1,7 @@
 using FastGithub.Scanner;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
 using System;
 using System.Net.Http;
 using System.Net.Security;
@@ -15,6 +16,7 @@ namespace FastGithub.ReverseProxy
     sealed class NoneSniHttpClientFactory
     {
         private readonly IGithubScanResults githubScanResults;
+        private readonly IOptionsMonitor<GithubReverseProxyOptions> options;
         private readonly ILogger<NoneSniHttpClientFactory> logger;
 
         /// <summary>
@@ -25,12 +27,12 @@ namespace FastGithub.ReverseProxy
         /// <summary>
         /// 具有生命周期的httpHandler延时创建对象
         /// </summary>
-        private Lazy<LifetimeHttpHandler> lifeTimeHttpHandlerLazy;
+        private volatile Lazy<LifetimeHttpHandler> lifeTimeHttpHandlerLazy;
 
         /// <summary>
         /// HttpHandler清理器
         /// </summary>
-        private readonly LifetimeHttpHandlerCleaner httpHandlerCleaner = new LifetimeHttpHandlerCleaner();
+        private readonly LifetimeHttpHandlerCleaner httpHandlerCleaner;
 
 
         /// <summary>
@@ -39,11 +41,14 @@ namespace FastGithub.ReverseProxy
         /// <param name="githubScanResults"></param>
         public NoneSniHttpClientFactory(
             IGithubScanResults githubScanResults,
+            IOptionsMonitor<GithubReverseProxyOptions> options,
             ILogger<NoneSniHttpClientFactory> logger)
         {
             this.githubScanResults = githubScanResults;
+            this.options = options;
             this.logger = logger;
             this.lifeTimeHttpHandlerLazy = new Lazy<LifetimeHttpHandler>(this.CreateHttpHandler, true);
+            this.httpHandlerCleaner = new LifetimeHttpHandlerCleaner(logger);
         }
 
         /// <summary>
@@ -53,7 +58,7 @@ namespace FastGithub.ReverseProxy
         public HttpMessageInvoker CreateHttpClient()
         {
             var handler = this.lifeTimeHttpHandlerLazy.Value;
-            return new HttpMessageInvoker(handler, disposeHandler: false);
+            return new HttpMessageInvoker(handler);
         }
 
         /// <summary>
@@ -67,6 +72,7 @@ namespace FastGithub.ReverseProxy
                 Proxy = null,
                 UseProxy = false,
                 AllowAutoRedirect = false,
+                MaxConnectionsPerServer = this.options.CurrentValue.MaxConnectionsPerServer,
                 ConnectCallback = async (ctx, ct) =>
                 {
                     var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
@@ -77,8 +83,12 @@ namespace FastGithub.ReverseProxy
                         return stream;
                     }
 
-                    var sslStream = new SslStream(stream, leaveInnerStreamOpen: false, delegate { return true; });
-                    await sslStream.AuthenticateAsClientAsync(string.Empty, null, false);
+                    var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
+                    await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
+                    {
+                        TargetHost = string.Empty,
+                        RemoteCertificateValidationCallback = delegate { return true; }
+                    }, ct);
                     return sslStream;
                 }
             };

+ 5 - 3
FastGithub.ReverseProxy/ReverseProxyApplicationBuilderExtensions.cs

@@ -24,12 +24,13 @@ namespace FastGithub
         {
             var httpForwarder = app.ApplicationServices.GetRequiredService<IHttpForwarder>();
             var httpClientFactory = app.ApplicationServices.GetRequiredService<NoneSniHttpClientFactory>();
-            var options = app.ApplicationServices.GetRequiredService<IOptionsMonitor<GithubLookupFactoryOptions>>();
+            var lookupOptions = app.ApplicationServices.GetRequiredService<IOptionsMonitor<GithubLookupFactoryOptions>>();
+            var options = app.ApplicationServices.GetRequiredService<IOptionsMonitor<GithubReverseProxyOptions>>();
 
             app.Use(next => async context =>
             {
                 var host = context.Request.Host.Host;
-                if (options.CurrentValue.Domains.Contains(host) == false)
+                if (lookupOptions.CurrentValue.Domains.Contains(host) == false)
                 {
                     await context.Response.WriteAsJsonAsync(new { message = $"不支持以{host}访问" });
                 }
@@ -38,7 +39,8 @@ namespace FastGithub
                     var port = context.Request.Host.Port ?? 443;
                     var destinationPrefix = $"http://{host}:{port}/";
                     var httpClient = httpClientFactory.CreateHttpClient();
-                    await httpForwarder.SendAsync(context, destinationPrefix, httpClient);
+                    var requestConfig = options.CurrentValue.ForwarderRequestConfig;
+                    await httpForwarder.SendAsync(context, destinationPrefix, httpClient, requestConfig);
                 }
             });
 

+ 3 - 1
FastGithub.Scanner/GithubDnsHttpHandler.cs

@@ -39,7 +39,9 @@ namespace FastGithub.Scanner
                 {
                     var builder = new UriBuilder(uri)
                     {
-                        Host = address.ToString()
+                        Scheme = Uri.UriSchemeHttp,
+                        Host = address.ToString(),
+                        Port = 443
                     };
                     request.RequestUri = builder.Uri;
                     request.Headers.Host = uri.Host;

+ 2 - 2
FastGithub.Scanner/GithubLookupFactoryOptions.cs

@@ -1,4 +1,4 @@
-using System;
+using System.Collections.Generic;
 
 namespace FastGithub.Scanner
 {
@@ -11,6 +11,6 @@ namespace FastGithub.Scanner
         /// <summary>
         /// 反查的域名
         /// </summary>
-        public string[] Domains { get; set; } = Array.Empty<string>();
+        public HashSet<string> Domains { get; set; } = new();
     }
 }

+ 6 - 2
FastGithub.Scanner/ScannerServiceCollectionExtensions.cs

@@ -50,8 +50,12 @@ namespace FastGithub
                             return stream;
                         }
 
-                        var sslStream = new SslStream(stream, leaveInnerStreamOpen: false, delegate { return true; });
-                        await sslStream.AuthenticateAsClientAsync(string.Empty, null, false);
+                        var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
+                        await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
+                        {
+                            TargetHost = string.Empty,
+                            RemoteCertificateValidationCallback = delegate { return true; }
+                        }, ct);
                         return sslStream;
                     }
                 });

+ 8 - 2
FastGithub/appsettings.json

@@ -2,8 +2,14 @@
   "Dns": {
     "UpStream": "114.114.114.114", // 上游dns
     "GithubTTL": "00:10:00", // github相关域名解析结果的存活时长
-    "SetToLocalMachine": true, // 是否设置本机使用此dns(仅支持windows)
-    "UseReverseProxy": true // 是否使用反向代理访问github
+    "SetToLocalMachine": true // 是否设置本机使用此dns(仅支持windows)    
+  },
+  "ReverseProxy": {
+    "Enable": true, // 是否使用反向代理访问github,
+    "MaxConnectionsPerServer": 100, // 代理最大连接数
+    "ForwarderRequestConfig": {
+      "Timeout": "00:02:00" // 代理超时时间
+    }
   },
   "Lookup": { // ip查找     
     "IPAddressComProvider": {