优化DnscryptProxy初始化逻辑

This commit is contained in:
陈国伟 2021-08-27 08:41:29 +08:00
parent bec32d2e35
commit d4f9172574
3 changed files with 51 additions and 36 deletions

View File

@ -25,16 +25,7 @@ namespace FastGithub.DomainResolve
/// <summary> /// <summary>
/// 获取监听的节点 /// 获取监听的节点
/// </summary> /// </summary>
public IPEndPoint EndPoint { get; } public IPEndPoint? LocalEndPoint { get; private set; }
/// <summary>
/// DnscryptProxy服务
/// </summary>
public DnscryptProxy()
{
var port = LocalMachine.GetAvailablePort(IPAddress.Loopback.AddressFamily, min: 5353);
this.EndPoint = new IPEndPoint(IPAddress.Loopback, port);
}
/// <summary> /// <summary>
/// 启动dnscrypt-proxy /// 启动dnscrypt-proxy
@ -44,7 +35,10 @@ namespace FastGithub.DomainResolve
public async Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken)
{ {
var tomlPath = Path.Combine(PATH, $"{NAME}.toml"); var tomlPath = Path.Combine(PATH, $"{NAME}.toml");
await TomlUtil.SetListensAsync(tomlPath, this.EndPoint, cancellationToken); var port = LocalMachine.GetAvailablePort(IPAddress.Loopback.AddressFamily, min: 5353);
var localEndPoint = new IPEndPoint(IPAddress.Loopback, port);
await TomlUtil.SetListensAsync(tomlPath, localEndPoint, cancellationToken);
await TomlUtil.SetEdnsClientSubnetAsync(tomlPath, cancellationToken); await TomlUtil.SetEdnsClientSubnetAsync(tomlPath, cancellationToken);
foreach (var process in Process.GetProcessesByName(NAME)) foreach (var process in Process.GetProcessesByName(NAME))
@ -64,6 +58,23 @@ namespace FastGithub.DomainResolve
{ {
this.process = StartDnscryptProxy(string.Empty); this.process = StartDnscryptProxy(string.Empty);
} }
if (this.process != null)
{
this.LocalEndPoint = localEndPoint;
this.process.EnableRaisingEvents = true;
this.process.Exited += Process_Exited;
}
}
/// <summary>
/// 进程退出时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Process_Exited(object? sender, EventArgs e)
{
this.LocalEndPoint = null;
} }
/// <summary> /// <summary>
@ -81,6 +92,7 @@ namespace FastGithub.DomainResolve
{ {
this.process.Kill(); this.process.Kill();
} }
this.LocalEndPoint = null;
} }
/// <summary> /// <summary>

View File

