diff --git a/FastGithub.ReverseProxy/HttpClient.cs b/FastGithub.ReverseProxy/HttpClient.cs
new file mode 100644
index 0000000..0e86e5c
--- /dev/null
+++ b/FastGithub.ReverseProxy/HttpClient.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FastGithub.ReverseProxy
+{
+ ///
+ /// YARP的HttpClient
+ ///
+ class HttpClient : HttpMessageInvoker
+ {
+ private readonly bool tlsSni;
+
+ ///
+ /// YARP的HttpClient
+ ///
+ ///
+ ///
+ ///
+ public HttpClient(HttpMessageHandler handler, bool disposeHandler, bool tlsSni) :
+ base(handler, disposeHandler)
+ {
+ this.tlsSni = tlsSni;
+ }
+
+ ///
+ /// 发送数据
+ ///
+ ///
+ ///
+ ///
+ public override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var isHttps = request.RequestUri?.Scheme == Uri.UriSchemeHttps;
+ request.SetSniContext(new SniContext(isHttps, this.tlsSni));
+ return base.SendAsync(request, cancellationToken);
+ }
+ }
+}
diff --git a/FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs b/FastGithub.ReverseProxy/HttpClientHanlder.cs
similarity index 75%
rename from FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs
rename to FastGithub.ReverseProxy/HttpClientHanlder.cs
index 7a8c898..c806768 100644
--- a/FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs
+++ b/FastGithub.ReverseProxy/HttpClientHanlder.cs
@@ -9,20 +9,20 @@ using System.Threading.Tasks;
namespace FastGithub.ReverseProxy
{
///
- /// 不发送NoSni的HttpClientHandler
+ /// YARP的HttpClientHandler
///
- class NoSniHttpClientHanlder : DelegatingHandler
+ class HttpClientHanlder : DelegatingHandler
{
private readonly DomainResolver domainResolver;
- private readonly ILogger logger;
+ private readonly ILogger logger;
///
- /// 不发送NoSni的HttpClientHandler
+ /// YARP的HttpClientHandler
///
///
- public NoSniHttpClientHanlder(
+ public HttpClientHanlder(
DomainResolver domainResolver,
- ILogger logger)
+ ILogger logger)
{
this.domainResolver = domainResolver;
this.logger = logger;
@@ -45,7 +45,8 @@ namespace FastGithub.ReverseProxy
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)
+ var sniContext = ctx.InitialRequestMessage.GetSniContext();
+ if (sniContext.IsHttps == false)
{
return stream;
}
@@ -53,7 +54,7 @@ namespace FastGithub.ReverseProxy
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
- TargetHost = string.Empty,
+ TargetHost = sniContext.TlsSniValue,
RemoteCertificateValidationCallback = delegate { return true; }
}, ct);
return sslStream;
@@ -74,16 +75,25 @@ namespace FastGithub.ReverseProxy
if (uri != null && uri.HostNameType == UriHostNameType.Dns)
{
var address = await this.domainResolver.ResolveAsync(uri.Host, cancellationToken);
- this.logger.LogInformation($"[{address}--NoSni->{uri.Host}]");
-
var builder = new UriBuilder(uri)
{
Scheme = Uri.UriSchemeHttp,
Host = address.ToString(),
- Port = 443
};
request.RequestUri = builder.Uri;
request.Headers.Host = uri.Host;
+
+ // 计算Sni
+ var context = request.GetSniContext();
+ if (context.IsHttps && context.TlsSni)
+ {
+ context.TlsSniValue = uri.Host;
+ this.logger.LogInformation($"[{address}--Sni->{uri.Host}]");
+ }
+ else
+ {
+ this.logger.LogInformation($"[{address}--NoSni->{uri.Host}]");
+ }
}
return await base.SendAsync(request, cancellationToken);
}
diff --git a/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs b/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
index 77e5b45..f3f27cb 100644
--- a/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
+++ b/FastGithub.ReverseProxy/ReverseProxyMiddleware.cs
@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
-using System.Net.Http;
using System.Threading.Tasks;
using Yarp.ReverseProxy.Forwarder;
@@ -13,21 +12,18 @@ namespace FastGithub.ReverseProxy
sealed class ReverseProxyMiddleware
{
private readonly IHttpForwarder httpForwarder;
- private readonly SniHttpClientHanlder sniHttpClientHanlder;
- private readonly NoSniHttpClientHanlder noSniHttpClientHanlder;
+ private readonly HttpClientHanlder httpClientHanlder;
private readonly FastGithubConfig fastGithubConfig;
private readonly ILogger logger;
public ReverseProxyMiddleware(
IHttpForwarder httpForwarder,
- SniHttpClientHanlder sniHttpClientHanlder,
- NoSniHttpClientHanlder noSniHttpClientHanlder,
+ HttpClientHanlder httpClientHanlder,
FastGithubConfig fastGithubConfig,
ILogger logger)
{
this.httpForwarder = httpForwarder;
- this.sniHttpClientHanlder = sniHttpClientHanlder;
- this.noSniHttpClientHanlder = noSniHttpClientHanlder;
+ this.httpClientHanlder = httpClientHanlder;
this.fastGithubConfig = fastGithubConfig;
this.logger = logger;
}
@@ -59,10 +55,7 @@ namespace FastGithub.ReverseProxy
{
var destinationPrefix = GetDestinationPrefix(host, domainConfig.Destination);
var requestConfig = new ForwarderRequestConfig { Timeout = domainConfig.Timeout };
-
- var httpClient = domainConfig.TlsSni
- ? new HttpMessageInvoker(this.sniHttpClientHanlder, disposeHandler: false)
- : new HttpMessageInvoker(this.noSniHttpClientHanlder, disposeHandler: false);
+ var httpClient = new HttpClient(this.httpClientHanlder, false, domainConfig.TlsSni);
var error = await httpForwarder.SendAsync(context, destinationPrefix, httpClient, requestConfig);
await ResponseErrorAsync(context, error);
diff --git a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
index 4f7c55e..15d6d11 100644
--- a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
+++ b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs
@@ -19,8 +19,7 @@ namespace FastGithub
.AddMemoryCache()
.AddHttpForwarder()
.AddSingleton()
- .AddTransient()
- .AddTransient()
+ .AddTransient()
.AddSingleton();
}
}
diff --git a/FastGithub.ReverseProxy/SniContext.cs b/FastGithub.ReverseProxy/SniContext.cs
new file mode 100644
index 0000000..8646ab7
--- /dev/null
+++ b/FastGithub.ReverseProxy/SniContext.cs
@@ -0,0 +1,34 @@
+namespace FastGithub.ReverseProxy
+{
+ ///
+ /// Sni上下文
+ ///
+ sealed class SniContext
+ {
+ ///
+ /// 获取请求是否为https
+ ///
+ public bool IsHttps { get; }
+
+ ///
+ /// 获取是否发送Sni
+ ///
+ public bool TlsSni { get; }
+
+ ///
+ /// Sni值
+ ///
+ public string TlsSniValue { get; set; } = string.Empty;
+
+ ///
+ /// Sni上下文
+ ///
+ ///
+ ///
+ public SniContext(bool isHttps, bool tlsSni)
+ {
+ this.IsHttps = isHttps;
+ this.TlsSni = tlsSni;
+ }
+ }
+}
diff --git a/FastGithub.ReverseProxy/SniContextExtensions.cs b/FastGithub.ReverseProxy/SniContextExtensions.cs
new file mode 100644
index 0000000..da9cb3d
--- /dev/null
+++ b/FastGithub.ReverseProxy/SniContextExtensions.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net.Http;
+
+namespace FastGithub.ReverseProxy
+{
+ ///
+ /// SniContext扩展
+ ///
+ static class SniContextExtensions
+ {
+ private static readonly HttpRequestOptionsKey key = new(nameof(SniContext));
+
+ ///
+ /// 设置SniContext
+ ///
+ ///
+ ///
+ public static void SetSniContext(this HttpRequestMessage httpRequestMessage, SniContext context)
+ {
+ httpRequestMessage.Options.Set(key, context);
+ }
+
+ ///
+ /// 获取SniContext
+ ///
+ ///
+ ///
+ public static SniContext GetSniContext(this HttpRequestMessage httpRequestMessage)
+ {
+ if (httpRequestMessage.Options.TryGetValue(key, out var value))
+ {
+ return value;
+ }
+ throw new InvalidOperationException($"请先调用{nameof(SetSniContext)}");
+ }
+ }
+}
diff --git a/FastGithub.ReverseProxy/SniHttpClientHanlder.cs b/FastGithub.ReverseProxy/SniHttpClientHanlder.cs
deleted file mode 100644
index 9893a22..0000000
--- a/FastGithub.ReverseProxy/SniHttpClientHanlder.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Microsoft.Extensions.Logging;
-using System;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace FastGithub.ReverseProxy
-{
- ///
- /// 携带Sni的的HttpClientHandler
- ///
- class SniHttpClientHanlder : DelegatingHandler
- {
- private readonly DomainResolver domainResolver;
- private readonly ILogger logger;
-
- ///
- /// 携带Sni的HttpClientHandler
- ///
- ///
- public SniHttpClientHanlder(
- DomainResolver domainResolver,
- ILogger logger)
- {
- this.domainResolver = domainResolver;
- this.logger = logger;
-
- this.InnerHandler = new SocketsHttpHandler
- {
- Proxy = null,
- UseProxy = false,
- AllowAutoRedirect = false,
- };
- }
-
- ///
- /// 替换域名为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);
- this.logger.LogInformation($"[{address}--Sni->{uri.Host}]");
-
- var builder = new UriBuilder(uri)
- {
- Host = address.ToString()
- };
- request.RequestUri = builder.Uri;
- request.Headers.Host = uri.Host;
- }
- return await base.SendAsync(request, cancellationToken);
- }
- }
-}