🐛 fix Accelerator

This commit is contained in:
Aigio Liu
2023-07-25 14:20:29 +08:00
parent 1c9e3c14ab
commit 68da00b9cd
11 changed files with 120 additions and 82 deletions
@@ -1,4 +1,6 @@
// ReSharper disable once CheckNamespace
using System.Security.Authentication;
namespace Microsoft.Extensions.DependencyInjection;
static partial class ListenOptionsExtensions
@@ -38,33 +40,35 @@ static partial class ListenOptionsExtensions
public static ListenOptions UseTls(this ListenOptions listen)
{
var certService = listen.ApplicationServices.GetRequiredService<CertService>();
//certService.CreateCaCertIfNotExists();
//certService.InstallAndTrustCaCert();
return listen.UseTls(https =>
listen.Use(next => context => TlsInvadeMiddleware.InvokeAsync(next, context));
listen.UseHttps(new TlsHandshakeCallbackOptions
{
https.ServerCertificateSelector = (ctx, domain) =>
OnConnection = ctx =>
{
var cert = certService.GetOrCreateServerCert(domain);
return cert;
};
var domain = ctx.ClientHelloInfo.ServerName;
var o = new SslServerAuthenticationOptions
{
ServerCertificate = certService.GetOrCreateServerCert(domain),
};
return ValueTask.FromResult(o);
},
});
}
/// <summary>
/// 使用 Tls 中间件
/// </summary>
/// <param name="listen"></param>
/// <param name="configureOptions">https配置</param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static ListenOptions UseTls(this ListenOptions listen, Action<HttpsConnectionAdapterOptions> configureOptions)
{
var invadeMiddleware = listen.ApplicationServices.GetRequiredService<TlsInvadeMiddleware>();
var restoreMiddleware = listen.ApplicationServices.GetRequiredService<TlsRestoreMiddleware>();
listen.Use(next => context => invadeMiddleware.InvokeAsync(next, context));
listen.UseHttps(configureOptions);
listen.Use(next => context => restoreMiddleware.InvokeAsync(next, context));
listen.Use(next => context => TlsRestoreMiddleware.InvokeAsync(next, context));
return listen;
}
///// <summary>
///// 使用 Tls 中间件
///// </summary>
///// <param name="listen"></param>
///// <param name="configureOptions">https配置</param>
///// <returns></returns>
//[MethodImpl(MethodImplOptions.AggressiveInlining)]
//static ListenOptions UseTls(this ListenOptions listen, Action<HttpsConnectionAdapterOptions> configureOptions)
//{
// listen.Use(next => context => TlsInvadeMiddleware.InvokeAsync(next, context));
// listen.UseHttps(configureOptions);
// listen.Use(next => context => TlsRestoreMiddleware.InvokeAsync(next, context));
// return listen;
//}
}
@@ -124,8 +124,8 @@ public static partial class ServiceCollectionExtensions
.AddSingleton<TunnelMiddleware>()
// tls
.AddSingleton<TlsInvadeMiddleware>()
.AddSingleton<TlsRestoreMiddleware>()
//.AddSingleton<TlsInvadeMiddleware>()
//.AddSingleton<TlsRestoreMiddleware>()
//http
.AddSingleton<HttpLocalRequestMiddleware>()
@@ -69,15 +69,19 @@ sealed class CertService
var key = $"{nameof(CertService)}:{domain}";
return serverCertCache.GetOrCreate(key, GetOrCreateCert);
// 生成域名的1年证书
// 生成域名的 1 年证书
X509Certificate2 GetOrCreateCert(ICacheEntry entry)
{
var domains = GetDomains(domain).Distinct();
var validFrom = DateTime.Today.AddDays(-1);
var validTo = DateTime.Today.AddYears(1);
DateTimeOffset today = DateTime.Today;
var validFrom = today.AddDays(-1);
var validTo = today.AddYears(1);
entry.SetAbsoluteExpiration(validTo);
return CertGenerator.GenerateByCaPfx(domains, validFrom, validTo, CaPfxFilePath);
using var serverCert = CertGenerator.GenerateByCaPfx(domains, validFrom, validTo, CaPfxFilePath);
var serverCertPfx = serverCert.Export(X509ContentType.Pfx);
// 将生成的证书导出后重新创建一个
return new X509Certificate2(serverCertPfx);
}
}
@@ -9,12 +9,12 @@ sealed class FakeTlsConnectionFeature : ITlsConnectionFeature
public X509Certificate2? ClientCertificate
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
get => default;
set { }
}
public Task<X509Certificate2?> GetClientCertificateAsync(CancellationToken cancellationToken)
{
throw new NotImplementedException();
return Task.FromResult<X509Certificate2?>(default);
}
}
@@ -9,8 +9,6 @@ namespace BD.WTTS.Services.Implementation;
sealed class HttpProxyMiddleware
{
readonly HttpParser<HttpRequestHandler> httpParser = new();
readonly byte[] http200 = Encoding.ASCII.GetBytes("HTTP/1.1 200 Connection Established\r\n\r\n");
readonly byte[] http400 = Encoding.ASCII.GetBytes("HTTP/1.1 400 Bad Request\r\n\r\n");
/// <summary>
/// 执行中间件
@@ -20,55 +18,79 @@ sealed class HttpProxyMiddleware
/// <returns></returns>
public async Task InvokeAsync(ConnectionDelegate next, ConnectionContext context)
{
var result = await context.Transport.Input.ReadAsync();
var httpRequest = GetHttpRequestHandler(result, out var consumed);
// 协议错误
if (consumed == 0L)
var input = context.Transport.Input;
var output = context.Transport.Output;
var request = new HttpRequestHandler();
while (context.ConnectionClosed.IsCancellationRequested == false)
{
await context.Transport.Output.WriteAsync(http400, context.ConnectionClosed);
}
else
{
// 隧道代理连接请求
if (httpRequest.ProxyProtocol == ProxyProtocol.TunnelProxy)
var result = await input.ReadAsync();
if (result.IsCanceled)
{
var position = result.Buffer.GetPosition(consumed);
context.Transport.Input.AdvanceTo(position);
await context.Transport.Output.WriteAsync(http200, context.ConnectionClosed);
}
else
{
var position = result.Buffer.Start;
context.Transport.Input.AdvanceTo(position);
break;
}
context.Features.Set<IHttpProxyFeature>(httpRequest);
await next(context);
try
{
if (ParseRequest(result, request, out var consumed))
{
if (request.ProxyProtocol == ProxyProtocol.TunnelProxy)
{
input.AdvanceTo(consumed);
await output.WriteAsync(
"HTTP/1.1 400 Bad Request\r\n\r\n"u8.ToArray(),
context.ConnectionClosed);
}
else
{
input.AdvanceTo(result.Buffer.Start);
}
context.Features.Set<IHttpProxyFeature>(request);
await next(context);
break;
}
else
{
input.AdvanceTo(result.Buffer.Start, result.Buffer.End);
}
if (result.IsCompleted)
{
break;
}
}
catch (Exception)
{
await output.WriteAsync(
"HTTP/1.1 200 Connection Established\r\n\r\n"u8.ToArray(),
context.ConnectionClosed);
break;
}
}
}
HttpRequestHandler GetHttpRequestHandler(ReadResult result, out long consumed)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
bool ParseRequest(ReadResult result, HttpRequestHandler request, out SequencePosition consumed)
{
var handler = new HttpRequestHandler();
var reader = new SequenceReader<byte>(result.Buffer);
if (httpParser.ParseRequestLine(handler, ref reader) &&
httpParser.ParseHeaders(handler, ref reader))
if (httpParser.ParseRequestLine(request, ref reader) &&
httpParser.ParseHeaders(request, ref reader))
{
consumed = reader.Consumed;
consumed = reader.Position;
return true;
}
else
{
consumed = 0L;
consumed = default;
return false;
}
return handler;
}
/// <summary>
/// 代理请求处理器
/// </summary>
private class HttpRequestHandler : IHttpRequestLineHandler, IHttpHeadersHandler, IHttpProxyFeature
sealed class HttpRequestHandler : IHttpRequestLineHandler, IHttpHeadersHandler, IHttpProxyFeature
{
private AspNetCoreHttpMethod method;
@@ -6,7 +6,7 @@ namespace BD.WTTS.Services.Implementation;
/// <summary>
/// Https 入侵中间件
/// </summary>
sealed class TlsInvadeMiddleware
static class TlsInvadeMiddleware
{
/// <summary>
/// 执行中间件
@@ -14,7 +14,7 @@ sealed class TlsInvadeMiddleware
/// <param name="next"></param>
/// <param name="context"></param>
/// <returns></returns>
public async Task InvokeAsync(ConnectionDelegate next, ConnectionContext context)
public static async Task InvokeAsync(ConnectionDelegate next, ConnectionContext context)
{
// 连接不是 tls
if (await IsTlsConnectionAsync(context) == false)
@@ -6,7 +6,7 @@ namespace BD.WTTS.Services.Implementation;
/// <summary>
/// Https 恢复中间件
/// </summary>
sealed class TlsRestoreMiddleware
static class TlsRestoreMiddleware
{
/// <summary>
/// 执行中间件
@@ -14,7 +14,7 @@ sealed class TlsRestoreMiddleware
/// <param name="next"></param>
/// <param name="context"></param>
/// <returns></returns>
public async Task InvokeAsync(ConnectionDelegate next, ConnectionContext context)
public static async Task InvokeAsync(ConnectionDelegate next, ConnectionContext context)
{
if (context.Features.Get<ITlsConnectionFeature>() == FakeTlsConnectionFeature.Instance)
{
@@ -21,7 +21,7 @@ sealed class LazyReverseProxyServiceImpl : IReverseProxyService
public void Dispose() => impl().Dispose();
public FlowStatistics? GetFlowStatistics() => impl().GetFlowStatistics();
public byte[]? GetFlowStatistics_Bytes() => impl().GetFlowStatistics_Bytes();
public async Task<StartProxyResult> StartProxyAsync(byte[] reverseProxySettings)
{
@@ -45,16 +45,6 @@ partial class YarpReverseProxyServiceImpl
app.UseRequestLogging();
app.UseHttpReverseProxy();
//app.UseRouting();
app.DisableRequestLogging();
//app.UseEndpoints(endpoint =>
//{
// endpoint.MapGet("/flowStatistics", context =>
// {
// var flowStatistics = context.RequestServices.GetRequiredService<IFlowAnalyzer>().GetFlowStatistics();
// return context.Response.WriteAsJsonAsync(flowStatistics);
// });
//});
}
}
@@ -141,7 +141,13 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
app = null;
}
public FlowStatistics? GetFlowStatistics() => app?.Services.GetService<IFlowAnalyzer>()?.GetFlowStatistics();
public byte[]? GetFlowStatistics_Bytes()
{
var flowAnalyzer = app?.Services.GetService<IFlowAnalyzer>();
var flowStatistics = flowAnalyzer?.GetFlowStatistics();
var bytes = Serializable.SMP2(flowStatistics);
return bytes;
}
// IDisposable
@@ -14,5 +14,17 @@ partial interface IReverseProxyService
/// 获取流量统计信息
/// </summary>
/// <returns></returns>
FlowStatistics? GetFlowStatistics();
byte[]? GetFlowStatistics_Bytes();
}
public static partial class ReverseProxyServiceExtensions
{
/// <inheritdoc cref="IReverseProxyService.GetFlowStatistics_Bytes"/>
public static FlowStatistics? GetFlowStatistics(this IReverseProxyService s)
{
var bytes = s.GetFlowStatistics_Bytes();
if (bytes == default) return default;
var flowStatistics = Serializable.DMP2<FlowStatistics>(bytes);
return flowStatistics;
}
}