@ -53,16 +53,16 @@ namespace FastGithub.DomainResolve
/// <summary> /// <summary>
/// 解析域名 /// 解析域名
/// </summary> /// </summary>
/// <param name="endPoint"></param> /// <param name="domain"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public async Task<IPAddress> ResolveAsync(DnsEndPoint endPoint, CancellationToken cancellationToken = default) public async Task<IPAddress> ResolveAsync(DnsEndPoint domain, CancellationToken cancellationToken = default)
{ {
var semaphore = this.semaphoreSlims.GetOrAdd(endPoint, _ => new SemaphoreSlim(1, 1)); var semaphore = this.semaphoreSlims.GetOrAdd(domain, _ => new SemaphoreSlim(1, 1));
try try
{ {
await semaphore.WaitAsync(cancellationToken); await semaphore.WaitAsync(cancellationToken);
return await this.LookupAsync(endPoint, cancellationToken); return await this.LookupAsync(domain, cancellationToken);
} }
finally finally
{ {
@ -73,28 +73,31 @@ namespace FastGithub.DomainResolve
/// <summary> /// <summary>
/// 查找ip /// 查找ip
/// </summary> /// </summary>
/// <param name="target"></param> /// <param name="domain"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<IPAddress> LookupAsync(DnsEndPoint target, CancellationToken cancellationToken) private async Task<IPAddress> LookupAsync(DnsEndPoint domain, CancellationToken cancellationToken)
{ {
if (this.memoryCache.TryGetValue<IPAddress>(target, out var address)) if (this.memoryCache.TryGetValue<IPAddress>(domain, out var address))
{ {
return address; return address;
} }
var expiration = this.dnscryptExpiration; var expiration = this.dnscryptExpiration;
address = await this.LookupCoreAsync(this.dnscryptProxy.EndPoint, target, cancellationToken); if (this.dnscryptProxy.LocalEndPoint != null)
if (address == null)
{ {
expiration = this.fallbackExpiration; address = await this.LookupCoreAsync(this.dnscryptProxy.LocalEndPoint, domain, cancellationToken);
address = await this.FallbackLookupAsync(target, cancellationToken);
} }
if (address == null) if (address == null)
{ {
throw new FastGithubException($"当前解析不到{target.Host}可用的ip请刷新重试"); expiration = this.fallbackExpiration;
address = await this.FallbackLookupAsync(domain, cancellationToken);
}
if (address == null)
{
throw new FastGithubException($"当前解析不到{domain.Host}可用的ip请刷新重试");
} }
// 往往是被污染的dns // 往往是被污染的dns
@ -103,22 +106,22 @@ namespace FastGithub.DomainResolve
expiration = this.loopbackExpiration; expiration = this.loopbackExpiration;
} }
this.logger.LogInformation($"[{target.Host}->{address}]"); this.logger.LogInformation($"[{domain.Host}->{address}]");
this.memoryCache.Set(target, address, expiration); this.memoryCache.Set(domain, address, expiration);
return address; return address;
} }
/// <summary> /// <summary>
/// 回退查找ip /// 回退查找ip
/// </summary> /// </summary>
/// <param name="target"></param> /// <param name="domain"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<IPAddress?> FallbackLookupAsync(DnsEndPoint target, CancellationToken cancellationToken) private async Task<IPAddress?> FallbackLookupAsync(DnsEndPoint domain, CancellationToken cancellationToken)
{ {
foreach (var dns in this.fastGithubConfig.FallbackDns) foreach (var dns in this.fastGithubConfig.FallbackDns)
{ {
var address = await this.LookupCoreAsync(dns, target, cancellationToken); var address = await this.LookupCoreAsync(dns, domain, cancellationToken);
if (address != null) if (address != null)
{ {
return address; return address;
@ -132,22 +135,22 @@ namespace FastGithub.DomainResolve
/// 查找ip /// 查找ip
/// </summary> /// </summary>
/// <param name="dns"></param> /// <param name="dns"></param>
/// <param name="target"></param> /// <param name="domain"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task<IPAddress?> LookupCoreAsync(IPEndPoint dns, DnsEndPoint target, CancellationToken cancellationToken) private async Task<IPAddress?> LookupCoreAsync(IPEndPoint dns, DnsEndPoint domain, CancellationToken cancellationToken)
{ {
try try
{ {
var dnsClient = new DnsClient(dns); var dnsClient = new DnsClient(dns);
using var timeoutTokenSource = new CancellationTokenSource(this.lookupTimeout); using var timeoutTokenSource = new CancellationTokenSource(this.lookupTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token);
var addresses = await dnsClient.Lookup(target.Host, RecordType.A, linkedTokenSource.Token); var addresses = await dnsClient.Lookup(domain.Host, RecordType.A, linkedTokenSource.Token);
return await this.FindFastValueAsync(addresses, target.Port, cancellationToken); return await this.FindFastValueAsync(addresses, domain.Port, cancellationToken);
} }
catch (Exception ex) catch (Exception ex)
{ {
this.logger.LogWarning($"dns({dns})无法解析{target.Host}{ex.Message}"); this.logger.LogWarning($"dns({dns})无法解析{domain.Host}{ex.Message}");
return default; return default;
} }
} }

View File

@ -12,9 +12,9 @@ namespace FastGithub.DomainResolve
/// <summary> /// <summary>
/// 解析域名 /// 解析域名
/// </summary> /// </summary>
/// <param name="target"></param> /// <param name="domain"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
Task<IPAddress> ResolveAsync(DnsEndPoint target, CancellationToken cancellationToken = default); Task<IPAddress> ResolveAsync(DnsEndPoint domain, CancellationToken cancellationToken = default);
} }
} }