using System; using System.Net.Http; using System.Net.Security; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace FastGithub.ReverseProxy { /// /// YARP的HttpClientHandler /// class HttpClientHanlder : DelegatingHandler { private readonly DomainResolver domainResolver; /// /// YARP的HttpClientHandler /// /// public HttpClientHanlder(DomainResolver domainResolver) { this.domainResolver = domainResolver; this.InnerHandler = CreateSocketsHttpHandler(); } /// /// 创建转发代理的httpHandler /// /// private static SocketsHttpHandler CreateSocketsHttpHandler() { return new SocketsHttpHandler { Proxy = null, UseProxy = false, AllowAutoRedirect = false, 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); var sniContext = ctx.InitialRequestMessage.GetSniContext(); if (sniContext.IsHttps == false) { return stream; } var sslStream = new SslStream(stream, leaveInnerStreamOpen: false); await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions { TargetHost = sniContext.TlsSniValue, RemoteCertificateValidationCallback = delegate { return true; } }, ct); return sslStream; } }; } /// /// 替换域名为ip /// /// /// /// protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { var uri = request.RequestUri; if (uri != null && uri.HostNameType == UriHostNameType.Dns) { var address = await this.domainResolver.ResolveAsync(uri.Host, cancellationToken); var builder = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp, Host = address.ToString(), }; request.RequestUri = builder.Uri; request.Headers.Host = uri.Host; } return await base.SendAsync(request, cancellationToken); } } }