类型重重名

This commit is contained in:
陈国伟 2021-07-16 13:44:55 +08:00
parent 3434997964
commit c96dab0df8
13 changed files with 125 additions and 69 deletions

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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>();
}
}

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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,

View File

@ -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 =>

View File

@ -18,8 +18,8 @@ namespace FastGithub
return services
.AddMemoryCache()
.AddHttpForwarder()
.AddSingleton<GithubResolver>()
.AddTransient<GithubHttpClientHanlder>();
.AddSingleton<TrustedResolver>()
.AddTransient<NoSniHttpClientHanlder>();
}
}
}

View File

@ -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;
}
}

View File

@ -11,6 +11,7 @@
"DomainMatches": [
"github.com",
"*.github.com",
"*.github.io",
"*.githubapp.com",
"*.githubassets.com",
"*.githubusercontent.com"

View File

@ -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