From 930a8b624ad70ce0dd527bfae9898a7cff5df8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Sun, 26 Sep 2021 17:39:36 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=80=E5=8C=96DomainResolver?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DomainResolver.cs | 69 ++----------------- FastGithub.DomainResolve/IDomainResolver.cs | 8 +-- FastGithub.Http/HttpClientHandler.cs | 2 +- FastGithub.HttpServer/HttpProxyMiddleware.cs | 6 +- .../SshReverseProxyHandler.cs | 18 +++-- 5 files changed, 28 insertions(+), 75 deletions(-) diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index 7baef65..b894e52 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -1,11 +1,6 @@ using FastGithub.Configuration; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.Options; -using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; -using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -21,11 +16,6 @@ namespace FastGithub.DomainResolve private readonly FastGithubConfig fastGithubConfig; private readonly DnsClient dnsClient; - private readonly ConcurrentDictionary semaphoreSlims = new(); - private readonly IMemoryCache ipEndPointAvailableCache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - private readonly TimeSpan ipEndPointExpiration = TimeSpan.FromMinutes(2d); - private readonly TimeSpan ipEndPointConnectTimeout = TimeSpan.FromSeconds(5d); - /// /// 域名解析器 /// @@ -43,72 +33,27 @@ namespace FastGithub.DomainResolve } /// - /// 解析可用的ip + /// 解析ip /// - /// 远程节点 + /// 域名 /// /// - public async Task ResolveAsync(DnsEndPoint endPoint, CancellationToken cancellationToken = default) + public async Task ResolveAsync(string domain, CancellationToken cancellationToken = default) { - await foreach (var address in this.ResolveAsync(endPoint.Host, cancellationToken)) + await foreach (var address in this.ResolveAllAsync(domain, cancellationToken)) { - if (await this.IsAvailableAsync(new IPEndPoint(address, endPoint.Port), cancellationToken)) - { - return address; - } + return address; } - throw new FastGithubException($"解析不到{endPoint.Host}可用的IP"); + return default; } - /// - /// 验证远程节点是否可连接 - /// - /// - /// - /// - /// - private async Task IsAvailableAsync(IPEndPoint ipEndPoint, CancellationToken cancellationToken) - { - var semaphore = this.semaphoreSlims.GetOrAdd(ipEndPoint, _ => new SemaphoreSlim(1, 1)); - try - { - await semaphore.WaitAsync(CancellationToken.None); - if (this.ipEndPointAvailableCache.TryGetValue(ipEndPoint, out var available)) - { - return available; - } - - try - { - using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp); - using var timeoutTokenSource = new CancellationTokenSource(this.ipEndPointConnectTimeout); - using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); - await socket.ConnectAsync(ipEndPoint, linkedTokenSource.Token); - available = true; - } - catch (Exception) - { - cancellationToken.ThrowIfCancellationRequested(); - available = false; - } - - this.ipEndPointAvailableCache.Set(ipEndPoint, available, ipEndPointExpiration); - return available; - } - finally - { - semaphore.Release(); - } - } - - /// /// 解析域名 /// /// 域名 /// /// - public async IAsyncEnumerable ResolveAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) + public async IAsyncEnumerable ResolveAllAsync(string domain, [EnumeratorCancellation] CancellationToken cancellationToken) { var hashSet = new HashSet(); foreach (var dns in this.GetDnsServers()) diff --git a/FastGithub.DomainResolve/IDomainResolver.cs b/FastGithub.DomainResolve/IDomainResolver.cs index 47b7319..691ab3c 100644 --- a/FastGithub.DomainResolve/IDomainResolver.cs +++ b/FastGithub.DomainResolve/IDomainResolver.cs @@ -11,12 +11,12 @@ namespace FastGithub.DomainResolve public interface IDomainResolver { /// - /// 解析可用的ip + /// 解析ip /// - /// 远程节点 + /// 域名 /// /// - Task ResolveAsync(DnsEndPoint endPoint, CancellationToken cancellationToken = default); + Task ResolveAsync(string domain, CancellationToken cancellationToken = default); /// /// 解析所有ip @@ -24,6 +24,6 @@ namespace FastGithub.DomainResolve /// 域名 /// /// - IAsyncEnumerable ResolveAsync(string domain, CancellationToken cancellationToken = default); + IAsyncEnumerable ResolveAllAsync(string domain, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/FastGithub.Http/HttpClientHandler.cs b/FastGithub.Http/HttpClientHandler.cs index f49ba2a..3c3fbdf 100644 --- a/FastGithub.Http/HttpClientHandler.cs +++ b/FastGithub.Http/HttpClientHandler.cs @@ -175,7 +175,7 @@ namespace FastGithub.Http } else { - await foreach (var item in this.domainResolver.ResolveAsync(dnsEndPoint.Host, cancellationToken)) + await foreach (var item in this.domainResolver.ResolveAllAsync(dnsEndPoint.Host, cancellationToken)) { yield return new IPEndPoint(item, dnsEndPoint.Port); } diff --git a/FastGithub.HttpServer/HttpProxyMiddleware.cs b/FastGithub.HttpServer/HttpProxyMiddleware.cs index 1e0308b..f6518dc 100644 --- a/FastGithub.HttpServer/HttpProxyMiddleware.cs +++ b/FastGithub.HttpServer/HttpProxyMiddleware.cs @@ -152,8 +152,10 @@ namespace FastGithub.HttpServer } // dns优选 - address = await this.domainResolver.ResolveAsync(new DnsEndPoint(targetHost, targetPort)); - return new IPEndPoint(address, targetPort); + address = await this.domainResolver.ResolveAsync(targetHost); + return address == null + ? throw new FastGithubException($"解析不到{targetHost}的IP") + : new IPEndPoint(address, targetPort); } /// diff --git a/FastGithub.HttpServer/SshReverseProxyHandler.cs b/FastGithub.HttpServer/SshReverseProxyHandler.cs index 0cdf324..0691802 100644 --- a/FastGithub.HttpServer/SshReverseProxyHandler.cs +++ b/FastGithub.HttpServer/SshReverseProxyHandler.cs @@ -1,7 +1,7 @@ -using FastGithub.DomainResolve; +using FastGithub.Configuration; +using FastGithub.DomainResolve; using Microsoft.AspNetCore.Connections; using System.IO.Pipelines; -using System.Net; using System.Net.Sockets; using System.Threading.Tasks; @@ -13,7 +13,8 @@ namespace FastGithub.HttpServer sealed class SshReverseProxyHandler : ConnectionHandler { private readonly IDomainResolver domainResolver; - private readonly DnsEndPoint githubSshEndPoint = new("ssh.github.com", 443); + private const string SSH_GITHUB_COM = "ssh.github.com"; + private const int SSH_OVER_HTTPS_PORT = 443; /// /// github的ssh代理处理者 @@ -31,9 +32,14 @@ namespace FastGithub.HttpServer /// public override async Task OnConnectedAsync(ConnectionContext context) { - var address = await this.domainResolver.ResolveAsync(this.githubSshEndPoint); - using var socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); - await socket.ConnectAsync(address, this.githubSshEndPoint.Port); + 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); + await socket.ConnectAsync(address, SSH_OVER_HTTPS_PORT); var targetStream = new NetworkStream(socket, ownsSocket: false); var task1 = targetStream.CopyToAsync(context.Transport.Output);