完善正向代理和反向代理共存

This commit is contained in:
老九 2021-09-14 20:30:14 +08:00
parent 9c2774dfa4
commit bc7a0b7084
14 changed files with 111 additions and 153 deletions

View File

@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>1.2.1</Version> <Version>2.0.0</Version>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Description>github加速神器</Description> <Description>github加速神器</Description>
<Copyright>https://github.com/dotnetcore/FastGithub</Copyright> <Copyright>https://github.com/dotnetcore/FastGithub</Copyright>

View File

@ -60,25 +60,38 @@ namespace FastGithub.Configuration
return GetAllIPAddresses().Contains(address); return GetAllIPAddresses().Contains(address);
} }
/// <summary> /// <summary>
/// 获取与远程节点通讯的的本机IP地址 /// 获取可用的随机Tcp端口
/// </summary> /// </summary>
/// <param name="remoteEndPoint">远程地址</param> /// <param name="addressFamily"></param>
/// <param name="min">最小值</param>
/// <returns></returns> /// <returns></returns>
public static IPAddress? GetLocalIPAddress(EndPoint remoteEndPoint) public static int GetAvailableTcpPort(AddressFamily addressFamily, int min = 1025)
{ {
try var hashSet = new HashSet<int>();
var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
foreach (var item in tcpListeners)
{ {
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); if (item.AddressFamily == addressFamily)
socket.Connect(remoteEndPoint);
return socket.LocalEndPoint is IPEndPoint localEndPoint ? localEndPoint.Address : default;
}
catch (Exception)
{ {
return default; hashSet.Add(item.Port);
} }
} }
for (var port = min; port < ushort.MaxValue; port++)
{
if (hashSet.Contains(port) == false)
{
return port;
}
}
throw new FastGithubException("当前无可用的端口");
}
/// <summary> /// <summary>
/// 获取可用的随机端口 /// 获取可用的随机端口
/// </summary> /// </summary>
@ -128,16 +141,5 @@ namespace FastGithub.Configuration
var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(); var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
return tcpListeners.Any(item => item.Port == port) == false; return tcpListeners.Any(item => item.Port == port) == false;
} }
/// <summary>
/// 是否可以监听指定udp端口
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
public static bool CanListenUdp(int port)
{
var udpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners();
return udpListeners.Any(item => item.Port == port) == false;
}
} }
} }

View File

@ -1,5 +1,4 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;
@ -8,24 +7,24 @@ using System.Threading.Tasks;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
/// <summary> /// <summary>
/// dns投毒后台服务 /// dns拦截后台服务
/// </summary> /// </summary>
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
sealed class DnsDnsPoisoningHostedService : BackgroundService sealed class DnsInterceptHostedService : BackgroundService
{ {
private readonly DnsPoisoningServer dnsPoisoningServer; private readonly DnsInterceptor dnsInterceptor;
private readonly IEnumerable<IConflictValidator> conflictValidators; private readonly IEnumerable<IConflictValidator> conflictValidators;
/// <summary> /// <summary>
/// dns后台服务 /// dns拦截后台服务
/// </summary> /// </summary>
/// <param name="dnsPoisoningServer"></param> /// <param name="dnsInterceptor"></param>
/// <param name="conflictValidators"></param> /// <param name="conflictValidators"></param>
public DnsDnsPoisoningHostedService( public DnsInterceptHostedService(
DnsPoisoningServer dnsPoisoningServer, DnsInterceptor dnsInterceptor,
IEnumerable<IConflictValidator> conflictValidators) IEnumerable<IConflictValidator> conflictValidators)
{ {
this.dnsPoisoningServer = dnsPoisoningServer; this.dnsInterceptor = dnsInterceptor;
this.conflictValidators = conflictValidators; this.conflictValidators = conflictValidators;
} }
@ -37,15 +36,11 @@ namespace FastGithub.Dns
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
await Task.Yield(); await Task.Yield();
if (OperatingSystem.IsWindows())
{
foreach (var item in this.conflictValidators) foreach (var item in this.conflictValidators)
{ {
await item.ValidateAsync(); await item.ValidateAsync();
} }
this.dnsPoisoningServer.DnsPoisoning(stoppingToken); this.dnsInterceptor.Intercept(stoppingToken);
}
} }
} }
} }

View File

