集成dns

This commit is contained in:
陈国伟 2021-06-15 15:01:00 +08:00
parent 3c0ee74be5
commit d2189462b0
22 changed files with 258 additions and 153 deletions

View File

@ -0,0 +1,79 @@
using DNS.Client.RequestResolver;
using DNS.Protocol;
using DNS.Protocol.ResourceRecords;
using DNS.Server;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class DnsHostedService : IHostedService, IRequestResolver
{
private readonly DnsServer dnsServer;
private readonly GithubScanService githubScanService;
private readonly ILogger<DnsHostedService> logger;
public DnsHostedService(
GithubScanService githubScanService,
IOptions<DnsOptions> options,
ILogger<DnsHostedService> logger)
{
this.dnsServer = new DnsServer(this, options.Value.UpStream);
this.githubScanService = githubScanService;
this.logger = logger;
}
/// <summary>
/// 解析dns
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IResponse> IRequestResolver.Resolve(IRequest request, CancellationToken cancellationToken)
{
var response = Response.FromRequest(request);
var question = request.Questions.FirstOrDefault();
if (question != null && question.Type == RecordType.A)
{
var domain = question.Name.ToString();
if (domain.Contains("github", StringComparison.OrdinalIgnoreCase))
{
var contexts = this.githubScanService.Result
.Where(item => item.Domain == domain)
.OrderBy(item => item.HttpElapsed);
foreach (var context in contexts)
{
var record = new IPAddressResourceRecord(question.Name, context.Address, TimeSpan.FromMinutes(2d));
response.AnswerRecords.Add(record);
this.logger.LogWarning(record.ToString());
}
return Task.FromResult<IResponse>(response);
}
}
return Task.FromResult<IResponse>(response);
}
public Task StartAsync(CancellationToken cancellationToken)
{
this.dnsServer.Listen();
this.logger.LogInformation("dns服务启用成功");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
this.dnsServer.Dispose();
this.logger.LogInformation("dns服务已终止");
return Task.CompletedTask;
}
}
}

9
FastGithub/DnsOptions.cs Normal file
View File

@ -0,0 +1,9 @@
using System.Net;
namespace FastGithub
{
class DnsOptions
{
public IPAddress UpStream { get; set; } = IPAddress.Parse("114.114.114.114");
}
}

View File

