代理的http流量应用域名配置

This commit is contained in:
老九 2021-09-26 20:45:43 +08:00
parent b6348133e4
commit 9086bf79f9
6 changed files with 39 additions and 32 deletions

View File

@ -15,6 +15,11 @@ namespace FastGithub.Configuration
private SortedDictionary<DomainPattern, DomainConfig> domainConfigs; private SortedDictionary<DomainPattern, DomainConfig> domainConfigs;
private ConcurrentDictionary<string, DomainConfig?> domainConfigCache; private ConcurrentDictionary<string, DomainConfig?> domainConfigCache;
/// <summary>
/// http代理端口
/// </summary>
public int HttpProxyPort { get; set; }
/// <summary> /// <summary>
/// 回退的dns /// 回退的dns
/// </summary> /// </summary>
@ -29,6 +34,7 @@ namespace FastGithub.Configuration
{ {
var opt = options.CurrentValue; var opt = options.CurrentValue;
this.HttpProxyPort = opt.HttpProxyPort;
this.FallbackDns = ConvertToIPEndPoints(opt.FallbackDns).ToArray(); this.FallbackDns = ConvertToIPEndPoints(opt.FallbackDns).ToArray();
this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs); this.domainConfigs = ConvertDomainConfigs(opt.DomainConfigs);
this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>(); this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();
@ -42,6 +48,7 @@ namespace FastGithub.Configuration
/// <param name="options"></param> /// <param name="options"></param>
private void Update(FastGithubOptions options) private void Update(FastGithubOptions options)
{ {
this.HttpProxyPort = options.HttpProxyPort;
this.FallbackDns = ConvertToIPEndPoints(options.FallbackDns).ToArray(); this.FallbackDns = ConvertToIPEndPoints(options.FallbackDns).ToArray();
this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs); this.domainConfigs = ConvertDomainConfigs(options.DomainConfigs);
this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>(); this.domainConfigCache = new ConcurrentDictionary<string, DomainConfig?>();

View File

@ -38,13 +38,13 @@ namespace FastGithub.DomainResolve
/// <param name="domain">域名</param> /// <param name="domain">域名</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<IPAddress?> ResolveAsync(string domain, CancellationToken cancellationToken = default) public async Task<IPAddress> ResolveAsync(string domain, CancellationToken cancellationToken = default)
{ {
await foreach (var address in this.ResolveAllAsync(domain, cancellationToken)) await foreach (var address in this.ResolveAllAsync(domain, cancellationToken))
{ {
return address; return address;
} }
return default; throw new FastGithubException($"解析不到{domain}的IP");
} }
/// <summary> /// <summary>

View File

@ -16,7 +16,7 @@ namespace FastGithub.DomainResolve
/// <param name="domain">域名</param> /// <param name="domain">域名</param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
Task<IPAddress?> ResolveAsync(string domain, CancellationToken cancellationToken = default); Task<IPAddress> ResolveAsync(string domain, CancellationToken cancellationToken = default);
/// <summary> /// <summary>
/// 解析所有ip /// 解析所有ip

View File

@ -3,7 +3,6 @@ using FastGithub.DomainResolve;
using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Options;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@ -25,8 +24,9 @@ namespace FastGithub.HttpServer
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 IOptions<FastGithubOptions> options; private readonly HttpReverseProxyMiddleware httpReverseProxy;
private readonly HttpMessageInvoker httpClient;
private readonly HttpMessageInvoker defaultHttpClient;
/// <summary> /// <summary>
/// http代理中间件 /// http代理中间件
@ -34,18 +34,19 @@ namespace FastGithub.HttpServer
/// <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="options"></param> /// <param name="httpReverseProxy"></param>
public HttpProxyMiddleware( public HttpProxyMiddleware(
FastGithubConfig fastGithubConfig, FastGithubConfig fastGithubConfig,
IDomainResolver domainResolver, IDomainResolver domainResolver,
IHttpForwarder httpForwarder, IHttpForwarder httpForwarder,
IOptions<FastGithubOptions> options) HttpReverseProxyMiddleware httpReverseProxy)
{ {
this.fastGithubConfig = fastGithubConfig; this.fastGithubConfig = fastGithubConfig;
this.domainResolver = domainResolver; this.domainResolver = domainResolver;
this.httpForwarder = httpForwarder; this.httpForwarder = httpForwarder;
this.options = options; this.httpReverseProxy = httpReverseProxy;
this.httpClient = new HttpMessageInvoker(CreateHttpHandler(), disposeHandler: false);
this.defaultHttpClient = new HttpMessageInvoker(CreateDefaultHttpHandler(), disposeHandler: false);
} }
/// <summary> /// <summary>
@ -84,12 +85,14 @@ namespace FastGithub.HttpServer
} }
else else
{ {
var destinationPrefix = $"{context.Request.Scheme}://{context.Request.Host}"; await this.httpReverseProxy.InvokeAsync(context, async ctx =>
await this.httpForwarder.SendAsync(context, destinationPrefix, this.httpClient); {
var destinationPrefix = $"{ctx.Request.Scheme}://{ctx.Request.Host}";
await this.httpForwarder.SendAsync(ctx, destinationPrefix, this.defaultHttpClient);
});
} }
} }
/// <summary> /// <summary>
/// 是否为fastgithub服务 /// 是否为fastgithub服务
/// </summary> /// </summary>
@ -99,7 +102,7 @@ namespace FastGithub.HttpServer
{ {
if (host.Host == LOOPBACK || host.Host == LOCALHOST) if (host.Host == LOOPBACK || host.Host == LOCALHOST)
{ {
return host.Port == this.options.Value.HttpProxyPort; return host.Port == this.fastGithubConfig.HttpProxyPort;
} }
return false; return false;
} }
@ -130,6 +133,7 @@ namespace FastGithub.HttpServer
/// <returns></returns> /// <returns></returns>
private async Task<EndPoint> GetTargetEndPointAsync(HostString host) private async Task<EndPoint> GetTargetEndPointAsync(HostString host)
{ {
const int HTTP_PORT = 80;
const int HTTPS_PORT = 443; const int HTTPS_PORT = 443;
var targetHost = host.Host; var targetHost = host.Host;
var targetPort = host.Port ?? HTTPS_PORT; var targetPort = host.Port ?? HTTPS_PORT;
@ -145,24 +149,26 @@ namespace FastGithub.HttpServer
return new DnsEndPoint(targetHost, targetPort); return new DnsEndPoint(targetHost, targetPort);
} }
// 目标端口为443走https代理中间人 if (targetPort == HTTP_PORT)
if (targetPort == HTTPS_PORT && targetHost != "ssh.github.com") {
return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Http);
}
if (targetPort == HTTPS_PORT)
{ {
return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Https); return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Https);
} }
// dns优选 // 不使用系统dns
address = await this.domainResolver.ResolveAsync(targetHost); address = await this.domainResolver.ResolveAsync(targetHost);
return address == null return new IPEndPoint(address, targetPort);
? throw new FastGithubException($"解析不到{targetHost}的IP")
: new IPEndPoint(address, targetPort);
} }
/// <summary> /// <summary>
/// 创建httpHandler /// 创建httpHandler
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private static SocketsHttpHandler CreateHttpHandler() private static SocketsHttpHandler CreateDefaultHttpHandler()
{ {
return new() return new()
{ {

View File

@ -1,5 +1,4 @@
using FastGithub.Configuration; using FastGithub.DomainResolve;
using FastGithub.DomainResolve;
using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Net.Sockets; using System.Net.Sockets;
@ -33,11 +32,6 @@ namespace FastGithub.HttpServer
public override async Task OnConnectedAsync(ConnectionContext context) public override async Task OnConnectedAsync(ConnectionContext context)
{ {
var address = await this.domainResolver.ResolveAsync(SSH_GITHUB_COM); var address = await this.domainResolver.ResolveAsync(SSH_GITHUB_COM);
if (address == null)
{
throw new FastGithubException($"解析不到{SSH_GITHUB_COM}的IP");
}
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(address, SSH_OVER_HTTPS_PORT); await socket.ConnectAsync(address, SSH_OVER_HTTPS_PORT);
var targetStream = new NetworkStream(socket, ownsSocket: false); var targetStream = new NetworkStream(socket, ownsSocket: false);

View File

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