自动侦测本机ip做为dns响应值

This commit is contained in:
陈国伟 2021-07-15 17:10:36 +08:00
parent 4ce79fa5d6
commit 2bacf5a4fc
5 changed files with 124 additions and 33 deletions

View File

@ -40,7 +40,9 @@ namespace FastGithub.Dns
{ {
this.options = options; this.options = options;
this.logger = logger; 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);
} }
/// <summary> /// <summary>
@ -57,7 +59,8 @@ namespace FastGithub.Dns
} }
this.logger.LogInformation("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); return base.StartAsync(cancellationToken);
} }
@ -74,7 +77,7 @@ namespace FastGithub.Dns
var result = await this.socket.ReceiveFromAsync(this.buffer, SocketFlags.None, remoteEndPoint); var result = await this.socket.ReceiveFromAsync(this.buffer, SocketFlags.None, remoteEndPoint);
var datas = new byte[result.ReceivedBytes]; var datas = new byte[result.ReceivedBytes];
this.buffer.AsSpan(0, datas.Length).CopyTo(datas); 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
/// <param name="datas"></param> /// <param name="datas"></param>
/// <param name="remoteEndPoint"></param> /// <param name="remoteEndPoint"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
private async void HandleRequestAsync(byte[] datas, EndPoint remoteEndPoint, CancellationToken cancellationToken) private async void HandleRequestAsync(byte[] datas, IPEndPoint remoteEndPoint, CancellationToken cancellationToken)
{ {
try try
{ {
var request = Request.FromArray(datas); 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); await this.socket.SendToAsync(response.ToArray(), SocketFlags.None, remoteEndPoint);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Net;
namespace FastGithub.Dns namespace FastGithub.Dns
{ {
@ -28,10 +27,5 @@ namespace FastGithub.Dns
/// 是否使用反向代理访问github /// 是否使用反向代理访问github
/// </summary> /// </summary>
public bool UseGithubReverseProxy { get; set; } = true; public bool UseGithubReverseProxy { get; set; } = true;
/// <summary>
/// dns响应的反向代理服务的ip
/// </summary>
public string GithubReverseProxyIPAddress { get; set; } = IPAddress.Loopback.ToString();
} }
} }

View File

@ -48,38 +48,55 @@ namespace FastGithub.Dns
public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default) public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default)
{ {
IResponse response = Response.FromRequest(request); 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) if (question == null || question.Type != RecordType.A)
{ {
return Task.FromResult(response); return Task.FromResult(response);
} }
var domain = question.Name.ToString(); var domain = question.Name;
if (this.githubResolver.IsSupported(domain) == false) if (this.githubResolver.IsSupported(domain.ToString()) == false)
{ {
return Task.FromResult(response); 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); this.logger.LogInformation($"[{domain}->{record.IPAddress}]");
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));
response.AnswerRecords.Add(record); response.AnswerRecords.Add(record);
this.logger.LogInformation($"[{domain}->{address}]");
} }
return Task.FromResult(response); return Task.FromResult(response);
} }
/// <summary>
/// 获取答案
/// </summary>
/// <param name="request"></param>
/// <param name="domain"></param>
/// <returns></returns>
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);
}
} }
} }

View File

@ -0,0 +1,77 @@
using DNS.Protocol;
using System.Buffers.Binary;
using System.Net;
using System.Net.NetworkInformation;
namespace FastGithub.Dns
{
/// <summary>
/// 远程请求
/// </summary>
sealed class RemoteRequest : Request
{
/// <summary>
/// 获取远程地址
/// </summary>
public IPAddress RemoteAddress { get; }
/// <summary>
/// 远程请求
/// </summary>
/// <param name="request"></param>
/// <param name="remoteAddress"></param>
public RemoteRequest(Request request, IPAddress remoteAddress)
: base(request)
{
this.RemoteAddress = remoteAddress;
}
/// <summary>
/// 获取对应的本机地址
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 是否在相同的子网里
/// </summary>
/// <param name="mask"></param>
/// <param name="local"></param>
/// <param name="remote"></param>
/// <returns></returns>
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);
}
}
}
}

View File

@ -3,8 +3,7 @@
"UpStream": "114.114.114.114", // dns "UpStream": "114.114.114.114", // dns
"GithubTTL": "00:10:00", // github "GithubTTL": "00:10:00", // github
"SetToLocalMachine": true, // 使dns(windows) "SetToLocalMachine": true, // 使dns(windows)
"UseGithubReverseProxy": true, // 使访github "UseGithubReverseProxy": true // 使访github
"GithubReverseProxyIPAddress": "127.0.0.1" // dnsipip
}, },
"Lookup": { // ip "Lookup": { // ip
"IPAddressComProvider": { "IPAddressComProvider": {