类型重重名
This commit is contained in:
parent
3434997964
commit
c96dab0df8
@ -3,22 +3,40 @@ using System.Net;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// dns的终节点
|
||||
/// </summary>
|
||||
public class DnsIPEndPoint
|
||||
{
|
||||
/// <summary>
|
||||
/// IP地址
|
||||
/// </summary>
|
||||
[AllowNull]
|
||||
public string Address { get; set; } = IPAddress.Loopback.ToString();
|
||||
public string IPAddress { get; set; }
|
||||
|
||||
public int Port { get; set; } = 53;
|
||||
/// <summary>
|
||||
/// 端口
|
||||
/// </summary>
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换为IPEndPoint
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IPEndPoint ToIPEndPoint()
|
||||
{
|
||||
return new IPEndPoint(IPAddress.Parse(this.Address), this.Port);
|
||||
return new IPEndPoint(System.Net.IPAddress.Parse(this.IPAddress), this.Port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool Validate()
|
||||
{
|
||||
return IPAddress.TryParse(this.Address, out var address) &&
|
||||
!(address.Equals(IPAddress.Loopback) && this.Port == 53);
|
||||
return System.Net.IPAddress.TryParse(this.IPAddress, out var address)
|
||||
? !(address.Equals(System.Net.IPAddress.Loopback) && this.Port == 53)
|
||||
: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,16 +4,36 @@ using System.Text.RegularExpressions;
|
||||
|
||||
namespace FastGithub
|
||||
{
|
||||
/// <summary>
|
||||
/// FastGithub的配置
|
||||
/// </summary>
|
||||
public class FastGithubOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 域名
|
||||
/// </summary>
|
||||
private DomainMatch[]? domainMatches;
|
||||
|
||||
public DnsIPEndPoint TrustedDns { get; set; } = new DnsIPEndPoint { Address = "127.0.0.1", Port = 5533 };
|
||||
/// <summary>
|
||||
/// 受信任的dns服务
|
||||
/// </summary>
|
||||
public DnsIPEndPoint TrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "127.0.0.1", Port = 5533 };
|
||||
|
||||
public DnsIPEndPoint UntrustedDns { get; set; } = new DnsIPEndPoint { Address = "114.1114.114.114", Port = 53 };
|
||||
/// <summary>
|
||||
/// 不受信任的dns服务
|
||||
/// </summary>
|
||||
public DnsIPEndPoint UntrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "114.114.114.114", Port = 53 };
|
||||
|
||||
/// <summary>
|
||||
/// 代理的域名匹配
|
||||
/// </summary>
|
||||
public HashSet<string> DomainMatches { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// 是否匹配指定的域名
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsMatch(string domain)
|
||||
{
|
||||
if (this.domainMatches == null)
|
||||
@ -23,26 +43,42 @@ namespace FastGithub
|
||||
return this.domainMatches.Any(item => item.IsMatch(domain));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 域名匹配
|
||||
/// </summary>
|
||||
private class DomainMatch
|
||||
{
|
||||
private readonly Regex regex;
|
||||
private readonly string value;
|
||||
private readonly string pattern;
|
||||
|
||||
public DomainMatch(string value)
|
||||
/// <summary>
|
||||
/// 域名匹配
|
||||
/// </summary>
|
||||
/// <param name="pattern">域名表达式</param>
|
||||
public DomainMatch(string pattern)
|
||||
{
|
||||
this.value = value;
|
||||
var pattern = Regex.Escape(value).Replace(@"\*", ".*");
|
||||
this.regex = new Regex($"^{pattern}$");
|
||||
this.pattern = pattern;
|
||||
var regexPattern = Regex.Escape(pattern).Replace(@"\*", ".*");
|
||||
this.regex = new Regex($"^{regexPattern}$", RegexOptions.IgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否与指定域名匹配
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsMatch(string domain)
|
||||
{
|
||||
return this.regex.IsMatch(domain);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为文本
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this.value;
|
||||
return this.pattern;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,9 +15,7 @@ namespace FastGithub.Dns
|
||||
/// </summary>
|
||||
sealed class DnsServerHostedService : BackgroundService
|
||||
{
|
||||
private const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C);
|
||||
|
||||
private readonly FastGihubResolver fastGihubResolver;
|
||||
private readonly RequestResolver requestResolver;
|
||||
private readonly IOptions<FastGithubOptions> options;
|
||||
private readonly ILogger<DnsServerHostedService> logger;
|
||||
|
||||
@ -28,15 +26,15 @@ namespace FastGithub.Dns
|
||||
/// <summary>
|
||||
/// dns后台服务
|
||||
/// </summary>
|
||||
/// <param name="githubRequestResolver"></param>
|
||||
/// <param name="requestResolver"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="logger"></param>
|
||||
public DnsServerHostedService(
|
||||
FastGihubResolver fastGihubResolver,
|
||||
RequestResolver requestResolver,
|
||||
IOptions<FastGithubOptions> options,
|
||||
ILogger<DnsServerHostedService> logger)
|
||||
{
|
||||
this.fastGihubResolver = fastGihubResolver;
|
||||
this.requestResolver = requestResolver;
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
}
|
||||
@ -51,12 +49,13 @@ namespace FastGithub.Dns
|
||||
this.socket.Bind(new IPEndPoint(IPAddress.Any, 53));
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C);
|
||||
this.socket.IOControl(SIO_UDP_CONNRESET, new byte[4], new byte[4]);
|
||||
}
|
||||
|
||||
this.logger.LogInformation("dns服务启动成功");
|
||||
var upStream = IPAddress.Parse(options.Value.UntrustedDns.Address);
|
||||
this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, upStream);
|
||||
var secondary = IPAddress.Parse(options.Value.UntrustedDns.IPAddress);
|
||||
this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, secondary);
|
||||
return base.StartAsync(cancellationToken);
|
||||
}
|
||||
|
||||
@ -88,8 +87,8 @@ namespace FastGithub.Dns
|
||||
try
|
||||
{
|
||||
var request = Request.FromArray(datas);
|
||||
var remoteRequest = new RemoteRequest(request, remoteEndPoint);
|
||||
var response = await this.fastGihubResolver.Resolve(remoteRequest, cancellationToken);
|
||||
var remoteEndPointRequest = new RemoteEndPointRequest(request, remoteEndPoint);
|
||||
var response = await this.requestResolver.Resolve(remoteEndPointRequest, cancellationToken);
|
||||
await this.socket.SendToAsync(response.ToArray(), SocketFlags.None, remoteEndPoint);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -126,7 +125,7 @@ namespace FastGithub.Dns
|
||||
{
|
||||
try
|
||||
{
|
||||
var results = NameServiceUtil.SetNameServers(nameServers);
|
||||
var results = SystemDnsUtil.SetNameServers(nameServers);
|
||||
this.logger.LogInformation($"设置本机dns成功");
|
||||
return results;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace FastGithub
|
||||
/// <summary>
|
||||
/// 服务注册扩展
|
||||
/// </summary>
|
||||
public static class DnsServiceCollectionExtensions
|
||||
public static class DnsServerServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 注册github的dns服务
|
||||
@ -16,7 +16,7 @@ namespace FastGithub
|
||||
public static IServiceCollection AddGithubDns(this IServiceCollection services)
|
||||
{
|
||||
return services
|
||||
.AddSingleton<FastGihubResolver>()
|
||||
.AddSingleton<RequestResolver>()
|
||||
.AddHostedService<DnsServerHostedService>();
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,12 @@ using System.Net.Sockets;
|
||||
namespace FastGithub.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// 远程请求
|
||||
/// 带远程终节点的请求
|
||||
/// </summary>
|
||||
sealed class RemoteRequest : Request
|
||||
sealed class RemoteEndPointRequest : Request
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取远程地址
|
||||
/// 获取程终节点
|
||||
/// </summary>
|
||||
public EndPoint RemoteEndPoint { get; }
|
||||
|
||||
@ -20,7 +20,7 @@ namespace FastGithub.Dns
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="remoteEndPoint"></param>
|
||||
public RemoteRequest(Request request, EndPoint remoteEndPoint)
|
||||
public RemoteEndPointRequest(Request request, EndPoint remoteEndPoint)
|
||||
: base(request)
|
||||
{
|
||||
this.RemoteEndPoint = remoteEndPoint;
|
||||
@ -12,26 +12,27 @@ using System.Threading.Tasks;
|
||||
namespace FastGithub.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// 反向代理解析器
|
||||
/// dns解析者
|
||||
/// </summary>
|
||||
sealed class FastGihubResolver : IRequestResolver
|
||||
sealed class RequestResolver : IRequestResolver
|
||||
{
|
||||
private readonly IRequestResolver untrustedDnsResolver;
|
||||
private readonly TimeSpan ttl = TimeSpan.FromMinutes(1d);
|
||||
private readonly IRequestResolver untrustedResolver;
|
||||
private readonly IOptionsMonitor<FastGithubOptions> options;
|
||||
private readonly ILogger<FastGihubResolver> logger;
|
||||
private readonly ILogger<RequestResolver> logger;
|
||||
|
||||
/// <summary>
|
||||
/// github相关域名解析器
|
||||
/// dns解析者
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="logger"></param>
|
||||
public FastGihubResolver(
|
||||
public RequestResolver(
|
||||
IOptionsMonitor<FastGithubOptions> options,
|
||||
ILogger<FastGihubResolver> logger)
|
||||
ILogger<RequestResolver> logger)
|
||||
{
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
this.untrustedDnsResolver = new UdpRequestResolver(options.CurrentValue.UntrustedDns.ToIPEndPoint());
|
||||
this.untrustedResolver = new UdpRequestResolver(options.CurrentValue.UntrustedDns.ToIPEndPoint());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -43,7 +44,7 @@ namespace FastGithub.Dns
|
||||
public async Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = Response.FromRequest(request);
|
||||
if (request is not RemoteRequest remoteRequest)
|
||||
if (request is not RemoteEndPointRequest remoteEndPointRequest)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
@ -57,14 +58,15 @@ namespace FastGithub.Dns
|
||||
var domain = question.Name;
|
||||
if (this.options.CurrentValue.IsMatch(domain.ToString()) == true)
|
||||
{
|
||||
var localAddress = remoteRequest.GetLocalAddress() ?? IPAddress.Loopback;
|
||||
var record = new IPAddressResourceRecord(domain, localAddress, TimeSpan.FromMinutes(1d));
|
||||
this.logger.LogInformation($"[{domain}->{localAddress}]");
|
||||
var localAddress = remoteEndPointRequest.GetLocalAddress() ?? IPAddress.Loopback;
|
||||
var record = new IPAddressResourceRecord(domain, localAddress, this.ttl);
|
||||
response.AnswerRecords.Add(record);
|
||||
|
||||
this.logger.LogInformation($"[{domain}->{localAddress}]");
|
||||
return response;
|
||||
}
|
||||
|
||||
return await this.untrustedDnsResolver.Resolve(request, cancellationToken);
|
||||
return await this.untrustedResolver.Resolve(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,10 +9,10 @@ using System.Runtime.Versioning;
|
||||
namespace FastGithub.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// 域名服务工具
|
||||
/// 系统域名服务工具
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
static class NameServiceUtil
|
||||
static class SystemDnsUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// www.baidu.com的ip
|
||||
@ -8,19 +8,19 @@ using System.Threading.Tasks;
|
||||
namespace FastGithub.ReverseProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// 适用于请求github的HttpClientHandler
|
||||
/// 不发送NoSni的HttpClientHandler
|
||||
/// </summary>
|
||||
class GithubHttpClientHanlder : DelegatingHandler
|
||||
class NoSniHttpClientHanlder : DelegatingHandler
|
||||
{
|
||||
private readonly GithubResolver githubResolver;
|
||||
private readonly TrustedResolver trustedDomainResolver;
|
||||
|
||||
/// <summary>
|
||||
/// 请求github的HttpClientHandler
|
||||
/// 不发送NoSni的HttpClientHandler
|
||||
/// </summary>
|
||||
/// <param name="githubResolver"></param>
|
||||
public GithubHttpClientHanlder(GithubResolver githubResolver)
|
||||
/// <param name="trustedDomainResolver"></param>
|
||||
public NoSniHttpClientHanlder(TrustedResolver trustedDomainResolver)
|
||||
{
|
||||
this.githubResolver = githubResolver;
|
||||
this.trustedDomainResolver = trustedDomainResolver;
|
||||
this.InnerHandler = CreateNoneSniHttpHandler();
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ namespace FastGithub.ReverseProxy
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 替换github域名为ip
|
||||
/// 替换域名为ip
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
@ -68,7 +68,7 @@ namespace FastGithub.ReverseProxy
|
||||
var uri = request.RequestUri;
|
||||
if (uri != null && uri.HostNameType == UriHostNameType.Dns)
|
||||
{
|
||||
var address = await this.githubResolver.ResolveAsync(uri.Host, cancellationToken);
|
||||
var address = await this.trustedDomainResolver.ResolveAsync(uri.Host, cancellationToken);
|
||||
var builder = new UriBuilder(uri)
|
||||
{
|
||||
Scheme = Uri.UriSchemeHttp,
|
||||
@ -21,7 +21,7 @@ namespace FastGithub
|
||||
public static IApplicationBuilder UseGithubReverseProxy(this IApplicationBuilder app)
|
||||
{
|
||||
var httpForwarder = app.ApplicationServices.GetRequiredService<IHttpForwarder>();
|
||||
var httpClientHanlder = app.ApplicationServices.GetRequiredService<GithubHttpClientHanlder>();
|
||||
var httpClientHanlder = app.ApplicationServices.GetRequiredService<NoSniHttpClientHanlder>();
|
||||
var options = app.ApplicationServices.GetRequiredService<IOptionsMonitor<FastGithubOptions>>();
|
||||
|
||||
app.Use(next => async context =>
|
||||
|
||||
@ -18,8 +18,8 @@ namespace FastGithub
|
||||
return services
|
||||
.AddMemoryCache()
|
||||
.AddHttpForwarder()
|
||||
.AddSingleton<GithubResolver>()
|
||||
.AddTransient<GithubHttpClientHanlder>();
|
||||
.AddSingleton<TrustedResolver>()
|
||||
.AddTransient<NoSniHttpClientHanlder>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,22 +12,23 @@ using System.Threading.Tasks;
|
||||
namespace FastGithub.ReverseProxy
|
||||
{
|
||||
/// <summary>
|
||||
/// github解析器
|
||||
/// 受信任的域名解析器
|
||||
/// </summary>
|
||||
sealed class GithubResolver
|
||||
sealed class TrustedResolver
|
||||
{
|
||||
private readonly IMemoryCache memoryCache;
|
||||
private readonly TimeSpan cacheTimeSpan = TimeSpan.FromSeconds(10d);
|
||||
private readonly IOptionsMonitor<FastGithubOptions> options;
|
||||
private readonly ILogger<GithubResolver> logger;
|
||||
private readonly ILogger<TrustedResolver> logger;
|
||||
|
||||
/// <summary>
|
||||
/// github解析器
|
||||
/// 受信任的域名解析器
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public GithubResolver(
|
||||
public TrustedResolver(
|
||||
IMemoryCache memoryCache,
|
||||
IOptionsMonitor<FastGithubOptions> options,
|
||||
ILogger<GithubResolver> logger)
|
||||
ILogger<TrustedResolver> logger)
|
||||
{
|
||||
this.memoryCache = memoryCache;
|
||||
this.options = options;
|
||||
@ -41,11 +42,11 @@ namespace FastGithub.ReverseProxy
|
||||
/// <returns></returns>
|
||||
public async Task<IPAddress> ResolveAsync(string domain, CancellationToken cancellationToken)
|
||||
{
|
||||
// 缓存,避免做不必要的并发查询
|
||||
// 缓存以避免做不必要的并发查询
|
||||
var key = $"domain:{domain}";
|
||||
var address = await this.memoryCache.GetOrCreateAsync(key, async e =>
|
||||
{
|
||||
e.SetAbsoluteExpiration(TimeSpan.FromMinutes(2d));
|
||||
e.SetAbsoluteExpiration(this.cacheTimeSpan);
|
||||
var dnsClient = new DnsClient(this.options.CurrentValue.TrustedDns.ToIPEndPoint());
|
||||
var addresses = await dnsClient.Lookup(domain, DNS.Protocol.RecordType.A, cancellationToken);
|
||||
return addresses?.FirstOrDefault();
|
||||
@ -57,7 +58,8 @@ namespace FastGithub.ReverseProxy
|
||||
this.logger.LogWarning(message);
|
||||
throw new HttpRequestException(message);
|
||||
}
|
||||
this.logger.LogInformation($"[{domain}->{address}]");
|
||||
|
||||
this.logger.LogInformation($"[{address}->{domain}]");
|
||||
return address;
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@
|
||||
"DomainMatches": [
|
||||
"github.com",
|
||||
"*.github.com",
|
||||
"*.github.io",
|
||||
"*.githubapp.com",
|
||||
"*.githubassets.com",
|
||||
"*.githubusercontent.com"
|
||||
|
||||
@ -1,4 +1,2 @@
|
||||
dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r linux-x64 -o ./bin/publish/linux-x64
|
||||
dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x86 -o ./bin/publish/win-x86
|
||||
dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x64 -o ./bin/publish/win-x64
|
||||
dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r osx-x64 -o ./bin/publish/osx-x64
|
||||
dotnet publish -c Release -f net6.0 /p:PublishSingleFile=true /p:PublishTrimmed=true -r win-x64 -o ./bin/publish/win-x64
|
||||
Loading…
Reference in New Issue
Block a user