From d0dcd990fba85aa1902da4c092330f5ceb538120 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=88=E5=9B=BD=E4=BC=9F?= <366193849@qq.com>
Date: Wed, 22 Sep 2021 13:07:43 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A080=E7=AB=AF=E5=8F=A3=E6=95=B0?=
=?UTF-8?q?=E6=8D=AE=E5=8C=85=E6=95=B0=E6=8D=AE=E5=8C=85=E6=8B=A6=E6=88=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...everseProxyPort.cs => ReverseProxyPort.cs} | 34 +++----
FastGithub.HttpServer/HttpProxyMiddleware.cs | 2 +-
.../KestrelServerOptionsExtensions.cs | 10 +-
.../HttpInterceptHostedService.cs | 36 +++++++
FastGithub.PacketIntercept/HttpInterceptor.cs | 95 +++++++++++++++++++
.../HttpsInterceptHostedService.cs | 3 +-
.../HttpsInterceptor.cs | 12 +--
.../ServiceCollectionExtensions.cs | 8 +-
8 files changed, 163 insertions(+), 37 deletions(-)
rename FastGithub.Configuration/{HttpsReverseProxyPort.cs => ReverseProxyPort.cs} (55%)
create mode 100644 FastGithub.PacketIntercept/HttpInterceptHostedService.cs
create mode 100644 FastGithub.PacketIntercept/HttpInterceptor.cs
diff --git a/FastGithub.Configuration/HttpsReverseProxyPort.cs b/FastGithub.Configuration/ReverseProxyPort.cs
similarity index 55%
rename from FastGithub.Configuration/HttpsReverseProxyPort.cs
rename to FastGithub.Configuration/ReverseProxyPort.cs
index eae78f8..9965fc1 100644
--- a/FastGithub.Configuration/HttpsReverseProxyPort.cs
+++ b/FastGithub.Configuration/ReverseProxyPort.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -7,34 +6,27 @@ using System.Net.Sockets;
namespace FastGithub.Configuration
{
///
- /// https反向代理端口
+ /// 反向代理端口
///
- public static class HttpsReverseProxyPort
+ public static class ReverseProxyPort
{
///
- /// 获取端口值
+ /// http端口
///
- public static int Value { get; } = GetAvailableTcpPort(AddressFamily.InterNetwork);
+ public static int Http { get; } = GetAvailableTcpPort(80);
+
+ ///
+ /// https端口
+ ///
+ public static int Https { get; } = GetAvailableTcpPort(443);
///
/// 获取可用的随机Tcp端口
///
+ ///
///
///
- private static int GetAvailableTcpPort(AddressFamily addressFamily)
- {
- return OperatingSystem.IsWindows()
- ? GetAvailableTcpPort(addressFamily, 443)
- : GetAvailableTcpPort(addressFamily, 12345);
- }
-
- ///
- /// 获取可用的随机Tcp端口
- ///
- ///
- /// 最小值
- ///
- private static int GetAvailableTcpPort(AddressFamily addressFamily, int min)
+ private static int GetAvailableTcpPort(int minValue, AddressFamily addressFamily = AddressFamily.InterNetwork)
{
var hashSet = new HashSet();
var tcpListeners = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
@@ -47,7 +39,7 @@ namespace FastGithub.Configuration
}
}
- for (var port = min; port < IPEndPoint.MaxPort; port++)
+ for (var port = minValue; port < IPEndPoint.MaxPort; port++)
{
if (hashSet.Contains(port) == false)
{
diff --git a/FastGithub.HttpServer/HttpProxyMiddleware.cs b/FastGithub.HttpServer/HttpProxyMiddleware.cs
index ba5bdf0..1e0308b 100644
--- a/FastGithub.HttpServer/HttpProxyMiddleware.cs
+++ b/FastGithub.HttpServer/HttpProxyMiddleware.cs
@@ -148,7 +148,7 @@ namespace FastGithub.HttpServer
// 目标端口为443,走https代理中间人
if (targetPort == HTTPS_PORT && targetHost != "ssh.github.com")
{
- return new IPEndPoint(IPAddress.Loopback, HttpsReverseProxyPort.Value);
+ return new IPEndPoint(IPAddress.Loopback, ReverseProxyPort.Https);
}
// dns优选
diff --git a/FastGithub.HttpServer/KestrelServerOptionsExtensions.cs b/FastGithub.HttpServer/KestrelServerOptionsExtensions.cs
index 312c1e1..a686c17 100644
--- a/FastGithub.HttpServer/KestrelServerOptionsExtensions.cs
+++ b/FastGithub.HttpServer/KestrelServerOptionsExtensions.cs
@@ -69,11 +69,11 @@ namespace FastGithub
///
public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel)
{
- const int HTTP_PORT = 80;
- if (CanListenTcp(HTTP_PORT) == true)
+ var httpPort = ReverseProxyPort.Http;
+ if (CanListenTcp(httpPort) == true)
{
- kestrel.Listen(IPAddress.Loopback, HTTP_PORT);
- kestrel.GetLogger().LogInformation($"已监听http://{IPAddress.Loopback}:{HTTP_PORT},http反向代理服务启动完成");
+ kestrel.Listen(IPAddress.Loopback, httpPort);
+ kestrel.GetLogger().LogInformation($"已监听http://{IPAddress.Loopback}:{httpPort},http反向代理服务启动完成");
}
}
@@ -85,7 +85,7 @@ namespace FastGithub
///
public static int ListenHttpsReverseProxy(this KestrelServerOptions kestrel)
{
- var httpsPort = HttpsReverseProxyPort.Value;
+ var httpsPort = ReverseProxyPort.Https;
if (CanListenTcp(httpsPort) == false)
{
throw new FastGithubException($"tcp端口{httpsPort}已经被其它进程占用");
diff --git a/FastGithub.PacketIntercept/HttpInterceptHostedService.cs b/FastGithub.PacketIntercept/HttpInterceptHostedService.cs
new file mode 100644
index 0000000..a2308df
--- /dev/null
+++ b/FastGithub.PacketIntercept/HttpInterceptHostedService.cs
@@ -0,0 +1,36 @@
+using Microsoft.Extensions.Hosting;
+using System.Runtime.Versioning;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace FastGithub.Dns
+{
+ ///
+ /// http拦截后台服务
+ ///
+ [SupportedOSPlatform("windows")]
+ sealed class HttpInterceptHostedService : BackgroundService
+ {
+ private readonly HttpInterceptor httpsInterceptor;
+
+ ///
+ /// http拦截后台服务
+ ///
+ ///
+ public HttpInterceptHostedService(HttpInterceptor httpInterceptor)
+ {
+ this.httpsInterceptor = httpInterceptor;
+ }
+
+ ///
+ /// https后台
+ ///
+ ///
+ ///
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ await Task.Yield();
+ this.httpsInterceptor.Intercept(stoppingToken);
+ }
+ }
+}
diff --git a/FastGithub.PacketIntercept/HttpInterceptor.cs b/FastGithub.PacketIntercept/HttpInterceptor.cs
new file mode 100644
index 0000000..9cbb51d
--- /dev/null
+++ b/FastGithub.PacketIntercept/HttpInterceptor.cs
@@ -0,0 +1,95 @@
+using FastGithub.Configuration;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Buffers.Binary;
+using System.Runtime.Versioning;
+using System.Threading;
+using WinDivertSharp;
+
+namespace FastGithub.Dns
+{
+ ///
+ /// http拦截器
+ ///
+ [SupportedOSPlatform("windows")]
+ sealed class HttpInterceptor
+ {
+ private readonly ILogger logger;
+ private readonly ushort http80Port = BinaryPrimitives.ReverseEndianness((ushort)80);
+ private readonly ushort httpReverseProxyPort = BinaryPrimitives.ReverseEndianness((ushort)ReverseProxyPort.Http);
+
+ ///
+ /// http拦截器
+ ///
+ ///
+ public HttpInterceptor(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
+ ///
+ /// 拦截80端口的数据包
+ ///
+ ///
+ public void Intercept(CancellationToken cancellationToken)
+ {
+ if (ReverseProxyPort.Http == 80)
+ {
+ return;
+ }
+
+ var filter = $"loopback and (tcp.DstPort == 80 or tcp.SrcPort == {ReverseProxyPort.Http})";
+ var handle = WinDivert.WinDivertOpen(filter, WinDivertLayer.Network, 0, WinDivertOpenFlags.None);
+ if (handle == IntPtr.Zero)
+ {
+ return;
+ }
+
+ cancellationToken.Register(hwnd => WinDivert.WinDivertClose((IntPtr)hwnd!), handle);
+
+ var packetLength = 0U;
+ using var winDivertBuffer = new WinDivertBuffer();
+ var winDivertAddress = new WinDivertAddress();
+
+ while (cancellationToken.IsCancellationRequested == false)
+ {
+ if (WinDivert.WinDivertRecv(handle, winDivertBuffer, ref winDivertAddress, ref packetLength))
+ {
+ try
+ {
+ this.ModifyHttpsPacket(winDivertBuffer, ref winDivertAddress, ref packetLength);
+ }
+ catch (Exception ex)
+ {
+ this.logger.LogWarning(ex.Message);
+ }
+ finally
+ {
+ WinDivert.WinDivertSend(handle, winDivertBuffer, packetLength, ref winDivertAddress);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 443端口转发到https反向代理端口
+ ///
+ ///
+ ///
+ ///
+ unsafe private void ModifyHttpsPacket(WinDivertBuffer winDivertBuffer, ref WinDivertAddress winDivertAddress, ref uint packetLength)
+ {
+ var packet = WinDivert.WinDivertHelperParsePacket(winDivertBuffer, packetLength);
+ if (packet.TcpHeader->DstPort == http80Port)
+ {
+ packet.TcpHeader->DstPort = this.httpReverseProxyPort;
+ }
+ else
+ {
+ packet.TcpHeader->SrcPort = http80Port;
+ }
+ winDivertAddress.Impostor = true;
+ WinDivert.WinDivertHelperCalcChecksums(winDivertBuffer, packetLength, ref winDivertAddress, WinDivertChecksumHelperParam.All);
+ }
+ }
+}
diff --git a/FastGithub.PacketIntercept/HttpsInterceptHostedService.cs b/FastGithub.PacketIntercept/HttpsInterceptHostedService.cs
index 2200556..76d6306 100644
--- a/FastGithub.PacketIntercept/HttpsInterceptHostedService.cs
+++ b/FastGithub.PacketIntercept/HttpsInterceptHostedService.cs
@@ -1,5 +1,4 @@
-using FastGithub.Configuration;
-using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Hosting;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
diff --git a/FastGithub.PacketIntercept/HttpsInterceptor.cs b/FastGithub.PacketIntercept/HttpsInterceptor.cs
index 8bbe9ec..abdb301 100644
--- a/FastGithub.PacketIntercept/HttpsInterceptor.cs
+++ b/FastGithub.PacketIntercept/HttpsInterceptor.cs
@@ -14,15 +14,15 @@ namespace FastGithub.Dns
[SupportedOSPlatform("windows")]
sealed class HttpsInterceptor
{
- private readonly ILogger logger;
+ private readonly ILogger logger;
private readonly ushort https443Port = BinaryPrimitives.ReverseEndianness((ushort)443);
- private readonly ushort httpReverseProxyPort = BinaryPrimitives.ReverseEndianness((ushort)HttpsReverseProxyPort.Value);
+ private readonly ushort httpsReverseProxyPort = BinaryPrimitives.ReverseEndianness((ushort)ReverseProxyPort.Https);
///
/// https拦截器
///
///
- public HttpsInterceptor(ILogger logger)
+ public HttpsInterceptor(ILogger logger)
{
this.logger = logger;
}
@@ -33,12 +33,12 @@ namespace FastGithub.Dns
///
public void Intercept(CancellationToken cancellationToken)
{
- if (HttpsReverseProxyPort.Value == 443)
+ if (ReverseProxyPort.Https == 443)
{
return;
}
- var filter = $"loopback and (tcp.DstPort == 443 or tcp.SrcPort == {HttpsReverseProxyPort.Value})";
+ var filter = $"loopback and (tcp.DstPort == 443 or tcp.SrcPort == {ReverseProxyPort.Https})";
var handle = WinDivert.WinDivertOpen(filter, WinDivertLayer.Network, 0, WinDivertOpenFlags.None);
if (handle == IntPtr.Zero)
{
@@ -82,7 +82,7 @@ namespace FastGithub.Dns
var packet = WinDivert.WinDivertHelperParsePacket(winDivertBuffer, packetLength);
if (packet.TcpHeader->DstPort == https443Port)
{
- packet.TcpHeader->DstPort = this.httpReverseProxyPort;
+ packet.TcpHeader->DstPort = this.httpsReverseProxyPort;
}
else
{
diff --git a/FastGithub.PacketIntercept/ServiceCollectionExtensions.cs b/FastGithub.PacketIntercept/ServiceCollectionExtensions.cs
index b5506ea..8fa9020 100644
--- a/FastGithub.PacketIntercept/ServiceCollectionExtensions.cs
+++ b/FastGithub.PacketIntercept/ServiceCollectionExtensions.cs
@@ -18,11 +18,15 @@ namespace FastGithub
[SupportedOSPlatform("windows")]
public static IServiceCollection AddPacketIntercept(this IServiceCollection services)
{
- services.TryAddSingleton();
- services.TryAddSingleton();
services.AddSingleton();
services.AddSingleton();
+
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+ services.TryAddSingleton();
+
services.AddHostedService();
+ services.AddHostedService();
return services.AddHostedService();
}
}