增加FastGithubException异常

This commit is contained in:
xljiulang 2021-07-17 21:34:04 +08:00
parent 49a18eaae9
commit 92ce30af09
7 changed files with 121 additions and 82 deletions

View File

@ -0,0 +1,43 @@
using System.Text.RegularExpressions;
namespace FastGithub
{
/// <summary>
/// 域名匹配
/// </summary>
sealed class DomainMatch
{
private readonly Regex regex;
private readonly string pattern;
/// <summary>
/// 域名匹配
/// </summary>
/// <param name="pattern">域名表达式</param>
public DomainMatch(string 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.pattern;
}
}
}

View File

@ -0,0 +1,29 @@
using System;
namespace FastGithub
{
/// <summary>
/// 表示FastGithub异常
/// </summary>
public class FastGithubException : Exception
{
/// <summary>
/// FastGithub异常
/// </summary>
/// <param name="message"></param>
public FastGithubException(string message)
: base(message)
{
}
/// <summary>
/// FastGithub异常
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
public FastGithubException(string message, Exception? innerException)
: base(message, innerException)
{
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Net;
namespace FastGithub namespace FastGithub
{ {
@ -13,22 +14,52 @@ namespace FastGithub
/// 域名 /// 域名
/// </summary> /// </summary>
private DomainMatch[]? domainMatches; private DomainMatch[]? domainMatches;
private IPEndPoint? trustedDnsEndPoint;
private IPEndPoint? unTrustedDnsEndPoint;
/// <summary> /// <summary>
/// 受信任的dns服务 /// 受信任的dns服务
/// </summary> /// </summary>
public DnsIPEndPoint TrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "127.0.0.1", Port = 5533 }; public IPEndPointOptions TrustedDns { get; set; } = new IPEndPointOptions { IPAddress = "127.0.0.1", Port = 5533 };
/// <summary> /// <summary>
/// 不受信任的dns服务 /// 不受信任的dns服务
/// </summary> /// </summary>
public DnsIPEndPoint UntrustedDns { get; set; } = new DnsIPEndPoint { IPAddress = "114.114.114.114", Port = 53 }; public IPEndPointOptions UntrustedDns { get; set; } = new IPEndPointOptions { IPAddress = "114.114.114.114", Port = 53 };
/// <summary> /// <summary>
/// 代理的域名匹配 /// 代理的域名匹配
/// </summary> /// </summary>
public HashSet<string> DomainMatches { get; set; } = new(); public HashSet<string> DomainMatches { get; set; } = new();
/// <summary>
/// 验证选项值
/// </summary>
/// <exception cref="FastGithubException"></exception>
public void Validate()
{
this.trustedDnsEndPoint = this.TrustedDns.ToIPEndPoint();
this.unTrustedDnsEndPoint = this.UntrustedDns.ToIPEndPoint();
this.domainMatches = this.DomainMatches.Select(item => new DomainMatch(item)).ToArray();
}
/// <summary>
/// 受信任的dns服务节点
/// </summary>
public IPEndPoint GetTrustedDns()
{
return this.trustedDnsEndPoint ?? throw new InvalidOperationException();
}
/// <summary>
/// 不受信任的dns服务节点
/// </summary>
public IPEndPoint GetUnTrustedDns()
{
return this.unTrustedDnsEndPoint ?? throw new InvalidOperationException();
}
/// <summary> /// <summary>
/// 是否匹配指定的域名 /// 是否匹配指定的域名
/// </summary> /// </summary>
@ -38,48 +69,9 @@ namespace FastGithub
{ {
if (this.domainMatches == null) if (this.domainMatches == null)
{ {
this.domainMatches = this.DomainMatches.Select(item => new DomainMatch(item)).ToArray(); throw new InvalidOperationException();
} }
return this.domainMatches.Any(item => item.IsMatch(domain)); return this.domainMatches.Any(item => item.IsMatch(domain));
} }
/// <summary>
/// 域名匹配
/// </summary>
private class DomainMatch
{
private readonly Regex regex;
private readonly string pattern;
/// <summary>
/// 域名匹配
/// </summary>
/// <param name="pattern">域名表达式</param>
public DomainMatch(string 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.pattern;
}
}
} }
} }

