增强dns返回的ip的稳定性
This commit is contained in:
parent
3d20996d4b
commit
42458fd25a
@ -5,11 +5,26 @@ namespace FastGithub.Scanner
|
|||||||
{
|
{
|
||||||
sealed class GithubContext : IEquatable<GithubContext>
|
sealed class GithubContext : IEquatable<GithubContext>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取域名
|
||||||
|
/// </summary>
|
||||||
public string Domain { get; }
|
public string Domain { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取ip
|
||||||
|
/// </summary>
|
||||||
public IPAddress Address { get; }
|
public IPAddress Address { get; }
|
||||||
|
|
||||||
public TimeSpan? HttpElapsed { get; set; }
|
/// <summary>
|
||||||
|
/// 获取或设置是否可用
|
||||||
|
/// </summary>
|
||||||
|
public bool Available { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取或设置扫描总耗时
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Elapsed { get; set; } = TimeSpan.MaxValue;
|
||||||
|
|
||||||
|
|
||||||
public GithubContext(string domain, IPAddress address)
|
public GithubContext(string domain, IPAddress address)
|
||||||
{
|
{
|
||||||
@ -19,7 +34,7 @@ namespace FastGithub.Scanner
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{Address}\t{Domain}\t# {HttpElapsed}";
|
return $"{Address}\t{Domain}\t# {Elapsed}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
public override bool Equals(object? obj)
|
||||||
|
|||||||
66
FastGithub.Scanner/GithubContextCollection.cs
Normal file
66
FastGithub.Scanner/GithubContextCollection.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace FastGithub.Scanner
|
||||||
|
{
|
||||||
|
sealed class GithubContextCollection
|
||||||
|
{
|
||||||
|
private readonly object syncRoot = new();
|
||||||
|
private readonly HashSet<GithubContext> contextHashSet = new();
|
||||||
|
private readonly Dictionary<string, IPAddress> domainAdressCache = new();
|
||||||
|
|
||||||
|
public bool Add(GithubContext context)
|
||||||
|
{
|
||||||
|
lock (this.syncRoot)
|
||||||
|
{
|
||||||
|
return this.contextHashSet.Add(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GithubContext[] ToArray()
|
||||||
|
{
|
||||||
|
lock (this.syncRoot)
|
||||||
|
{
|
||||||
|
return this.contextHashSet.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找又稳又快的ip
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="domain"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IPAddress? FindFastAddress(string domain)
|
||||||
|
{
|
||||||
|
lock (this.syncRoot)
|
||||||
|
{
|
||||||
|
// 如果上一次的ip可以使用,就返回上一次的ip
|
||||||
|
if (this.domainAdressCache.TryGetValue(domain, out var address))
|
||||||
|
{
|
||||||
|
var key = new GithubContext(domain, address);
|
||||||
|
if (this.contextHashSet.TryGetValue(key, out var context) && context.Available)
|
||||||
|
{
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fastAddress = this.contextHashSet
|
||||||
|
.Where(item => item.Available && item.Domain == domain)
|
||||||
|
.OrderBy(item => item.Elapsed)
|
||||||
|
.Select(item => item.Address)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (fastAddress != null)
|
||||||
|
{
|
||||||
|
this.domainAdressCache[domain] = fastAddress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.domainAdressCache.Remove(domain);
|
||||||
|
}
|
||||||
|
return fastAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace FastGithub.Scanner
|
|
||||||
{
|
|
||||||
sealed class GithubContextHashSet : HashSet<GithubContext>
|
|
||||||
{
|
|
||||||
public readonly object SyncRoot = new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -14,7 +14,7 @@ namespace FastGithub.Scanner
|
|||||||
{
|
{
|
||||||
private readonly GithubMetaService metaService;
|
private readonly GithubMetaService metaService;
|
||||||
private readonly ILogger<GithubScanService> logger;
|
private readonly ILogger<GithubScanService> logger;
|
||||||
private readonly GithubContextHashSet results = new();
|
private readonly GithubContextCollection results = new();
|
||||||
|
|
||||||
private readonly InvokeDelegate<GithubContext> fullScanDelegate;
|
private readonly InvokeDelegate<GithubContext> fullScanDelegate;
|
||||||
private readonly InvokeDelegate<GithubContext> resultScanDelegate;
|
private readonly InvokeDelegate<GithubContext> resultScanDelegate;
|
||||||
@ -30,6 +30,7 @@ namespace FastGithub.Scanner
|
|||||||
this.fullScanDelegate = pipelineBuilder
|
this.fullScanDelegate = pipelineBuilder
|
||||||
.New()
|
.New()
|
||||||
.Use<ConcurrentMiddleware>()
|
.Use<ConcurrentMiddleware>()
|
||||||
|
.Use<ScanElapsedMiddleware>()
|
||||||
.Use<PortScanMiddleware>()
|
.Use<PortScanMiddleware>()
|
||||||
.Use<HttpsScanMiddleware>()
|
.Use<HttpsScanMiddleware>()
|
||||||
.Use<ScanOkLogMiddleware>()
|
.Use<ScanOkLogMiddleware>()
|
||||||
@ -37,6 +38,7 @@ namespace FastGithub.Scanner
|
|||||||
|
|
||||||
this.resultScanDelegate = pipelineBuilder
|
this.resultScanDelegate = pipelineBuilder
|
||||||
.New()
|
.New()
|
||||||
|
.Use<ScanElapsedMiddleware>()
|
||||||
.Use<PortScanMiddleware>()
|
.Use<PortScanMiddleware>()
|
||||||
.Use<HttpsScanMiddleware>()
|
.Use<HttpsScanMiddleware>()
|
||||||
.Use<ScanOkLogMiddleware>()
|
.Use<ScanOkLogMiddleware>()
|
||||||
@ -58,12 +60,9 @@ namespace FastGithub.Scanner
|
|||||||
async Task ScanAsync(GithubContext context)
|
async Task ScanAsync(GithubContext context)
|
||||||
{
|
{
|
||||||
await this.fullScanDelegate(context);
|
await this.fullScanDelegate(context);
|
||||||
if (context.HttpElapsed != null)
|
if (context.Available == true)
|
||||||
{
|
{
|
||||||
lock (this.results.SyncRoot)
|
this.results.Add(context);
|
||||||
{
|
|
||||||
this.results.Add(context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,15 +70,10 @@ namespace FastGithub.Scanner
|
|||||||
public async Task ScanResultAsync()
|
public async Task ScanResultAsync()
|
||||||
{
|
{
|
||||||
this.logger.LogInformation("结果扫描开始");
|
this.logger.LogInformation("结果扫描开始");
|
||||||
GithubContext[] contexts;
|
|
||||||
lock (this.results.SyncRoot)
|
|
||||||
{
|
|
||||||
contexts = this.results.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var contexts = this.results.ToArray();
|
||||||
foreach (var context in contexts)
|
foreach (var context in contexts)
|
||||||
{
|
{
|
||||||
context.HttpElapsed = null;
|
|
||||||
await this.resultScanDelegate(context);
|
await this.resultScanDelegate(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,19 +82,9 @@ namespace FastGithub.Scanner
|
|||||||
|
|
||||||
public IPAddress? FindFastAddress(string domain)
|
public IPAddress? FindFastAddress(string domain)
|
||||||
{
|
{
|
||||||
if (domain.Contains("github", StringComparison.OrdinalIgnoreCase))
|
return domain.Contains("github", StringComparison.OrdinalIgnoreCase)
|
||||||
{
|
? this.results.FindFastAddress(domain)
|
||||||
lock (this.results.SyncRoot)
|
: default;
|
||||||
{
|
|
||||||
return this.results
|
|
||||||
.Where(item => item.Domain == domain && item.HttpElapsed != null)
|
|
||||||
.OrderBy(item => item.HttpElapsed)
|
|
||||||
.Select(item => item.Address)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,8 @@ namespace FastGithub.Scanner.Middlewares
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
context.Available = false;
|
||||||
|
|
||||||
var request = new HttpRequestMessage
|
var request = new HttpRequestMessage
|
||||||
{
|
{
|
||||||
Method = HttpMethod.Get,
|
Method = HttpMethod.Get,
|
||||||
@ -40,13 +42,12 @@ namespace FastGithub.Scanner.Middlewares
|
|||||||
UseProxy = false,
|
UseProxy = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
var startTime = DateTime.Now;
|
|
||||||
using var cancellationTokenSource = new CancellationTokenSource(this.options.CurrentValue.HttpsScanTimeout);
|
using var cancellationTokenSource = new CancellationTokenSource(this.options.CurrentValue.HttpsScanTimeout);
|
||||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token);
|
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token);
|
||||||
var server = response.EnsureSuccessStatusCode().Headers.Server;
|
var server = response.EnsureSuccessStatusCode().Headers.Server;
|
||||||
if (server.Any(s => string.Equals("GitHub.com", s.Product?.Name, StringComparison.OrdinalIgnoreCase)))
|
if (server.Any(s => string.Equals("GitHub.com", s.Product?.Name, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
context.HttpElapsed = DateTime.Now.Subtract(startTime);
|
context.Available = true;
|
||||||
await next();
|
await next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
FastGithub.Scanner/Middlewares/ScanElapsedMiddleware.cs
Normal file
26
FastGithub.Scanner/Middlewares/ScanElapsedMiddleware.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FastGithub.Scanner.Middlewares
|
||||||
|
{
|
||||||
|
[Service(ServiceLifetime.Singleton)]
|
||||||
|
sealed class ScanElapsedMiddleware : IMiddleware<GithubContext>
|
||||||
|
{
|
||||||
|
public async Task InvokeAsync(GithubContext context, Func<Task> next)
|
||||||
|
{
|
||||||
|
var stopwatch = new Stopwatch();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
stopwatch.Start();
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stopwatch.Stop();
|
||||||
|
context.Elapsed = stopwatch.Elapsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@ namespace FastGithub.Scanner.Middlewares
|
|||||||
|
|
||||||
public Task InvokeAsync(GithubContext context, Func<Task> next)
|
public Task InvokeAsync(GithubContext context, Func<Task> next)
|
||||||
{
|
{
|
||||||
if (context.HttpElapsed != null)
|
if (context.Available)
|
||||||
{
|
{
|
||||||
this.logger.LogInformation(context.ToString());
|
this.logger.LogInformation(context.ToString());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user