@ -14,14 +14,14 @@ using WinDivertSharp;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
/// <summary> /// <summary>
/// dns投毒服务 /// dns拦截器
/// </summary> /// </summary>
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
sealed class DnsPoisoningServer sealed class DnsInterceptor
{ {
const string DNS_FILTER = "udp.DstPort == 53"; const string DNS_FILTER = "udp.DstPort == 53";
private readonly FastGithubConfig fastGithubConfig; private readonly FastGithubConfig fastGithubConfig;
private readonly ILogger<DnsPoisoningServer> logger; private readonly ILogger<DnsInterceptor> logger;
private readonly TimeSpan ttl = TimeSpan.FromSeconds(10d); private readonly TimeSpan ttl = TimeSpan.FromSeconds(10d);
/// <summary> /// <summary>
@ -35,19 +35,19 @@ namespace FastGithub.Dns
/// </summary> /// </summary>
/// <param name="fastGithubConfig"></param> /// <param name="fastGithubConfig"></param>
/// <param name="logger"></param> /// <param name="logger"></param>
public DnsPoisoningServer( public DnsInterceptor(
FastGithubConfig fastGithubConfig, FastGithubConfig fastGithubConfig,
ILogger<DnsPoisoningServer> logger) ILogger<DnsInterceptor> logger)
{ {
this.fastGithubConfig = fastGithubConfig; this.fastGithubConfig = fastGithubConfig;
this.logger = logger; this.logger = logger;
} }
/// <summary> /// <summary>
/// DNS投毒 /// DNS拦截
/// </summary> /// </summary>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
public void DnsPoisoning(CancellationToken cancellationToken) public void Intercept(CancellationToken cancellationToken)
{ {
var handle = WinDivert.WinDivertOpen(DNS_FILTER, WinDivertLayer.Network, 0, WinDivertOpenFlags.None); var handle = WinDivert.WinDivertOpen(DNS_FILTER, WinDivertLayer.Network, 0, WinDivertOpenFlags.None);
if (handle == IntPtr.Zero) if (handle == IntPtr.Zero)

View File

@ -11,17 +11,17 @@ namespace FastGithub
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
/// <summary> /// <summary>
/// 注册dns投毒服务 /// 注册dns拦截器
/// </summary> /// </summary>
/// <param name="services"></param> /// <param name="services"></param>
/// <returns></returns> /// <returns></returns>
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
public static IServiceCollection AddDnsPoisoning(this IServiceCollection services) public static IServiceCollection AddDnsInterceptor(this IServiceCollection services)
{ {
services.TryAddSingleton<DnsPoisoningServer>(); services.TryAddSingleton<DnsInterceptor>();
services.AddSingleton<IConflictValidator, HostsConflictValidator>(); services.AddSingleton<IConflictValidator, HostsConflictValidator>();
services.AddSingleton<IConflictValidator, ProxyConflictValidtor>(); services.AddSingleton<IConflictValidator, ProxyConflictValidtor>();
return services.AddHostedService<DnsDnsPoisoningHostedService>(); return services.AddHostedService<DnsInterceptHostedService>();
} }
} }
} }

View File

