From c96dab0df8ae20de9658b9791241e5e02ce680de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Fri, 16 Jul 2021 13:44:55 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E9=87=8D=E9=87=8D=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.Core/DnsIPEndPoint.cs | 28 ++++++++-- FastGithub.Core/FastGithubOptions.cs | 52 ++++++++++++++++--- FastGithub.Dns/DnsServerHostedService.cs | 21 ++++---- ...> DnsServerServiceCollectionExtensions.cs} | 4 +- ...oteRequest.cs => RemoteEndPointRequest.cs} | 8 +-- ...astGihubResolver.cs => RequestResolver.cs} | 28 +++++----- .../{NameServiceUtil.cs => SystemDnsUtil.cs} | 4 +- ...ntHanlder.cs => NoSniHttpClientHanlder.cs} | 18 +++---- ...everseProxyApplicationBuilderExtensions.cs | 2 +- ...ReverseProxyServiceCollectionExtensions.cs | 4 +- .../{GithubResolver.cs => TrustedResolver.cs} | 20 +++---- FastGithub/appsettings.json | 1 + FastGithub/publish.cmd | 4 +- 13 files changed, 125 insertions(+), 69 deletions(-) rename FastGithub.Dns/{DnsServiceCollectionExtensions.cs => DnsServerServiceCollectionExtensions.cs} (82%) rename FastGithub.Dns/{RemoteRequest.cs => RemoteEndPointRequest.cs} (84%) rename FastGithub.Dns/{FastGihubResolver.cs => RequestResolver.cs} (69%) rename FastGithub.Dns/{NameServiceUtil.cs => SystemDnsUtil.cs} (97%) rename FastGithub.ReverseProxy/{GithubHttpClientHanlder.cs => NoSniHttpClientHanlder.cs} (82%) rename FastGithub.ReverseProxy/{GithubResolver.cs => TrustedResolver.cs} (77%) diff --git a/FastGithub.Core/DnsIPEndPoint.cs b/FastGithub.Core/DnsIPEndPoint.cs index 640d2e8..8c6c6df 100644 --- a/FastGithub.Core/DnsIPEndPoint.cs +++ b/FastGithub.Core/DnsIPEndPoint.cs @@ -3,22 +3,40 @@ using System.Net; namespace FastGithub { + /// + /// dns的终节点 + /// public class DnsIPEndPoint { + /// + /// IP地址 + /// [AllowNull] - public string Address { get; set; } = IPAddress.Loopback.ToString(); + public string IPAddress { get; set; } - public int Port { get; set; } = 53; + /// + /// 端口 + /// + public int Port { get; set; } + /// + /// 转换为IPEndPoint + /// + /// public IPEndPoint ToIPEndPoint() { - return new IPEndPoint(IPAddress.Parse(this.Address), this.Port); + return new IPEndPoint(System.Net.IPAddress.Parse(this.IPAddress), this.Port); } + /// + /// 验证 + /// + /// public bool Validate() { - return IPAddress.TryParse(this.Address, out var address) && - !(address.Equals(IPAddress.Loopback) && this.Port == 53); + return System.Net.IPAddress.TryParse(this.IPAddress, out var address) + ? !(address.Equals(System.Net.IPAddress.Loopback) && this.Port == 53) + : false; } } } diff --git a/FastGithub.Core/FastGithubOptions.cs b/FastGithub.Core/FastGithubOptions.cs index 148f04d..a57918a 100644 --- a/FastGithub.Core/FastGithubOptions.cs +++ b/FastGithub.Core/FastGithubOptions.cs @@ -4,16 +4,36 @@ using System.Text.RegularExpressions; namespace FastGithub { + /// + /// FastGithub的配置 + /// public class FastGithubOptions { + /// + /// 域名 + /// private DomainMatch[]? domainMatches; - public DnsIPEndPoint TrustedDns { get; set; } = new DnsIPEndPoint { Address = "127.0.0.1", Port = 5533 }; + /// + /// 受信任的dns服务 + /// + public DnsIPEndPoint TrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "127.0.0.1", Port = 5533 }; - public DnsIPEndPoint UntrustedDns { get; set; } = new DnsIPEndPoint { Address = "114.1114.114.114", Port = 53 }; + /// + /// 不受信任的dns服务 + /// + public DnsIPEndPoint UntrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "114.114.114.114", Port = 53 }; + /// + /// 代理的域名匹配 + /// public HashSet DomainMatches { get; set; } = new(); + /// + /// 是否匹配指定的域名 + /// + /// + /// public bool IsMatch(string domain) { if (this.domainMatches == null) @@ -23,26 +43,42 @@ namespace FastGithub return this.domainMatches.Any(item => item.IsMatch(domain)); } + /// + /// 域名匹配 + /// private class DomainMatch { private readonly Regex regex; - private readonly string value; + private readonly string pattern; - public DomainMatch(string value) + /// + /// 域名匹配 + /// + /// 域名表达式 + public DomainMatch(string pattern) { - this.value = value; - var pattern = Regex.Escape(value).Replace(@"\*", ".*"); - this.regex = new Regex($"^{pattern}$"); + this.pattern = pattern; + var regexPattern = Regex.Escape(pattern).Replace(@"\*", ".*"); + this.regex = new Regex($"^{regexPattern}$", RegexOptions.IgnoreCase); } + /// + /// 是否与指定域名匹配 + /// + /// + /// public bool IsMatch(string domain) { return this.regex.IsMatch(domain); } + /// + /// 转换为文本 + /// + /// public override string ToString() { - return this.value; + return this.pattern; } } } diff --git a/FastGithub.Dns/DnsServerHostedService.cs b/FastGithub.Dns/DnsServerHostedService.cs index 45cf53d..812f3af 100644 --- a/FastGithub.Dns/DnsServerHostedService.cs +++ b/FastGithub.Dns/DnsServerHostedService.cs @@ -15,9 +15,7 @@ namespace FastGithub.Dns /// sealed class DnsServerHostedService : BackgroundService { - private const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C); - - private readonly FastGihubResolver fastGihubResolver; + private readonly RequestResolver requestResolver; private readonly IOptions options; private readonly ILogger logger; @@ -28,15 +26,15 @@ namespace FastGithub.Dns /// /// dns后台服务 /// - /// + /// /// /// public DnsServerHostedService( - FastGihubResolver fastGihubResolver, + RequestResolver requestResolver, IOptions options, ILogger logger) { - this.fastGihubResolver = fastGihubResolver; + this.requestResolver = requestResolver; this.options = options; this.logger = logger; } @@ -51,12 +49,13 @@ namespace FastGithub.Dns this.socket.Bind(new IPEndPoint(IPAddress.Any, 53)); if (OperatingSystem.IsWindows()) { + const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C); this.socket.IOControl(SIO_UDP_CONNRESET, new byte[4], new byte[4]); } this.logger.LogInformation("dns服务启动成功"); - var upStream = IPAddress.Parse(options.Value.UntrustedDns.Address); - this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, upStream); + var secondary = IPAddress.Parse(options.Value.UntrustedDns.IPAddress); + this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, secondary); return base.StartAsync(cancellationToken); } @@ -88,8 +87,8 @@ namespace FastGithub.Dns try { var request = Request.FromArray(datas); - var remoteRequest = new RemoteRequest(request, remoteEndPoint); - var response = await this.fastGihubResolver.Resolve(remoteRequest, cancellationToken); + var remoteEndPointRequest = new RemoteEndPointRequest(request, remoteEndPoint); + var response = await this.requestResolver.Resolve(remoteEndPointRequest, cancellationToken); await this.socket.SendToAsync(response.ToArray(), SocketFlags.None, remoteEndPoint); } catch (Exception ex) @@ -126,7 +125,7 @@ namespace FastGithub.Dns { try { - var results = NameServiceUtil.SetNameServers(nameServers); + var results = SystemDnsUtil.SetNameServers(nameServers); this.logger.LogInformation($"设置本机dns成功"); return results; } diff --git a/FastGithub.Dns/DnsServiceCollectionExtensions.cs b/FastGithub.Dns/DnsServerServiceCollectionExtensions.cs similarity index 82% rename from FastGithub.Dns/DnsServiceCollectionExtensions.cs rename to FastGithub.Dns/DnsServerServiceCollectionExtensions.cs index 2ad2699..1321ee1 100644 --- a/FastGithub.Dns/DnsServiceCollectionExtensions.cs +++ b/FastGithub.Dns/DnsServerServiceCollectionExtensions.cs @@ -6,7 +6,7 @@ namespace FastGithub /// /// 服务注册扩展 /// - public static class DnsServiceCollectionExtensions + public static class DnsServerServiceCollectionExtensions { /// /// 注册github的dns服务 @@ -16,7 +16,7 @@ namespace FastGithub public static IServiceCollection AddGithubDns(this IServiceCollection services) { return services - .AddSingleton() + .AddSingleton() .AddHostedService(); } } diff --git a/FastGithub.Dns/RemoteRequest.cs b/FastGithub.Dns/RemoteEndPointRequest.cs similarity index 84% rename from FastGithub.Dns/RemoteRequest.cs rename to FastGithub.Dns/RemoteEndPointRequest.cs index 7a8e745..4ec6116 100644 --- a/FastGithub.Dns/RemoteRequest.cs +++ b/FastGithub.Dns/RemoteEndPointRequest.cs @@ -6,12 +6,12 @@ using System.Net.Sockets; namespace FastGithub.Dns { /// - /// 远程请求 + /// 带远程终节点的请求 /// - sealed class RemoteRequest : Request + sealed class RemoteEndPointRequest : Request { /// - /// 获取远程地址 + /// 获取程终节点 /// public EndPoint RemoteEndPoint { get; } @@ -20,7 +20,7 @@ namespace FastGithub.Dns /// /// /// - public RemoteRequest(Request request, EndPoint remoteEndPoint) + public RemoteEndPointRequest(Request request, EndPoint remoteEndPoint) : base(request) { this.RemoteEndPoint = remoteEndPoint; diff --git a/FastGithub.Dns/FastGihubResolver.cs b/FastGithub.Dns/RequestResolver.cs similarity index 69% rename from FastGithub.Dns/FastGihubResolver.cs rename to FastGithub.Dns/RequestResolver.cs index 0520069..a94261b 100644 --- a/FastGithub.Dns/FastGihubResolver.cs +++ b/FastGithub.Dns/RequestResolver.cs @@ -12,26 +12,27 @@ using System.Threading.Tasks; namespace FastGithub.Dns { /// - /// 反向代理解析器 + /// dns解析者 /// - sealed class FastGihubResolver : IRequestResolver + sealed class RequestResolver : IRequestResolver { - private readonly IRequestResolver untrustedDnsResolver; + private readonly TimeSpan ttl = TimeSpan.FromMinutes(1d); + private readonly IRequestResolver untrustedResolver; private readonly IOptionsMonitor options; - private readonly ILogger logger; + private readonly ILogger logger; /// - /// github相关域名解析器 + /// dns解析者 /// /// /// - public FastGihubResolver( + public RequestResolver( IOptionsMonitor options, - ILogger logger) + ILogger logger) { this.options = options; this.logger = logger; - this.untrustedDnsResolver = new UdpRequestResolver(options.CurrentValue.UntrustedDns.ToIPEndPoint()); + this.untrustedResolver = new UdpRequestResolver(options.CurrentValue.UntrustedDns.ToIPEndPoint()); } /// @@ -43,7 +44,7 @@ namespace FastGithub.Dns public async Task Resolve(IRequest request, CancellationToken cancellationToken = default) { var response = Response.FromRequest(request); - if (request is not RemoteRequest remoteRequest) + if (request is not RemoteEndPointRequest remoteEndPointRequest) { return response; } @@ -57,14 +58,15 @@ namespace FastGithub.Dns var domain = question.Name; if (this.options.CurrentValue.IsMatch(domain.ToString()) == true) { - var localAddress = remoteRequest.GetLocalAddress() ?? IPAddress.Loopback; - var record = new IPAddressResourceRecord(domain, localAddress, TimeSpan.FromMinutes(1d)); - this.logger.LogInformation($"[{domain}->{localAddress}]"); + var localAddress = remoteEndPointRequest.GetLocalAddress() ?? IPAddress.Loopback; + var record = new IPAddressResourceRecord(domain, localAddress, this.ttl); response.AnswerRecords.Add(record); + + this.logger.LogInformation($"[{domain}->{localAddress}]"); return response; } - return await this.untrustedDnsResolver.Resolve(request, cancellationToken); + return await this.untrustedResolver.Resolve(request, cancellationToken); } } } diff --git a/FastGithub.Dns/NameServiceUtil.cs b/FastGithub.Dns/SystemDnsUtil.cs similarity index 97% rename from FastGithub.Dns/NameServiceUtil.cs rename to FastGithub.Dns/SystemDnsUtil.cs index 80a524e..1b2dce3 100644 --- a/FastGithub.Dns/NameServiceUtil.cs +++ b/FastGithub.Dns/SystemDnsUtil.cs @@ -9,10 +9,10 @@ using System.Runtime.Versioning; namespace FastGithub.Dns { /// - /// 域名服务工具 + /// 系统域名服务工具 /// [SupportedOSPlatform("windows")] - static class NameServiceUtil + static class SystemDnsUtil { /// /// www.baidu.com的ip diff --git a/FastGithub.ReverseProxy/GithubHttpClientHanlder.cs b/FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs similarity index 82% rename from FastGithub.ReverseProxy/GithubHttpClientHanlder.cs rename to FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs index 2894191..fc23c62 100644 --- a/FastGithub.ReverseProxy/GithubHttpClientHanlder.cs +++ b/FastGithub.ReverseProxy/NoSniHttpClientHanlder.cs @@ -8,19 +8,19 @@ using System.Threading.Tasks; namespace FastGithub.ReverseProxy { /// - /// 适用于请求github的HttpClientHandler + /// 不发送NoSni的HttpClientHandler /// - class GithubHttpClientHanlder : DelegatingHandler + class NoSniHttpClientHanlder : DelegatingHandler { - private readonly GithubResolver githubResolver; + private readonly TrustedResolver trustedDomainResolver; /// - /// 请求github的HttpClientHandler + /// 不发送NoSni的HttpClientHandler /// - /// - public GithubHttpClientHanlder(GithubResolver githubResolver) + /// + public NoSniHttpClientHanlder(TrustedResolver trustedDomainResolver) { - this.githubResolver = githubResolver; + this.trustedDomainResolver = trustedDomainResolver; this.InnerHandler = CreateNoneSniHttpHandler(); } @@ -58,7 +58,7 @@ namespace FastGithub.ReverseProxy /// - /// 替换github域名为ip + /// 替换域名为ip /// /// /// @@ -68,7 +68,7 @@ namespace FastGithub.ReverseProxy var uri = request.RequestUri; if (uri != null && uri.HostNameType == UriHostNameType.Dns) { - var address = await this.githubResolver.ResolveAsync(uri.Host, cancellationToken); + var address = await this.trustedDomainResolver.ResolveAsync(uri.Host, cancellationToken); var builder = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp, diff --git a/FastGithub.ReverseProxy/ReverseProxyApplicationBuilderExtensions.cs b/FastGithub.ReverseProxy/ReverseProxyApplicationBuilderExtensions.cs index 5b565e8..9fcc6c8 100644 --- a/FastGithub.ReverseProxy/ReverseProxyApplicationBuilderExtensions.cs +++ b/FastGithub.ReverseProxy/ReverseProxyApplicationBuilderExtensions.cs @@ -21,7 +21,7 @@ namespace FastGithub public static IApplicationBuilder UseGithubReverseProxy(this IApplicationBuilder app) { var httpForwarder = app.ApplicationServices.GetRequiredService(); - var httpClientHanlder = app.ApplicationServices.GetRequiredService(); + var httpClientHanlder = app.ApplicationServices.GetRequiredService(); var options = app.ApplicationServices.GetRequiredService>(); app.Use(next => async context => diff --git a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs index e1e5a05..8b45ce0 100644 --- a/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs +++ b/FastGithub.ReverseProxy/ReverseProxyServiceCollectionExtensions.cs @@ -18,8 +18,8 @@ namespace FastGithub return services .AddMemoryCache() .AddHttpForwarder() - .AddSingleton() - .AddTransient(); + .AddSingleton() + .AddTransient(); } } } diff --git a/FastGithub.ReverseProxy/GithubResolver.cs b/FastGithub.ReverseProxy/TrustedResolver.cs similarity index 77% rename from FastGithub.ReverseProxy/GithubResolver.cs rename to FastGithub.ReverseProxy/TrustedResolver.cs index e08474b..2f8d721 100644 --- a/FastGithub.ReverseProxy/GithubResolver.cs +++ b/FastGithub.ReverseProxy/TrustedResolver.cs @@ -12,22 +12,23 @@ using System.Threading.Tasks; namespace FastGithub.ReverseProxy { /// - /// github解析器 + /// 受信任的域名解析器 /// - sealed class GithubResolver + sealed class TrustedResolver { private readonly IMemoryCache memoryCache; + private readonly TimeSpan cacheTimeSpan = TimeSpan.FromSeconds(10d); private readonly IOptionsMonitor options; - private readonly ILogger logger; + private readonly ILogger logger; /// - /// github解析器 + /// 受信任的域名解析器 /// /// - public GithubResolver( + public TrustedResolver( IMemoryCache memoryCache, IOptionsMonitor options, - ILogger logger) + ILogger logger) { this.memoryCache = memoryCache; this.options = options; @@ -41,11 +42,11 @@ namespace FastGithub.ReverseProxy /// public async Task ResolveAsync(string domain, CancellationToken cancellationToken) { - // 缓存,避免做不必要的并发查询 + // 缓存以避免做不必要的并发查询 var key = $"domain:{domain}"; var address = await this.memoryCache.GetOrCreateAsync(key, async e => { - e.SetAbsoluteExpiration(TimeSpan.FromMinutes(2d)); + e.SetAbsoluteExpiration(this.cacheTimeSpan); var dnsClient = new DnsClient(this.options.CurrentValue.TrustedDns.ToIPEndPoint()); var addresses = await dnsClient.Lookup(domain, DNS.Protocol.RecordType.A, cancellationToken); return addresses?.FirstOrDefault(); @@ -57,7 +58,8 @@ namespace FastGithub.ReverseProxy this.logger.LogWarning(message); throw new HttpRequestException(message); } - this.logger.LogInformation($"[{domain}->{address}]"); + + this.logger.LogInformation($"[{address}->{domain}]"); return address; } } diff --git a/FastGithub/appsettings.json b/FastGithub/appsettings.json index 8adf40c..9746d27 100644 --- a/FastGithub/appsettings.json +++ b/FastGithub/appsettings.json @@ -11,6 +11,7 @@ "DomainMatches": [ "github.com", "*.github.com", + "*.github.io", "*.githubapp.com", "*.githubassets.com", "*.githubusercontent.com" diff --git a/FastGithub/publish.cmd b/FastGithub/publish.cmd index d294743..976424b 100644 --- a/FastGithub/publish.cmd +++ b/FastGithub/publish.cmd @@ -1,4 +1,2 @@ dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r linux-x64 -o ./bin/publish/linux-x64 -dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x86 -o ./bin/publish/win-x86 -dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x64 -o ./bin/publish/win-x64 -dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r osx-x64 -o ./bin/publish/osx-x64 +dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x64 -o ./bin/publish/win-x64 \ No newline at end of file