mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-21 17:13:09 +08:00
🐛 fix Accelerator
This commit is contained in:
+28
-24
@@ -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;
|
||||
//}
|
||||
}
|
||||
|
||||
+2
-2
@@ -124,8 +124,8 @@ public static partial class ServiceCollectionExtensions
|
||||
.AddSingleton<TunnelMiddleware>()
|
||||
|
||||
// tls
|
||||
.AddSingleton<TlsInvadeMiddleware>()
|
||||
.AddSingleton<TlsRestoreMiddleware>()
|
||||
//.AddSingleton<TlsInvadeMiddleware>()
|
||||
//.AddSingleton<TlsRestoreMiddleware>()
|
||||
|
||||
//http
|
||||
.AddSingleton<HttpLocalRequestMiddleware>()
|
||||
|
||||
+8
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
}
|
||||
+54
-32
@@ -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;
|
||||
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+2
-2
@@ -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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -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)
|
||||
{
|
||||
|
||||
-10
@@ -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);
|
||||
// });
|
||||
//});
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -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
|
||||
|
||||
|
||||
+13
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user