增加SocketTimedOut的ip黑名单处理
This commit is contained in:
parent
2324634a86
commit
d9034477da
@ -3,6 +3,7 @@ using DNS.Protocol;
|
||||
using FastGithub.Configuration;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@ -19,7 +20,9 @@ namespace FastGithub.DomainResolve
|
||||
/// </summary>
|
||||
sealed class DomainResolver : IDomainResolver
|
||||
{
|
||||
private readonly IMemoryCache memoryCache;
|
||||
private readonly IMemoryCache blackIPAddressCache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
|
||||
private readonly IMemoryCache domainResolveCache = new MemoryCache(Options.Create(new MemoryCacheOptions()));
|
||||
|
||||
private readonly FastGithubConfig fastGithubConfig;
|
||||
private readonly DnscryptProxy dnscryptProxy;
|
||||
private readonly ILogger<DomainResolver> logger;
|
||||
@ -33,23 +36,40 @@ namespace FastGithub.DomainResolve
|
||||
|
||||
/// <summary>
|
||||
/// 域名解析器
|
||||
/// </summary>
|
||||
/// <param name="memoryCache"></param>
|
||||
/// </summary>
|
||||
/// <param name="fastGithubConfig"></param>
|
||||
/// <param name="dnscryptProxy"></param>
|
||||
/// <param name="logger"></param>
|
||||
public DomainResolver(
|
||||
IMemoryCache memoryCache,
|
||||
FastGithubConfig fastGithubConfig,
|
||||
DnscryptProxy dnscryptProxy,
|
||||
ILogger<DomainResolver> logger)
|
||||
{
|
||||
this.memoryCache = memoryCache;
|
||||
this.fastGithubConfig = fastGithubConfig;
|
||||
this.dnscryptProxy = dnscryptProxy;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置ip黑名单
|
||||
/// </summary>
|
||||
/// <param name="address">ip</param>
|
||||
/// <param name="expiration">过期时间</param>
|
||||
public void SetBlack(IPAddress address, TimeSpan expiration)
|
||||
{
|
||||
this.blackIPAddressCache.Set(address, address, expiration);
|
||||
this.logger.LogWarning($"已自动将{address}关到黑屋{expiration}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新域名解析结果
|
||||
/// </summary>
|
||||
/// <param name="domain">域名</param>
|
||||
public void FlushDomain(DnsEndPoint domain)
|
||||
{
|
||||
this.domainResolveCache.Remove(domain);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名
|
||||
/// </summary>
|
||||
@ -78,7 +98,7 @@ namespace FastGithub.DomainResolve
|
||||
/// <returns></returns>
|
||||
private async Task<IPAddress> LookupAsync(DnsEndPoint domain, CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.memoryCache.TryGetValue<IPAddress>(domain, out var address))
|
||||
if (this.domainResolveCache.TryGetValue<IPAddress>(domain, out var address))
|
||||
{
|
||||
return address;
|
||||
}
|
||||
@ -107,7 +127,7 @@ namespace FastGithub.DomainResolve
|
||||
}
|
||||
|
||||
this.logger.LogInformation($"[{domain.Host}->{address}]");
|
||||
this.memoryCache.Set(domain, address, expiration);
|
||||
this.domainResolveCache.Set(domain, address, expiration);
|
||||
return address;
|
||||
}
|
||||
|
||||
@ -170,11 +190,6 @@ namespace FastGithub.DomainResolve
|
||||
return default;
|
||||
}
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
return addresses.FirstOrDefault();
|
||||
}
|
||||
|
||||
var tasks = addresses.Select(address => this.IsAvailableAsync(address, port, cancellationToken));
|
||||
var fastTask = await Task.WhenAny(tasks);
|
||||
return await fastTask;
|
||||
@ -190,6 +205,16 @@ namespace FastGithub.DomainResolve
|
||||
/// <returns></returns>
|
||||
private async Task<IPAddress?> IsAvailableAsync(IPAddress address, int port, CancellationToken cancellationToken)
|
||||
{
|
||||
if (port <= 0)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
if (this.blackIPAddressCache.TryGetValue(address, out _))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@ -9,10 +10,23 @@ namespace FastGithub.DomainResolve
|
||||
/// </summary>
|
||||
public interface IDomainResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置ip黑名单
|
||||
/// </summary>
|
||||
/// <param name="address">ip</param>
|
||||
/// <param name="expiration">过期时间</param>
|
||||
void SetBlack(IPAddress address, TimeSpan expiration);
|
||||
|
||||
/// <summary>
|
||||
/// 刷新域名解析结果
|
||||
/// </summary>
|
||||
/// <param name="domain">域名</param>
|
||||
void FlushDomain(DnsEndPoint domain);
|
||||
|
||||
/// <summary>
|
||||
/// 解析域名
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="domain">域名</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IPAddress> ResolveAsync(DnsEndPoint domain, CancellationToken cancellationToken = default);
|
||||
|
||||
@ -15,8 +15,7 @@ namespace FastGithub
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddDomainResolve(this IServiceCollection services)
|
||||
{
|
||||
services.AddMemoryCache();
|
||||
{
|
||||
services.TryAddSingleton<DnscryptProxy>();
|
||||
services.TryAddSingleton<IDomainResolver, DomainResolver>();
|
||||
return services.AddHostedService<DnscryptProxyHostedService>();
|
||||
|
||||
@ -21,6 +21,7 @@ namespace FastGithub.Http
|
||||
{
|
||||
private readonly DomainConfig domainConfig;
|
||||
private readonly IDomainResolver domainResolver;
|
||||
private readonly TimeSpan blackIPAddressExpiration = TimeSpan.FromMinutes(10d);
|
||||
|
||||
/// <summary>
|
||||
/// HttpClientHandler
|
||||
@ -42,8 +43,16 @@ namespace FastGithub.Http
|
||||
/// <returns></returns>
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.ProcessRequestAsync(request, cancellationToken);
|
||||
return await this.SendRequestAsync(request, cancellationToken);
|
||||
try
|
||||
{
|
||||
await this.ProcessRequestAsync(request, cancellationToken);
|
||||
return await this.SendRequestAsync(request, cancellationToken);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
this.InterceptRequestException(request, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -109,6 +118,32 @@ namespace FastGithub.Http
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截请求异常
|
||||
/// 查找TimedOut的ip地址添加到黑名单
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="exception"></param>
|
||||
private void InterceptRequestException(HttpRequestMessage request, HttpRequestException exception)
|
||||
{
|
||||
if (request.RequestUri == null ||
|
||||
exception.InnerException is not SocketException socketException ||
|
||||
socketException.SocketErrorCode != SocketError.TimedOut)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IPAddress.TryParse(request.RequestUri.Host, out var address))
|
||||
{
|
||||
this.domainResolver.SetBlack(address, this.blackIPAddressExpiration);
|
||||
}
|
||||
|
||||
if (request.Headers.Host != null)
|
||||
{
|
||||
this.domainResolver.FlushDomain(new DnsEndPoint(request.Headers.Host, request.RequestUri.Port));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建转发代理的httpHandler
|
||||
/// </summary>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user