HttpClientHanlder.cs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using System;
  2. using System.Net.Http;
  3. using System.Net.Security;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace FastGithub.ReverseProxy
  8. {
  9. /// <summary>
  10. /// YARP的HttpClientHandler
  11. /// </summary>
  12. class HttpClientHanlder : DelegatingHandler
  13. {
  14. private readonly DomainResolver domainResolver;
  15. /// <summary>
  16. /// YARP的HttpClientHandler
  17. /// </summary>
  18. /// <param name="domainResolver"></param>
  19. public HttpClientHanlder(DomainResolver domainResolver)
  20. {
  21. this.domainResolver = domainResolver;
  22. this.InnerHandler = CreateSocketsHttpHandler();
  23. }
  24. /// <summary>
  25. /// 创建转发代理的httpHandler
  26. /// </summary>
  27. /// <returns></returns>
  28. private static SocketsHttpHandler CreateSocketsHttpHandler()
  29. {
  30. return new SocketsHttpHandler
  31. {
  32. Proxy = null,
  33. UseProxy = false,
  34. AllowAutoRedirect = false,
  35. ConnectCallback = async (ctx, ct) =>
  36. {
  37. var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
  38. await socket.ConnectAsync(ctx.DnsEndPoint, ct);
  39. var stream = new NetworkStream(socket, ownsSocket: true);
  40. var sniContext = ctx.InitialRequestMessage.GetSniContext();
  41. if (sniContext.IsHttps == false)
  42. {
  43. return stream;
  44. }
  45. var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
  46. await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
  47. {
  48. TargetHost = sniContext.TlsSniValue,
  49. RemoteCertificateValidationCallback = delegate { return true; }
  50. }, ct);
  51. return sslStream;
  52. }
  53. };
  54. }
  55. /// <summary>
  56. /// 替换域名为ip
  57. /// </summary>
  58. /// <param name="request"></param>
  59. /// <param name="cancellationToken"></param>
  60. /// <returns></returns>
  61. protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  62. {
  63. var uri = request.RequestUri;
  64. if (uri != null && uri.HostNameType == UriHostNameType.Dns)
  65. {
  66. var address = await this.domainResolver.ResolveAsync(uri.Host, cancellationToken);
  67. var builder = new UriBuilder(uri)
  68. {
  69. Scheme = Uri.UriSchemeHttp,
  70. Host = address.ToString(),
  71. };
  72. request.RequestUri = builder.Uri;
  73. request.Headers.Host = uri.Host;
  74. }
  75. return await base.SendAsync(request, cancellationToken);
  76. }
  77. }
  78. }