开源FastGithub

0 前言#

github网站访问慢或访问不了,相信很多人都会遇到过,解决方式大概有两种:一种是使用代理访问;另一种是使用ipaddress.com等域名解析网站查询域名的ip,然后在host文件增加ip与域名的映射。

1 代理访问#

代理访问是在一台能上github的服务器开通代理服务,然后你所在机器在访问github时,流量由代理服务器转发,稳定的代理服务,一般都是收费用。

2 域名解析网站#

例如使用ipaddress.com查询域名的ip,但你的网络可能还是无法正常的访问这个ip,或者无法连接此ip的443端口。所以如果你在网上搜索"github慢",得到别人贴出的"最新github ip"数据,粘贴到你的host文件,你可能还是无法访问github。

3 FastGithub#

github定制版的dns服务,解析访问github最快的ip

3.1 加速原理#

  • 使用github公开的ip范围,扫描所有可用的ip;
  • 间隔指定时间(5min)检测与记录扫描到的ip的访问耗时;
  • 拦截dns,访问github时,返回最快的ip;

3.2 获取github的ip#

访问https://api.github.com/meta,我们就可以拿到github公开其使用的ip,为了能够在所有环境获取到这个meta数据,我们需要把这个meta转存到gitee或本机,因为这份数据更新不频繁。FastGithub依赖这份数据,目前从gitee获取到缓存副本。

3.3 443端口扫描#

github使用了https,所以对应的tcp端口是443,尝试连接到github各ip下的443端口,如果在指定时间内(默认1s)能连接成功,证明这个ip是有用的,反之就要丢弃这个ip了。在.net下,我们可以使用Socket来进行tcp连接:

Copy
[Service(ServiceLifetime.Singleton)] sealed class PortScanMiddleware : IMiddleware<GithubContext> { private const int PORT = 443; private readonly IOptionsMonitor<GithubOptions> options; private readonly ILogger<PortScanMiddleware> logger; public PortScanMiddleware( IOptionsMonitor<GithubOptions> options, ILogger<PortScanMiddleware> logger) { this.options = options; this.logger = logger; } public async Task InvokeAsync(GithubContext context, Func<Task> next) { try { using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); using var cancellationTokenSource = new CancellationTokenSource(this.options.CurrentValue.PortScanTimeout); await socket.ConnectAsync(context.Address, PORT, cancellationTokenSource.Token); await next(); } catch (Exception) { this.logger.LogTrace($"{context.Domain} {context.Address}{PORT}端口未开放"); } } }

3.4 Https检测#

443端口开放,不意味这个ip就能正常的使用github,有可能在建立ssl时会失败,或者在https请求时,服务返回的内容并不是github官网的内容,所以我们需要进一步的侦测是否有http响应,响应内容是不是github的内容。据我观察,正常的github响应Server头,都有GitHub.com值。

Copy
[Service(ServiceLifetime.Singleton)] sealed class HttpsScanMiddleware : IMiddleware<GithubContext> { private readonly IOptionsMonitor<GithubOptions> options; private readonly ILogger<HttpsScanMiddleware> logger; public HttpsScanMiddleware( IOptionsMonitor<GithubOptions> options, ILogger<HttpsScanMiddleware> logger) { this.options = options; this.logger = logger; } public async Task InvokeAsync(GithubContext context, Func<Task> next) { try { var request = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri($"https://{context.Address}"), }; request.Headers.Host = context.Domain; using var httpClient = new HttpClient(new HttpClientHandler { Proxy = null, UseProxy = false, }); var startTime = DateTime.Now; using var cancellationTokenSource = new CancellationTokenSource(this.options.CurrentValue.HttpsScanTimeout); var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationTokenSource.Token); var server = response.EnsureSuccessStatusCode().Headers.Server; if (server.Any(s => string.Equals("GitHub.com", s.Product?.Name, StringComparison.OrdinalIgnoreCase))) { context.HttpElapsed = DateTime.Now.Subtract(startTime); await next(); } } catch (TaskCanceledException) { this.logger.LogTrace($"{context.Domain} {context.Address}连接超时"); } catch (Exception ex) { this.logger.LogTrace($"{context.Domain} {context.Address} {ex.Message}"); } } }

3.5 Dns服务#

我们可以建设一个本机或局域网的dns服务,访问github时,就返回检测到的最快的一条ip,访问其它域名时,转发给8.8.8.8这样稳定的上游dns服务来解析。这样既不影响其它域名的解析速度与稳定性,同时又能正常的使用github所有服务。

4 源代码和软件#

4.1 源代码#

github

4.2 软件下载#

gitee

posted @   jiulang  阅读(8811)  评论(31编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示
CONTENTS