View File

@ -7,7 +7,7 @@ namespace FastGithub
/// <summary> /// <summary>
/// dns的终节点 /// dns的终节点
/// </summary> /// </summary>
public class DnsIPEndPoint public class IPEndPointOptions
{ {
/// <summary> /// <summary>
/// IP地址 /// IP地址
@ -24,29 +24,20 @@ namespace FastGithub
/// 转换为IPEndPoint /// 转换为IPEndPoint
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
/// <exception cref="FastGithubException"></exception>
public IPEndPoint ToIPEndPoint() public IPEndPoint ToIPEndPoint()
{
return new IPEndPoint(System.Net.IPAddress.Parse(this.IPAddress), this.Port);
}
/// <summary>
/// 验证dns
/// 防止使用自己使用自己来解析域名造成死循环
/// </summary>
/// <returns></returns>
public bool Validate()
{ {
if (System.Net.IPAddress.TryParse(this.IPAddress, out var address) == false) if (System.Net.IPAddress.TryParse(this.IPAddress, out var address) == false)
{ {
return false; throw new FastGithubException($"无效的ip{this.IPAddress}");
} }
if (this.Port == 53 && IsLocalMachineIPAddress(address)) if (this.Port == 53 && IsLocalMachineIPAddress(address))
{ {
return false; throw new FastGithubException($"配置的dns值不能指向{nameof(FastGithub)}自身:{this.IPAddress}:{this.Port}");
} }
return true; return new IPEndPoint(address, this.Port);
} }
/// <summary> /// <summary>

View File

@ -63,20 +63,24 @@ namespace FastGithub.ReverseProxy
var address = addresses?.FirstOrDefault(); var address = addresses?.FirstOrDefault();
if (address == null) if (address == null)
{ {
throw new Exception($"解析不到{domain}的ip"); throw new FastGithubException($"dns({endpoint})解析不到{domain}的ip");
} }
// 受干扰的dns常常返回127.0.0.1来阻断请求 // 受干扰的dns常常返回127.0.0.1来阻断请求
// 如果解析到的ip为本机ip会产生反向代理请求死循环 // 如果解析到的ip为本机ip会产生反向代理请求死循环
if (address.Equals(IPAddress.Loopback)) if (address.Equals(IPAddress.Loopback))
{ {
throw new Exception($"dns受干扰解析{domain}的ip为{address}"); throw new FastGithubException($"dns({endpoint}):解析{domain}被干扰为{address}");
} }
return address; return address;
} }
catch (FastGithubException)
{
throw;
}
catch (Exception ex) catch (Exception ex)
{ {
throw new ReverseProxyException($"dns({endpoint}){ex.Message}", ex); throw new FastGithubException($"dns({endpoint}){ex.Message}", ex);
} }
} }
} }

View File

@ -1,20 +0,0 @@
using System;
namespace FastGithub.ReverseProxy
{
/// <summary>
/// 反向代理异常
/// </summary>
sealed class ReverseProxyException : Exception
{
/// <summary>
/// 反向代理异常
/// </summary>
/// <param name="message"></param>
/// <param name="inner"></param>
public ReverseProxyException(string message, Exception? inner)
: base(message, inner)
{
}
}
}

View File

@ -39,7 +39,7 @@ namespace FastGithub
.AddDnscryptProxy() .AddDnscryptProxy()
.AddOptions<FastGithubOptions>() .AddOptions<FastGithubOptions>()
.Bind(ctx.Configuration.GetSection(nameof(FastGithub))) .Bind(ctx.Configuration.GetSection(nameof(FastGithub)))
.Validate(opt => opt.TrustedDns.Validate() && opt.UntrustedDns.Validate(), "无效的Dns配置"); .PostConfigure(opt => opt.Validate());
}) })
.ConfigureWebHostDefaults(web => .ConfigureWebHostDefaults(web =>
{ {