@ -37,7 +37,7 @@ namespace FastGithub.DomainResolve
try try
{ {
await this.dnscryptProxy.StartAsync(cancellationToken); await this.dnscryptProxy.StartAsync(cancellationToken);
this.logger.LogInformation($"已监听端口{this.dnscryptProxy.LocalEndPoint?.Port}{this.dnscryptProxy}启动完成"); this.logger.LogInformation($"已监听dns://{this.dnscryptProxy.LocalEndPoint}{this.dnscryptProxy}启动完成");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -17,7 +17,7 @@ namespace FastGithub
public static IApplicationBuilder UseHttpProxy(this IApplicationBuilder app) public static IApplicationBuilder UseHttpProxy(this IApplicationBuilder app)
{ {
var middleware = app.ApplicationServices.GetRequiredService<HttpProxyMiddleware>(); var middleware = app.ApplicationServices.GetRequiredService<HttpProxyMiddleware>();
return app.Use(next => context => middleware.InvokeAsync(context, next)); return app.Use(next => context => middleware.InvokeAsync(context));
} }
/// <summary> /// <summary>

View File

@ -20,7 +20,6 @@ namespace FastGithub.ReverseProxy
private readonly FastGithubConfig fastGithubConfig; private readonly FastGithubConfig fastGithubConfig;
private readonly IDomainResolver domainResolver; private readonly IDomainResolver domainResolver;
private readonly IHttpForwarder httpForwarder; private readonly IHttpForwarder httpForwarder;
private readonly PortService portService;
private readonly SocketsHttpHandler socketsHttpHandler = new() { UseCookies = false, UseProxy = false, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None }; private readonly SocketsHttpHandler socketsHttpHandler = new() { UseCookies = false, UseProxy = false, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.None };
/// <summary> /// <summary>
@ -29,26 +28,22 @@ namespace FastGithub.ReverseProxy
/// <param name="fastGithubConfig"></param> /// <param name="fastGithubConfig"></param>
/// <param name="domainResolver"></param> /// <param name="domainResolver"></param>
/// <param name="httpForwarder"></param> /// <param name="httpForwarder"></param>
/// <param name="portService"></param>
public HttpProxyMiddleware( public HttpProxyMiddleware(
FastGithubConfig fastGithubConfig, FastGithubConfig fastGithubConfig,
IDomainResolver domainResolver, IDomainResolver domainResolver,
IHttpForwarder httpForwarder, IHttpForwarder httpForwarder)
PortService portService)
{ {
this.fastGithubConfig = fastGithubConfig; this.fastGithubConfig = fastGithubConfig;
this.domainResolver = domainResolver; this.domainResolver = domainResolver;
this.httpForwarder = httpForwarder; this.httpForwarder = httpForwarder;
this.portService = portService;
} }
/// <summary> /// <summary>
/// 处理请求 /// 处理请求
/// </summary> /// </summary>
/// <param name="context"></param> /// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns> /// <returns></returns>
public async Task InvokeAsync(HttpContext context, RequestDelegate next) public async Task InvokeAsync(HttpContext context)
{ {
if (context.Request.Method != HttpMethods.Connect) if (context.Request.Method != HttpMethods.Connect)
{ {
@ -77,7 +72,6 @@ namespace FastGithub.ReverseProxy
} }
} }
/// <summary> /// <summary>
/// 获取目标终节点 /// 获取目标终节点
/// </summary> /// </summary>
@ -85,28 +79,28 @@ namespace FastGithub.ReverseProxy
/// <returns></returns> /// <returns></returns>
private async Task<EndPoint> GetTargetEndPointAsync(HttpRequest request) private async Task<EndPoint> GetTargetEndPointAsync(HttpRequest request)
{ {
var domain = request.Host.Host; var targetHost = request.Host.Host;
var port = request.Host.Port ?? 443; var targetPort = request.Host.Port ?? 443;
if (IPAddress.TryParse(domain, out var address) == true) if (IPAddress.TryParse(targetHost, out var address) == true)
{ {
return new IPEndPoint(address, port); return new IPEndPoint(address, targetPort);
} }
if (this.fastGithubConfig.TryGetDomainConfig(domain, out _) == false) if (this.fastGithubConfig.TryGetDomainConfig(targetHost, out _) == false)
{ {
return new DnsEndPoint(domain, port); return new DnsEndPoint(targetHost, targetPort);
} }
// https走反向代理中间人 // https走反向代理中间人
if (port == 443) if (targetPort == 443)
{ {
return new IPEndPoint(IPAddress.Loopback, this.portService.HttpsReverseProxyPort); return new IPEndPoint(IPAddress.Loopback, HttpsReverseProxyPort.Value);
} }
// dns优选 // dns优选
address = await this.domainResolver.ResolveAsync(new DnsEndPoint(domain, port)); address = await this.domainResolver.ResolveAsync(new DnsEndPoint(targetHost, targetPort));
return new IPEndPoint(address, port); return new IPEndPoint(address, targetPort);
} }
} }
} }

View File

@ -0,0 +1,17 @@
using FastGithub.Configuration;
using System;
using System.Net.Sockets;
namespace FastGithub.ReverseProxy
{
/// <summary>
/// https反向代理端口
/// </summary>
static class HttpsReverseProxyPort
{
/// <summary>
/// 获取端口值
/// </summary>
public static int Value { get; } = OperatingSystem.IsWindows() ? 443 : LocalMachine.GetAvailableTcpPort(AddressFamily.InterNetwork);
}
}

View File