@ -3,15 +3,16 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile> <EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<Version>1.0.1</Version> <Version>1.0.2</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DNS" Version="6.1.0" />
<PackageReference Include="IPNetwork2" Version="2.5.320" /> <PackageReference Include="IPNetwork2" Version="2.5.320" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0-preview.4.21253.7" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0-preview.4.21253.7" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,19 +1,22 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Net; using System.Net;
namespace FastGithub namespace FastGithub
{ {
class GithubContext class GithubContext
{ {
[AllowNull] public string Domain { get; }
public string Domain { get; set; }
[AllowNull] public IPAddress Address { get; }
public IPAddress Address { get; set; }
public TimeSpan? HttpElapsed { get; set; } public TimeSpan? HttpElapsed { get; set; }
public GithubContext(string domain,IPAddress address)
{
this.Domain = domain;
this.Address = address;
}
public override string ToString() public override string ToString()
{ {
return $"{Address}\t{Domain}\t# {HttpElapsed}"; return $"{Address}\t{Domain}\t# {HttpElapsed}";

View File

@ -1,35 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class GithubHostedService : IHostedService
{
private readonly IServiceScopeFactory serviceScopeFactory;
private readonly IHostApplicationLifetime hostApplicationLifetime;
public GithubHostedService(
IServiceScopeFactory serviceScopeFactory,
IHostApplicationLifetime hostApplicationLifetime)
{
this.serviceScopeFactory = serviceScopeFactory;
this.hostApplicationLifetime = hostApplicationLifetime;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
var scope = this.serviceScopeFactory.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<GithubService>();
await service.ScanAddressAsync(cancellationToken);
this.hostApplicationLifetime.StopApplication();
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

View File

@ -4,8 +4,12 @@ namespace FastGithub
{ {
class GithubOptions class GithubOptions
{ {
public TimeSpan ScanAllInterval { get; set; } = TimeSpan.FromHours(12d);
public TimeSpan ScanResultInterval { get; set; } = TimeSpan.FromMinutes(5d);
public Uri MetaUri { get; set; } = new Uri("https://gitee.com/jiulang/fast-github/raw/master/FastGithub/meta.json"); public Uri MetaUri { get; set; } = new Uri("https://gitee.com/jiulang/fast-github/raw/master/FastGithub/meta.json");
public TimeSpan PortScanTimeout { get; set; } = TimeSpan.FromSeconds(1d); public TimeSpan PortScanTimeout { get; set; } = TimeSpan.FromSeconds(1d);
public TimeSpan HttpsScanTimeout { get; set; } = TimeSpan.FromSeconds(5d); public TimeSpan HttpsScanTimeout { get; set; } = TimeSpan.FromSeconds(5d);

View File

@ -0,0 +1,31 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class GithubScanAllHostedService : BackgroundService
{
private readonly GithubScanService githubScanService;
private readonly IOptionsMonitor<GithubOptions> options;
public GithubScanAllHostedService(
GithubScanService githubScanService,
IOptionsMonitor<GithubOptions> options)
{
this.githubScanService = githubScanService;
this.options = options;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (stoppingToken.IsCancellationRequested == false)
{
await githubScanService.ScanAllAsync(stoppingToken);
await Task.Delay(this.options.CurrentValue.ScanResultInterval, stoppingToken);
}
}
}
}

View File

@ -7,10 +7,10 @@ namespace FastGithub
/// <summary> /// <summary>
/// 表示中间件创建者 /// 表示中间件创建者
/// </summary> /// </summary>
sealed class GithubBuilder : IGithubBuilder sealed class GithubScanBuilder : IGithubScanBuilder
{ {
private readonly GithubDelegate completedHandler; private readonly GithubScanDelegate completedHandler;
private readonly List<Func<GithubDelegate, GithubDelegate>> middlewares = new(); private readonly List<Func<GithubScanDelegate, GithubScanDelegate>> middlewares = new();
/// <summary> /// <summary>
/// 获取服务提供者 /// 获取服务提供者
@ -21,7 +21,7 @@ namespace FastGithub
/// 中间件创建者 /// 中间件创建者
/// </summary> /// </summary>
/// <param name="appServices"></param> /// <param name="appServices"></param>
public GithubBuilder(IServiceProvider appServices) public GithubScanBuilder(IServiceProvider appServices)
: this(appServices, context => Task.CompletedTask) : this(appServices, context => Task.CompletedTask)
{ {
} }
@ -31,7 +31,7 @@ namespace FastGithub
/// </summary> /// </summary>
/// <param name="appServices"></param> /// <param name="appServices"></param>
/// <param name="completedHandler">完成执行内容处理者</param> /// <param name="completedHandler">完成执行内容处理者</param>
public GithubBuilder(IServiceProvider appServices, GithubDelegate completedHandler) public GithubScanBuilder(IServiceProvider appServices, GithubScanDelegate completedHandler)
{ {
this.AppServices = appServices; this.AppServices = appServices;
this.completedHandler = completedHandler; this.completedHandler = completedHandler;
@ -42,7 +42,7 @@ namespace FastGithub
/// </summary> /// </summary>
/// <param name="middleware"></param> /// <param name="middleware"></param>
/// <returns></returns> /// <returns></returns>
public IGithubBuilder Use(Func<GithubDelegate, GithubDelegate> middleware) public IGithubScanBuilder Use(Func<GithubScanDelegate, GithubScanDelegate> middleware)
{ {
this.middlewares.Add(middleware); this.middlewares.Add(middleware);
return this; return this;
@ -53,7 +53,7 @@ namespace FastGithub
/// 创建所有中间件执行处理者 /// 创建所有中间件执行处理者
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public GithubDelegate Build() public GithubScanDelegate Build()
{ {
var handler = this.completedHandler; var handler = this.completedHandler;
for (var i = this.middlewares.Count - 1; i >= 0; i--) for (var i = this.middlewares.Count - 1; i >= 0; i--)

View File

@ -6,7 +6,7 @@ namespace FastGithub
/// <summary> /// <summary>
/// 中间件创建者扩展 /// 中间件创建者扩展
/// </summary> /// </summary>
static class GithubBuilderExtensions static class GithubScanBuilderExtensions
{ {
/// <summary> /// <summary>
/// 使用中间件 /// 使用中间件
@ -14,7 +14,7 @@ namespace FastGithub
/// <typeparam name="TMiddleware"></typeparam> /// <typeparam name="TMiddleware"></typeparam>
/// <param name="builder"></param> /// <param name="builder"></param>
/// <returns></returns> /// <returns></returns>
public static IGithubBuilder Use<TMiddleware>(this IGithubBuilder builder) where TMiddleware : class, IGithubMiddleware public static IGithubScanBuilder Use<TMiddleware>(this IGithubScanBuilder builder) where TMiddleware : class, IGithubScanMiddleware
{ {
return builder.AppServices.GetService(typeof(TMiddleware)) is TMiddleware middleware return builder.AppServices.GetService(typeof(TMiddleware)) is TMiddleware middleware
? builder.Use(middleware.InvokeAsync) ? builder.Use(middleware.InvokeAsync)
@ -28,7 +28,7 @@ namespace FastGithub
/// <param name="builder"></param> /// <param name="builder"></param>
/// <param name="middleware"></param> /// <param name="middleware"></param>
/// <returns></returns> /// <returns></returns>
public static IGithubBuilder Use(this IGithubBuilder builder, Func<GithubContext, Func<Task>, Task> middleware) public static IGithubScanBuilder Use(this IGithubScanBuilder builder, Func<GithubContext, Func<Task>, Task> middleware)
{ {
return builder.Use(next => context => middleware(context, () => next(context))); return builder.Use(next => context => middleware(context, () => next(context)));
} }

View File

@ -7,5 +7,5 @@ namespace FastGithub
/// </summary> /// </summary>
/// <param name="context">中间件上下文</param> /// <param name="context">中间件上下文</param>
/// <returns></returns> /// <returns></returns>
delegate Task GithubDelegate(GithubContext context); delegate Task GithubScanDelegate(GithubContext context);
} }

View File

@ -0,0 +1,30 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class GithubScanResultHostedService : BackgroundService
{
private readonly GithubScanService githubScanService;
private readonly IOptionsMonitor<GithubOptions> options;
public GithubScanResultHostedService(
GithubScanService githubScanService,
IOptionsMonitor<GithubOptions> options)
{
this.githubScanService = githubScanService;
this.options = options;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (stoppingToken.IsCancellationRequested == false)
{
await Task.Delay(this.options.CurrentValue.ScanResultInterval, stoppingToken);
await githubScanService.ScanResultAsync();
}
}
}
}

View File

@ -0,0 +1,51 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class GithubScanService
{
private readonly GithubMetaService metaService;
private readonly GithubScanDelegate scanDelegate;
public ConcurrentQueue<GithubContext> Result { get; } = new();
public GithubScanService(
GithubMetaService metaService,
GithubScanDelegate scanDelegate)
{
this.metaService = metaService;
this.scanDelegate = scanDelegate;
}
public async Task ScanAllAsync(CancellationToken cancellationToken = default)
{
var meta = await this.metaService.GetMetaAsync(cancellationToken);
if (meta != null)
{
this.Result.Clear();
var scanTasks = meta.ToGithubContexts().Select(ctx => ScanAsync(ctx));
await Task.WhenAll(scanTasks);
}
}
public async Task ScanResultAsync()
{
while (this.Result.TryDequeue(out var context))
{
await this.ScanAsync(context);
}
}
private async Task ScanAsync(GithubContext context)
{
await this.scanDelegate(context);
if (context.HttpElapsed != null)
{
this.Result.Enqueue(context);
}
}
}
}

View File

@ -1,73 +0,0 @@
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace FastGithub
{
sealed class GithubService
{
private readonly GithubMetaService githubMetaService;
private readonly GithubDelegate githubDelegate;
private readonly ILogger<GithubService> logger;
public GithubService(
GithubMetaService githubMetaService,
GithubDelegate githubDelegate,
ILogger<GithubService> logger)
{
this.githubMetaService = githubMetaService;
this.githubDelegate = githubDelegate;
this.logger = logger;
}
public async Task ScanAddressAsync(CancellationToken cancellationToken = default)
{
var meta = await this.githubMetaService.GetMetaAsync(cancellationToken);
if (meta != null)
{
var scanTasks = this.GetMetaScanTasks(meta);
var contexts = await Task.WhenAll(scanTasks);
var sortedContexts = contexts
.Where(item => item.HttpElapsed != null)
.OrderBy(item => item.Domain)
.ThenBy(item => item.HttpElapsed);
using var fileStream = File.OpenWrite("github.txt");
using var fileWriter = new StreamWriter(fileStream);
foreach (var context in sortedContexts)
{
var message = context.ToString();
await fileWriter.WriteLineAsync(message);
}
}
this.logger.LogInformation("扫描结束");
}
private IEnumerable<Task<GithubContext>> GetMetaScanTasks(Meta meta)
{
foreach (var item in meta.ToDomainAddress())
{
var context = new GithubContext
{
Domain = item.Domain,
Address = item.Address,
};
yield return InvokeAsync(context);
}
async Task<GithubContext> InvokeAsync(GithubContext context)
{
await this.githubDelegate(context);
return context;
}
}
}
}

View File

@ -5,7 +5,7 @@ namespace FastGithub
/// <summary> /// <summary>
/// 定义中间件管道创建者的接口 /// 定义中间件管道创建者的接口
/// </summary> /// </summary>
interface IGithubBuilder interface IGithubScanBuilder
{ {
/// <summary> /// <summary>
/// 获取服务提供者 /// 获取服务提供者
@ -17,12 +17,12 @@ namespace FastGithub
/// </summary> /// </summary>
/// <param name="middleware">中间件</param> /// <param name="middleware">中间件</param>
/// <returns></returns> /// <returns></returns>
IGithubBuilder Use(Func<GithubDelegate, GithubDelegate> middleware); IGithubScanBuilder Use(Func<GithubScanDelegate, GithubScanDelegate> middleware);
/// <summary> /// <summary>
/// 创建所有中间件执行处理者 /// 创建所有中间件执行处理者
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
GithubDelegate Build(); GithubScanDelegate Build();
} }
} }

View File

@ -6,7 +6,7 @@ namespace FastGithub
/// <summary> /// <summary>
/// 定义中间件的接口 /// 定义中间件的接口
/// </summary> /// </summary>
interface IGithubMiddleware interface IGithubScanMiddleware
{ {
/// <summary> /// <summary>
/// 执行中间件 /// 执行中间件

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -37,7 +36,7 @@ namespace FastGithub
public string[] Dependabot { get; set; } = Array.Empty<string>(); public string[] Dependabot { get; set; } = Array.Empty<string>();
public IEnumerable<DomainAddress> ToDomainAddress() public IEnumerable<GithubContext> ToGithubContexts()
{ {
foreach (var range in IPRange.From(this.Web).OrderBy(item => item.Size)) foreach (var range in IPRange.From(this.Web).OrderBy(item => item.Size))
{ {
@ -45,7 +44,7 @@ namespace FastGithub
{ {
foreach (var address in range) foreach (var address in range)
{ {
yield return new DomainAddress("github.com", address); yield return new GithubContext("github.com", address);
} }
} }
} }
@ -56,12 +55,10 @@ namespace FastGithub
{ {
foreach (var address in range) foreach (var address in range)
{ {
yield return new DomainAddress("api.github.com", address); yield return new GithubContext("api.github.com", address);
} }
} }
} }
} }
public record DomainAddress(string Domain, IPAddress Address);
} }
} }

View File

@ -4,7 +4,7 @@ using System.Threading.Tasks;
namespace FastGithub.Middlewares namespace FastGithub.Middlewares
{ {
sealed class ConcurrentMiddleware : IGithubMiddleware sealed class ConcurrentMiddleware : IGithubScanMiddleware
{ {
private readonly SemaphoreSlim semaphoreSlim = new(Environment.ProcessorCount * 4); private readonly SemaphoreSlim semaphoreSlim = new(Environment.ProcessorCount * 4);

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace FastGithub.Middlewares namespace FastGithub.Middlewares
{ {
sealed class HttpsScanMiddleware : IGithubMiddleware sealed class HttpsScanMiddleware : IGithubScanMiddleware
{ {
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
private readonly ILogger<HttpsScanMiddleware> logger; private readonly ILogger<HttpsScanMiddleware> logger;
@ -50,11 +50,11 @@ namespace FastGithub.Middlewares
} }
catch (TaskCanceledException) catch (TaskCanceledException)
{ {
this.logger.LogInformation($"{context.Domain} {context.Address}连接超时"); this.logger.LogTrace($"{context.Domain} {context.Address}连接超时");
} }
catch (Exception ex) catch (Exception ex)
{ {
this.logger.LogInformation($"{context.Domain} {context.Address} {ex.Message}"); this.logger.LogTrace($"{context.Domain} {context.Address} {ex.Message}");
} }
} }
} }

View File

@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace FastGithub.Middlewares namespace FastGithub.Middlewares
{ {
sealed class PortScanMiddleware : IGithubMiddleware sealed class PortScanMiddleware : IGithubScanMiddleware
{ {
private const int PORT = 443; private const int PORT = 443;
private readonly IOptionsMonitor<GithubOptions> options; private readonly IOptionsMonitor<GithubOptions> options;
@ -33,7 +33,7 @@ namespace FastGithub.Middlewares
} }
catch (Exception) catch (Exception)
{ {
this.logger.LogInformation($"{context.Domain} {context.Address}的{PORT}端口未开放"); this.logger.LogTrace($"{context.Domain} {context.Address}的{PORT}端口未开放");
} }
} }
} }

View File

@ -4,7 +4,7 @@ using System.Threading.Tasks;
namespace FastGithub.Middlewares namespace FastGithub.Middlewares
{ {
sealed class ScanOkLogMiddleware : IGithubMiddleware sealed class ScanOkLogMiddleware : IGithubScanMiddleware
{ {
private readonly ILogger<ScanOkLogMiddleware> logger; private readonly ILogger<ScanOkLogMiddleware> logger;
@ -17,7 +17,7 @@ namespace FastGithub.Middlewares
{ {
if (context.HttpElapsed != null) if (context.HttpElapsed != null)
{ {
this.logger.LogWarning(context.ToString()); this.logger.LogInformation(context.ToString());
} }
return next(); return next();

View File

@ -28,10 +28,11 @@ namespace FastGithub
.ConfigureServices((ctx, services) => .ConfigureServices((ctx, services) =>
{ {
services services
.Configure<DnsOptions>(ctx.Configuration.GetSection("Dns"))
.Configure<GithubOptions>(ctx.Configuration.GetSection("Github")) .Configure<GithubOptions>(ctx.Configuration.GetSection("Github"))
.AddHttpClient() .AddHttpClient()
.AddTransient<GithubMetaService>() .AddSingleton<GithubMetaService>()
.AddTransient<GithubService>() .AddSingleton<GithubScanService>()
.AddSingleton<PortScanMiddleware>() .AddSingleton<PortScanMiddleware>()
.AddSingleton<HttpsScanMiddleware>() .AddSingleton<HttpsScanMiddleware>()
@ -39,14 +40,16 @@ namespace FastGithub
.AddSingleton<ScanOkLogMiddleware>() .AddSingleton<ScanOkLogMiddleware>()
.AddSingleton(serviceProvider => .AddSingleton(serviceProvider =>
{ {
return new GithubBuilder(serviceProvider, ctx => Task.CompletedTask) return new GithubScanBuilder(serviceProvider, ctx => Task.CompletedTask)
.Use<ConcurrentMiddleware>() .Use<ConcurrentMiddleware>()
.Use<PortScanMiddleware>() .Use<PortScanMiddleware>()
.Use<HttpsScanMiddleware>() .Use<HttpsScanMiddleware>()
.Use<ScanOkLogMiddleware>() .Use<ScanOkLogMiddleware>()
.Build(); .Build();
}) })
.AddHostedService<GithubHostedService>() .AddHostedService<DnsHostedService>()
.AddHostedService<GithubScanAllHostedService>()
.AddHostedService<GithubScanResultHostedService>()
; ;
}); });

View File

@ -1,12 +1,17 @@
{ {
"Dns": {
"UpStream": "114.114.114.114"
},
"Github": { "Github": {
"ScanAllInterval": "12:00:00", //
"ScanResultInterval": "00:05:00", //
"MetaUri": "https://gitee.com/jiulang/fast-github/raw/master/FastGithub/meta.json", // ipuri "MetaUri": "https://gitee.com/jiulang/fast-github/raw/master/FastGithub/meta.json", // ipuri
"PortScanTimeout": "00:00:01", // "PortScanTimeout": "00:00:01", //
"HttpsScanTimeout": "00:00:05" // https "HttpsScanTimeout": "00:00:05" // https
}, },
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Warning", "Default": "Information",
"System": "Warning", "System": "Warning",
"Microsoft": "Warning" "Microsoft": "Warning"
} }