FastGithub/FastGithub.Dns/GithubRequestResolver.cs
2021-06-16 19:57:20 +08:00

88 lines
2.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DNS.Client.RequestResolver;
using DNS.Protocol;
using DNS.Protocol.ResourceRecords;
using FastGithub.Scanner;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub.Dns
{
[Service(ServiceLifetime.Singleton)]
sealed class GithubRequestResolver : IRequestResolver
{
private readonly IGithubScanResults githubScanResults;
private readonly IMemoryCache memoryCache;
private readonly ILogger<GithubRequestResolver> logger;
private readonly TimeSpan TTL = TimeSpan.FromMinutes(10d);
public GithubRequestResolver(
IGithubScanResults githubScanResults,
IMemoryCache memoryCache,
ILogger<GithubRequestResolver> logger)
{
this.githubScanResults = githubScanResults;
this.memoryCache = memoryCache;
this.logger = logger;
}
public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default)
{
var response = Response.FromRequest(request);
var question = request.Questions.FirstOrDefault();
if (question != null && question.Type == RecordType.A)
{
var domain = question.Name.ToString();
var address = this.GetGithubAddress(domain, TTL);
if (address != null)
{
var record = new IPAddressResourceRecord(question.Name, address);
response.AnswerRecords.Add(record);
this.logger.LogInformation(record.ToString());
}
}
return Task.FromResult<IResponse>(response);
}
/// <summary>
/// 模拟TTL
/// 如果ip可用则10分钟内返回缓存的ip防止客户端ip频繁切换
/// </summary>
/// <param name="domain"></param>
/// <param name="ttl"></param>
/// <returns></returns>
private IPAddress? GetGithubAddress(string domain, TimeSpan ttl)
{
if (domain.Contains("github", StringComparison.OrdinalIgnoreCase) == false)
{
return default;
}
var key = $"ttl:{domain}";
if (this.memoryCache.TryGetValue<IPAddress>(key, out var address))
{
if (this.githubScanResults.IsAvailable(domain, address))
{
return address;
}
this.memoryCache.Remove(key);
}
address = this.githubScanResults.FindBestAddress(domain);
if (address != null)
{
this.memoryCache.Set(key, address, ttl);
}
return address;
}
}
}