@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System; using System;
using System.Net; using System.Net;
@ -30,18 +31,18 @@ namespace FastGithub
/// <param name="kestrel"></param> /// <param name="kestrel"></param>
public static void ListenHttpProxy(this KestrelServerOptions kestrel) public static void ListenHttpProxy(this KestrelServerOptions kestrel)
{ {
var httpPort = kestrel.ApplicationServices.GetRequiredService<PortService>().HttpProxyPort; var httpProxyPort = kestrel.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value.HttpProxyPort;
if (LocalMachine.CanListenTcp(httpPort) == false) if (LocalMachine.CanListenTcp(httpProxyPort) == false)
{ {
throw new FastGithubException("tcp端口{httpsPort}已经被其它进程占用,请在配置文件更换一个端口"); throw new FastGithubException($"tcp端口{httpProxyPort}已经被其它进程占用,请在配置文件更换{nameof(FastGithubOptions.HttpProxyPort)}为其它端口");
} }
kestrel.Listen(IPAddress.Any, httpPort); kestrel.Listen(IPAddress.Loopback, httpProxyPort);
kestrel.GetLogger().LogInformation($"已监听tcp端口{httpPort}http代理启动完成"); kestrel.GetLogger().LogInformation($"已监听http://127.0.0.1:{httpProxyPort}http代理启动完成");
} }
/// <summary> /// <summary>
/// 监听ssh反向代理 /// 尝试监听ssh反向代理
/// </summary> /// </summary>
/// <param name="kestrel"></param> /// <param name="kestrel"></param>
public static void ListenSshReverseProxy(this KestrelServerOptions kestrel) public static void ListenSshReverseProxy(this KestrelServerOptions kestrel)
@ -49,13 +50,13 @@ namespace FastGithub
const int SSH_PORT = 22; const int SSH_PORT = 22;
if (LocalMachine.CanListenTcp(SSH_PORT) == true) if (LocalMachine.CanListenTcp(SSH_PORT) == true)
{ {
kestrel.Listen(IPAddress.Any, SSH_PORT, listen => listen.UseConnectionHandler<SshReverseProxyHandler>()); kestrel.Listen(IPAddress.Loopback, SSH_PORT, listen => listen.UseConnectionHandler<SshReverseProxyHandler>());
kestrel.GetLogger().LogInformation($"已监听tcp端口{SSH_PORT}github的ssh代理启动完成"); kestrel.GetLogger().LogInformation($"已监听ssh://127.0.0.1:{SSH_PORT}ssh反向代理到github启动完成");
} }
} }
/// <summary> /// <summary>
/// 监听http反向代理 /// 尝试监听http反向代理
/// </summary> /// </summary>
/// <param name="kestrel"></param> /// <param name="kestrel"></param>
public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel) public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel)
@ -63,8 +64,8 @@ namespace FastGithub
const int HTTP_PORT = 80; const int HTTP_PORT = 80;
if (LocalMachine.CanListenTcp(HTTP_PORT) == true) if (LocalMachine.CanListenTcp(HTTP_PORT) == true)
{ {
kestrel.Listen(IPAddress.Any, HTTP_PORT); kestrel.Listen(IPAddress.Loopback, HTTP_PORT);
kestrel.GetLogger().LogInformation($"已监听tcp端口{HTTP_PORT}http反向代理启动完成"); kestrel.GetLogger().LogInformation($"已监听http://127.0.0.1:{HTTP_PORT}http反向代理启动完成");
} }
} }
@ -73,9 +74,10 @@ namespace FastGithub
/// </summary> /// </summary>
/// <param name="kestrel"></param> /// <param name="kestrel"></param>
/// <exception cref="FastGithubException"></exception> /// <exception cref="FastGithubException"></exception>
public static void ListenHttpsReverseProxy(this KestrelServerOptions kestrel) /// <returns></returns>
public static int ListenHttpsReverseProxy(this KestrelServerOptions kestrel)
{ {
var httpsPort = kestrel.ApplicationServices.GetRequiredService<PortService>().HttpsReverseProxyPort; var httpsPort = HttpsReverseProxyPort.Value;
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
TcpTable.KillPortOwner(httpsPort); TcpTable.KillPortOwner(httpsPort);
@ -90,15 +92,19 @@ namespace FastGithub
certService.CreateCaCertIfNotExists(); certService.CreateCaCertIfNotExists();
certService.InstallAndTrustCaCert(); certService.InstallAndTrustCaCert();
kestrel.Listen(IPAddress.Any, httpsPort, kestrel.Listen(IPAddress.Loopback, httpsPort,
listen => listen.UseHttps(https => listen => listen.UseHttps(https =>
https.ServerCertificateSelector = (ctx, domain) => https.ServerCertificateSelector = (ctx, domain) =>
certService.GetOrCreateServerCert(domain))); certService.GetOrCreateServerCert(domain)));
if (httpsPort == 443)
{
var logger = kestrel.GetLogger(); var logger = kestrel.GetLogger();
logger.LogInformation($"已监听tcp端口{httpsPort}https反向代理启动完成"); logger.LogInformation($"已监听https://127.0.0.1:{httpsPort}https反向代理启动完成");
} }
return httpsPort;
}
/// <summary> /// <summary>
/// 获取日志 /// 获取日志

View File

