From 2bacf5a4fc475fcfdc088f21d53adfd10785ce6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com> Date: Thu, 15 Jul 2021 17:10:36 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E4=BE=A6=E6=B5=8B=E6=9C=AC?= =?UTF-8?q?=E6=9C=BAip=E5=81=9A=E4=B8=BAdns=E5=93=8D=E5=BA=94=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.Dns/DnsHostedService.cs | 14 +++-- FastGithub.Dns/DnsOptions.cs | 8 +-- FastGithub.Dns/GithubRequestResolver.cs | 55 ++++++++++++------ FastGithub.Dns/RemoteRequest.cs | 77 +++++++++++++++++++++++++ FastGithub/appsettings.json | 3 +- 5 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 FastGithub.Dns/RemoteRequest.cs diff --git a/FastGithub.Dns/DnsHostedService.cs b/FastGithub.Dns/DnsHostedService.cs index cbb8919..3d2f3b8 100644 --- a/FastGithub.Dns/DnsHostedService.cs +++ b/FastGithub.Dns/DnsHostedService.cs @@ -40,7 +40,9 @@ namespace FastGithub.Dns { this.options = options; this.logger = logger; - this.requestResolver = new CompositeRequestResolver(IPAddress.Parse(options.Value.UpStream), githubRequestResolver); + + var upStream = IPAddress.Parse(options.Value.UpStream); + this.requestResolver = new CompositeRequestResolver(upStream, githubRequestResolver); } /// @@ -57,7 +59,8 @@ namespace FastGithub.Dns } this.logger.LogInformation("dns服务启动成功"); - this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, IPAddress.Parse(this.options.Value.UpStream)); + var upStream = IPAddress.Parse(options.Value.UpStream); + this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, upStream); return base.StartAsync(cancellationToken); } @@ -74,7 +77,7 @@ namespace FastGithub.Dns var result = await this.socket.ReceiveFromAsync(this.buffer, SocketFlags.None, remoteEndPoint); var datas = new byte[result.ReceivedBytes]; this.buffer.AsSpan(0, datas.Length).CopyTo(datas); - this.HandleRequestAsync(datas, result.RemoteEndPoint, stoppingToken); + this.HandleRequestAsync(datas, (IPEndPoint)result.RemoteEndPoint, stoppingToken); } } @@ -84,12 +87,13 @@ namespace FastGithub.Dns /// /// /// - private async void HandleRequestAsync(byte[] datas, EndPoint remoteEndPoint, CancellationToken cancellationToken) + private async void HandleRequestAsync(byte[] datas, IPEndPoint remoteEndPoint, CancellationToken cancellationToken) { try { var request = Request.FromArray(datas); - var response = await this.requestResolver.Resolve(request, cancellationToken); + var remoteRequest = new RemoteRequest(request, remoteEndPoint.Address); + var response = await this.requestResolver.Resolve(remoteRequest, cancellationToken); await this.socket.SendToAsync(response.ToArray(), SocketFlags.None, remoteEndPoint); } catch (Exception ex) diff --git a/FastGithub.Dns/DnsOptions.cs b/FastGithub.Dns/DnsOptions.cs index 03ce16e..f34f524 100644 --- a/FastGithub.Dns/DnsOptions.cs +++ b/FastGithub.Dns/DnsOptions.cs @@ -1,5 +1,4 @@ using System; -using System.Net; namespace FastGithub.Dns { @@ -27,11 +26,6 @@ namespace FastGithub.Dns /// /// 是否使用反向代理访问github /// - public bool UseGithubReverseProxy { get; set; } = true; - - /// - /// dns响应的反向代理服务的ip - /// - public string GithubReverseProxyIPAddress { get; set; } = IPAddress.Loopback.ToString(); + public bool UseGithubReverseProxy { get; set; } = true; } } diff --git a/FastGithub.Dns/GithubRequestResolver.cs b/FastGithub.Dns/GithubRequestResolver.cs index 6f7d4e0..221f336 100644 --- a/FastGithub.Dns/GithubRequestResolver.cs +++ b/FastGithub.Dns/GithubRequestResolver.cs @@ -48,38 +48,55 @@ namespace FastGithub.Dns public Task Resolve(IRequest request, CancellationToken cancellationToken = default) { IResponse response = Response.FromRequest(request); - var question = request.Questions.FirstOrDefault(); + if (request is not RemoteRequest remoteRequest) + { + return Task.FromResult(response); + } + var question = request.Questions.FirstOrDefault(); if (question == null || question.Type != RecordType.A) { return Task.FromResult(response); } - var domain = question.Name.ToString(); - if (this.githubResolver.IsSupported(domain) == false) + var domain = question.Name; + if (this.githubResolver.IsSupported(domain.ToString()) == false) { return Task.FromResult(response); } - if (this.options.CurrentValue.UseGithubReverseProxy == false) + var record = this.GetAnswerRecord(remoteRequest, domain); + if (record != null) { - var address = this.githubResolver.Resolve(domain); - if (address != null) - { - var ttl = this.options.CurrentValue.GithubTTL; - var record = new IPAddressResourceRecord(question.Name, address, ttl); - response.AnswerRecords.Add(record); - this.logger.LogInformation($"[{domain}->{address}]"); - } - } - else - { - var address = IPAddress.Parse(this.options.CurrentValue.GithubReverseProxyIPAddress); - var record = new IPAddressResourceRecord(question.Name, address, TimeSpan.FromMinutes(1)); + this.logger.LogInformation($"[{domain}->{record.IPAddress}]"); response.AnswerRecords.Add(record); - this.logger.LogInformation($"[{domain}->{address}]"); - } + } + return Task.FromResult(response); } + + /// + /// 获取答案 + /// + /// + /// + /// + private IPAddressResourceRecord? GetAnswerRecord(RemoteRequest request, Domain domain) + { + if (this.options.CurrentValue.UseGithubReverseProxy == true) + { + var localAddress = request.GetLocalAddress() ?? IPAddress.Loopback; + return new IPAddressResourceRecord(domain, localAddress, TimeSpan.FromMinutes(1d)); + } + + var githubAddress = this.githubResolver.Resolve(domain.ToString()); + if (githubAddress == null) + { + return default; + } + + var ttl = this.options.CurrentValue.GithubTTL; + return new IPAddressResourceRecord(domain, githubAddress, ttl); + } } } diff --git a/FastGithub.Dns/RemoteRequest.cs b/FastGithub.Dns/RemoteRequest.cs new file mode 100644 index 0000000..eb1cb7b --- /dev/null +++ b/FastGithub.Dns/RemoteRequest.cs @@ -0,0 +1,77 @@ +using DNS.Protocol; +using System.Buffers.Binary; +using System.Net; +using System.Net.NetworkInformation; + +namespace FastGithub.Dns +{ + /// + /// 远程请求 + /// + sealed class RemoteRequest : Request + { + /// + /// 获取远程地址 + /// + public IPAddress RemoteAddress { get; } + + /// + /// 远程请求 + /// + /// + /// + public RemoteRequest(Request request, IPAddress remoteAddress) + : base(request) + { + this.RemoteAddress = remoteAddress; + } + + /// + /// 获取对应的本机地址 + /// + /// + public IPAddress? GetLocalAddress() + { + foreach (var @interface in NetworkInterface.GetAllNetworkInterfaces()) + { + var addresses = @interface.GetIPProperties().UnicastAddresses; + foreach (var item in addresses) + { + if (IsInSubNet(item.IPv4Mask, item.Address, this.RemoteAddress)) + { + return item.Address; + } + } + } + return default; + } + + /// + /// 是否在相同的子网里 + /// + /// + /// + /// + /// + private static bool IsInSubNet(IPAddress mask, IPAddress local, IPAddress remote) + { + if (local.AddressFamily != remote.AddressFamily) + { + return false; + } + + var maskValue = GetValue(mask); + var localValue = GetValue(local); + var remoteValue = GetValue(remote); + return (maskValue & localValue) == (maskValue & remoteValue); + + static long GetValue(IPAddress address) + { + var bytes = address.GetAddressBytes(); + return bytes.Length == sizeof(int) + ? BinaryPrimitives.ReadInt32BigEndian(bytes) + : BinaryPrimitives.ReadInt64BigEndian(bytes); + } + } + } +} diff --git a/FastGithub/appsettings.json b/FastGithub/appsettings.json index 3a04cc0..30c7b58 100644 --- a/FastGithub/appsettings.json +++ b/FastGithub/appsettings.json @@ -3,8 +3,7 @@ "UpStream": "114.114.114.114", // dns "GithubTTL": "00:10:00", // githubĴʱ "SetToLocalMachine": true, // Ƿñʹôdns(֧windows) - "UseGithubReverseProxy": true, // Ƿʹ÷githubԽӱظ - "GithubReverseProxyIPAddress": "127.0.0.1" // dnsӦķipʱҪдip + "UseGithubReverseProxy": true // Ƿʹ÷githubԽӱظ }, "Lookup": { // ip "IPAddressComProvider": {