添加Hosting项目

This commit is contained in:
Gui.H 2022-05-08 22:04:53 +08:00
parent 593f12d925
commit 634e10f16d
7 changed files with 65 additions and 100 deletions

View File

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.0-preview.3.22175.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FastTunnel.Core\FastTunnel.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -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<int?>("FastTunnel:BASE_PORT") ?? 1270;
options.ListenAnyIP(basePort, listenOptions =>
{
listenOptions.UseConnectionFastTunnel();
});
});
builder.Configure((webHostBuilderContext, app) =>
{
app.UseFastTunnelServer();
});
}
}

View File

@ -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<ITlsConnectionFeature>();
var bodyFeature = context.Features.Get<IHttpRequestBodyDetectionFeature>();
var connectionItems = context.Features.Get<IConnectionItemsFeature>();
// 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<ITlsConnectionFeature>(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<X509Certificate2> 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<IConnectionItemsFeature>();
connectionItems.Items["tls.clientcert.negotiated"] = true;
return await _tlsFeature.GetClientCertificateAsync(cancellationToken);
}
}

View File

@ -36,7 +36,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FastTunnel.Api\FastTunnel.Api.csproj" /> <ProjectReference Include="..\FastTunnel.Api\FastTunnel.Api.csproj" />
<ProjectReference Include="..\FastTunnel.Core\FastTunnel.Core.csproj" /> <ProjectReference Include="..\FastTunnel.Hosting\FastTunnel.Hosting.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -53,6 +53,9 @@ public class Program
.WriteTo.Console()) .WriteTo.Console())
.ConfigureWebHost(webHostBuilder => .ConfigureWebHost(webHostBuilder =>
{ {
webHostBuilder.UseKestrel();
webHostBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "FastTunnel.Hosting");
webHostBuilder.ConfigureAppConfiguration((hostingContext, config) => webHostBuilder.ConfigureAppConfiguration((hostingContext, config) =>
{ {
var env = hostingContext.HostingEnvironment; var env = hostingContext.HostingEnvironment;
@ -60,15 +63,6 @@ public class Program
.AddJsonFile($"config/appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); .AddJsonFile($"config/appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
}); });
webHostBuilder.UseKestrel((context, options) =>
{
var basePort = context.Configuration.GetValue<int?>("BASE_PORT") ?? 1270;
options.ListenAnyIP(basePort, listenOptions =>
{
listenOptions.UseConnectionFastTunnel();
});
});
webHostBuilder.UseStartup<Startup>(); webHostBuilder.UseStartup<Startup>();
}); });
} }

View File

@ -80,10 +80,6 @@ public class Startup
c.SwaggerDoc("v2", new OpenApiInfo { Title = "FastTunel.Api", Version = "v2" }); c.SwaggerDoc("v2", new OpenApiInfo { Title = "FastTunel.Api", Version = "v2" });
}); });
#endif #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. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -98,10 +94,6 @@ public class Startup
#endif #endif
} }
// -------------------FastTunnel STEP2 OF 3------------------
app.UseFastTunnelServer();
// -------------------FastTunnel STEP2 END-------------------
app.UseRouting(); app.UseRouting();
// --------------------- Custom UI ---------------- // --------------------- Custom UI ----------------
@ -113,9 +105,6 @@ public class Startup
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {
endpoints.MapControllers(); endpoints.MapControllers();
// -------------------FastTunnel STEP3 OF 3------------------ });
//endpoints.MapFastTunnelServer();
// -------------------FastTunnel STEP3 END-------------------
});
} }
} }

View File

@ -8,11 +8,12 @@
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*",
// Http&
"BASE_PORT": 1270,
// //
"EnableFileLog": false, "EnableFileLog": false,
"FastTunnel": { "FastTunnel": {
// Http&
"BASE_PORT": 1270,
// //
// SubDomain ${SubDomain}.${WebDomain}访访 // SubDomain ${SubDomain}.${WebDomain}访访
"WebDomain": "test.cc", "WebDomain": "test.cc",