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",