@ -1,48 +0,0 @@
using FastGithub.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Net.Sockets;
namespace FastGithub.ReverseProxy
{
/// <summary>
/// 端口管理服务
/// </summary>
public class PortService
{
private int httpsReverseProxyPort = -1;
/// <summary>
/// http代理端口
/// </summary>
public int HttpProxyPort { get; }
/// <summary>
/// 获取https反向代理端口
/// </summary>
public int HttpsReverseProxyPort
{
get
{
if (OperatingSystem.IsWindows())
{
return 443;
}
if (this.httpsReverseProxyPort < 0)
{
this.httpsReverseProxyPort = LocalMachine.GetAvailablePort(AddressFamily.InterNetwork);
}
return this.httpsReverseProxyPort;
}
}
/// <summary>
/// 端口管理服务
/// </summary>
/// <param name="options"></param>
public PortService(IOptions<FastGithubOptions> options)
{
this.HttpProxyPort = options.Value.HttpProxyPort;
}
}
}

View File

@ -4,12 +4,12 @@ using Microsoft.Extensions.DependencyInjection;
namespace FastGithub namespace FastGithub
{ {
/// <summary> /// <summary>
/// https反向代理的服务注册扩展 /// http反向代理的服务注册扩展
/// </summary> /// </summary>
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
/// <summary> /// <summary>
/// 添加https反向代理 /// 添加http反向代理
/// </summary> /// </summary>
/// <param name="services"></param> /// <param name="services"></param>
/// <returns></returns> /// <returns></returns>
@ -19,7 +19,6 @@ namespace FastGithub
.AddMemoryCache() .AddMemoryCache()
.AddHttpForwarder() .AddHttpForwarder()
.AddSingleton<CertService>() .AddSingleton<CertService>()
.AddSingleton<PortService>()
.AddSingleton<HttpProxyMiddleware>() .AddSingleton<HttpProxyMiddleware>()
.AddSingleton<RequestLoggingMiddleware>() .AddSingleton<RequestLoggingMiddleware>()
.AddSingleton<HttpReverseProxyMiddleware>(); .AddSingleton<HttpReverseProxyMiddleware>();

View File

@ -52,15 +52,15 @@ namespace FastGithub
webBuilder.UseKestrel(kestrel => webBuilder.UseKestrel(kestrel =>
{ {
kestrel.NoLimit(); kestrel.NoLimit();
kestrel.ListenHttpsReverseProxy();
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
kestrel.ListenHttpsReverseProxy();
kestrel.ListenHttpReverseProxy(); kestrel.ListenHttpReverseProxy();
kestrel.ListenSshReverseProxy(); kestrel.ListenSshReverseProxy();
} }
else else
{ {
kestrel.ListenHttpsReverseProxy();
kestrel.ListenHttpProxy(); kestrel.ListenHttpProxy();
} }
}); });

View File

@ -1,10 +1,9 @@
using FastGithub.Configuration; using FastGithub.Configuration;
using FastGithub.ReverseProxy;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System; using System;
using System.Threading.Tasks;
namespace FastGithub namespace FastGithub
{ {
@ -40,7 +39,7 @@ namespace FastGithub
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
services.AddDnsPoisoning(); services.AddDnsInterceptor();
} }
} }
@ -54,22 +53,16 @@ namespace FastGithub
{ {
app.UseRequestLogging(); app.UseRequestLogging();
app.UseHttpReverseProxy(); app.UseHttpReverseProxy();
app.UseRouting();
app.UseEndpoints(endpoint => endpoint.MapFallback(context =>
{
context.Response.Redirect("https://github.com/dotnetcore/FastGithub");
return Task.CompletedTask;
}));
} }
else else
{ {
var portService = app.ApplicationServices.GetRequiredService<PortService>(); var httpProxyPort = app.ApplicationServices.GetRequiredService<IOptions<FastGithubOptions>>().Value.HttpProxyPort;
app.MapWhen(context => context.Connection.LocalPort == portService.HttpProxyPort, appBuilder => app.MapWhen(context => context.Connection.LocalPort == httpProxyPort, appBuilder =>
{ {
appBuilder.UseHttpProxy(); appBuilder.UseHttpProxy();
}); });
app.MapWhen(context => context.Connection.LocalPort != portService.HttpProxyPort, appBuilder => app.MapWhen(context => context.Connection.LocalPort != httpProxyPort, appBuilder =>
{ {
appBuilder.UseRequestLogging(); appBuilder.UseRequestLogging();
appBuilder.UseHttpReverseProxy(); appBuilder.UseHttpReverseProxy();