From 634e10f16d93894776ced0e140077189bdfeaf58 Mon Sep 17 00:00:00 2001 From: "Gui.H" Date: Sun, 8 May 2022 22:04:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0Hosting=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastTunnel.Hosting/FastTunnel.Hosting.csproj | 18 +++++ .../FastTunnelHostingStartup.cs | 39 ++++++++++ .../ClientCertBufferingFeature.cs | 76 ------------------- FastTunnel.Server/FastTunnel.Server.csproj | 2 +- FastTunnel.Server/Program.cs | 12 +-- FastTunnel.Server/Startup.cs | 13 +--- FastTunnel.Server/appsettings.json | 5 +- 7 files changed, 65 insertions(+), 100 deletions(-) create mode 100644 FastTunnel.Hosting/FastTunnel.Hosting.csproj create mode 100644 FastTunnel.Hosting/FastTunnelHostingStartup.cs delete mode 100644 FastTunnel.Server/ClientCertBufferingFeature.cs diff --git a/FastTunnel.Hosting/FastTunnel.Hosting.csproj b/FastTunnel.Hosting/FastTunnel.Hosting.csproj new file mode 100644 index 0000000..fb436fe --- /dev/null +++ b/FastTunnel.Hosting/FastTunnel.Hosting.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + enable + + + + + + + + + + + + diff --git a/FastTunnel.Hosting/FastTunnelHostingStartup.cs b/FastTunnel.Hosting/FastTunnelHostingStartup.cs new file mode 100644 index 0000000..a0ca45a --- /dev/null +++ b/FastTunnel.Hosting/FastTunnelHostingStartup.cs @@ -0,0 +1,39 @@ +// Licensed under the Apache License, Version 2.0 (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// https://github.com/FastTunnel/FastTunnel/edit/v2/LICENSE +// Copyright (c) 2019 Gui.H + +using FastTunnel.Hosting; +using Microsoft.AspNetCore.Hosting; +using FastTunnel.Core.Extensions; +using Microsoft.Extensions.Configuration; + +[assembly: HostingStartup(typeof(FastTunnelHostingStartup))] + +namespace FastTunnel.Hosting; + +public class FastTunnelHostingStartup : IHostingStartup +{ + public void Configure(IWebHostBuilder builder) + { + builder.ConfigureServices((webHostBuilderContext, services) => + { + services.AddFastTunnelServer(webHostBuilderContext.Configuration.GetSection("FastTunnel")); + }); + + builder.UseKestrel((context, options) => + { + var basePort = context.Configuration.GetValue("FastTunnel:BASE_PORT") ?? 1270; + options.ListenAnyIP(basePort, listenOptions => + { + listenOptions.UseConnectionFastTunnel(); + }); + }); + + builder.Configure((webHostBuilderContext, app) => + { + app.UseFastTunnelServer(); + }); + } +} diff --git a/FastTunnel.Server/ClientCertBufferingFeature.cs b/FastTunnel.Server/ClientCertBufferingFeature.cs deleted file mode 100644 index f056626..0000000 --- a/FastTunnel.Server/ClientCertBufferingFeature.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Connections.Features; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.WebUtilities; - -namespace FastTunnel.Server; - -internal static class ClientCertBufferingExtensions -{ - // Buffers HTTP/1.x request bodies received over TLS (https) if a client certificate needs to be negotiated. - // This avoids the issue where POST data is received during the certificate negotiation: - // InvalidOperationException: Received data during renegotiation. - public static IApplicationBuilder UseClientCertBuffering(this IApplicationBuilder builder) - { - return builder.Use((context, next) => - { - var tlsFeature = context.Features.Get(); - var bodyFeature = context.Features.Get(); - var connectionItems = context.Features.Get(); - - // Look for TLS connections that don't already have a client cert, and requests that could have a body. - if (tlsFeature != null && tlsFeature.ClientCertificate == null && bodyFeature.CanHaveBody - && !connectionItems.Items.TryGetValue("tls.clientcert.negotiated", out var _)) - { - context.Features.Set(new ClientCertBufferingFeature(tlsFeature, context)); - } - - return next(context); - }); - } -} - -internal class ClientCertBufferingFeature : ITlsConnectionFeature -{ - private readonly ITlsConnectionFeature _tlsFeature; - private readonly HttpContext _context; - - public ClientCertBufferingFeature(ITlsConnectionFeature tlsFeature, HttpContext context) - { - _tlsFeature = tlsFeature; - _context = context; - } - - public X509Certificate2 ClientCertificate - { - get => _tlsFeature.ClientCertificate; - set => _tlsFeature.ClientCertificate = value; - } - - public async Task GetClientCertificateAsync(CancellationToken cancellationToken) - { - // Note: This doesn't set its own size limit for the buffering or draining, it relies on the server's - // 30mb default request size limit. - if (!_context.Request.Body.CanSeek) - { - _context.Request.EnableBuffering(); - } - - var body = _context.Request.Body; - await body.DrainAsync(cancellationToken); - body.Position = 0; - - // Negative caching, prevent buffering on future requests even if the client does not give a cert when prompted. - var connectionItems = _context.Features.Get(); - connectionItems.Items["tls.clientcert.negotiated"] = true; - - return await _tlsFeature.GetClientCertificateAsync(cancellationToken); - } -} diff --git a/FastTunnel.Server/FastTunnel.Server.csproj b/FastTunnel.Server/FastTunnel.Server.csproj index 21d4e78..aaf9c23 100644 --- a/FastTunnel.Server/FastTunnel.Server.csproj +++ b/FastTunnel.Server/FastTunnel.Server.csproj @@ -36,7 +36,7 @@ - + diff --git a/FastTunnel.Server/Program.cs b/FastTunnel.Server/Program.cs index def3984..4c08d96 100644 --- a/FastTunnel.Server/Program.cs +++ b/FastTunnel.Server/Program.cs @@ -53,6 +53,9 @@ public class Program .WriteTo.Console()) .ConfigureWebHost(webHostBuilder => { + webHostBuilder.UseKestrel(); + webHostBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "FastTunnel.Hosting"); + webHostBuilder.ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; @@ -60,15 +63,6 @@ public class Program .AddJsonFile($"config/appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); }); - webHostBuilder.UseKestrel((context, options) => - { - var basePort = context.Configuration.GetValue("BASE_PORT") ?? 1270; - options.ListenAnyIP(basePort, listenOptions => - { - listenOptions.UseConnectionFastTunnel(); - }); - }); - webHostBuilder.UseStartup(); }); } diff --git a/FastTunnel.Server/Startup.cs b/FastTunnel.Server/Startup.cs index 367a708..8619b23 100644 --- a/FastTunnel.Server/Startup.cs +++ b/FastTunnel.Server/Startup.cs @@ -80,10 +80,6 @@ public class Startup c.SwaggerDoc("v2", new OpenApiInfo { Title = "FastTunel.Api", Version = "v2" }); }); #endif - - // -------------------FastTunnel STEP1 OF 3------------------ - services.AddFastTunnelServer(Configuration.GetSection("FastTunnel")); - // -------------------FastTunnel STEP1 END------------------- } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -98,10 +94,6 @@ public class Startup #endif } - // -------------------FastTunnel STEP2 OF 3------------------ - app.UseFastTunnelServer(); - // -------------------FastTunnel STEP2 END------------------- - app.UseRouting(); // --------------------- Custom UI ---------------- @@ -113,9 +105,6 @@ public class Startup app.UseEndpoints(endpoints => { endpoints.MapControllers(); - // -------------------FastTunnel STEP3 OF 3------------------ - //endpoints.MapFastTunnelServer(); - // -------------------FastTunnel STEP3 END------------------- - }); + }); } } diff --git a/FastTunnel.Server/appsettings.json b/FastTunnel.Server/appsettings.json index 1e0b4e5..36aa268 100644 --- a/FastTunnel.Server/appsettings.json +++ b/FastTunnel.Server/appsettings.json @@ -8,11 +8,12 @@ } }, "AllowedHosts": "*", - // Http&客户端通讯端口 - "BASE_PORT": 1270, + // 是否启用文件日志输出 "EnableFileLog": false, "FastTunnel": { + // Http&客户端通讯端口 + "BASE_PORT": 1270, // 可选,绑定的根域名, // 客户端需配置SubDomain,实现 ${SubDomain}.${WebDomain}访问内网的站点,注意:需要通过域名访问网站时必选。 "WebDomain": "test.cc",