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; using System.Net.Sockets; namespace FastGithub.ReverseProxy { /// /// 禁用tls sni的HttpClient工厂 /// [Service(ServiceLifetime.Singleton)] sealed class NoneSniHttpClientFactory { private readonly IGithubScanResults githubScanResults; private readonly IOptionsMonitor options; private readonly ILogger logger; /// /// 生命周期 /// private readonly TimeSpan lifeTime = TimeSpan.FromMinutes(2d); /// /// 具有生命周期的httpHandler延时创建对象 /// private volatile Lazy lifeTimeHttpHandlerLazy; /// /// HttpHandler清理器 /// private readonly LifetimeHttpHandlerCleaner httpHandlerCleaner; /// /// 禁用tls sni的HttpClient工厂 /// /// public NoneSniHttpClientFactory( IGithubScanResults githubScanResults, IOptionsMonitor options, ILogger logger) { this.githubScanResults = githubScanResults; this.options = options; this.logger = logger; this.lifeTimeHttpHandlerLazy = new Lazy(this.CreateHttpHandler, true); this.httpHandlerCleaner = new LifetimeHttpHandlerCleaner(logger); } /// /// 创建HttpClient /// /// public HttpMessageInvoker CreateHttpClient() { var handler = this.lifeTimeHttpHandlerLazy.Value; return new HttpMessageInvoker(handler); } /// /// 创建具有生命周期控制的httpHandler /// /// private LifetimeHttpHandler CreateHttpHandler() { var noneSniHandler = new SocketsHttpHandler { Proxy = null, UseProxy = false, AllowAutoRedirect = false, MaxConnectionsPerServer = this.options.CurrentValue.MaxConnectionsPerServer, ConnectCallback = async (ctx, ct) => { var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(ctx.DnsEndPoint, ct); var stream = new NetworkStream(socket, ownsSocket: true); if (ctx.InitialRequestMessage.Headers.Host == null) { return stream; } var sslStream = new SslStream(stream, leaveInnerStreamOpen: false); await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions { TargetHost = string.Empty, RemoteCertificateValidationCallback = delegate { return true; } }, ct); return sslStream; } }; var dnsHandler = new GithubDnsHttpHandler(this.githubScanResults, noneSniHandler, this.logger); return new LifetimeHttpHandler(dnsHandler, this.lifeTime, this.OnHttpHandlerDeactivate); } /// /// 当有httpHandler失效时 /// /// httpHandler private void OnHttpHandlerDeactivate(LifetimeHttpHandler handler) { // 切换激活状态的记录的实例 this.lifeTimeHttpHandlerLazy = new Lazy(this.CreateHttpHandler, true); this.httpHandlerCleaner.Add(handler); } } }