抽象tcp拦截器
This commit is contained in:
parent
d0dcd990fb
commit
e5dcab793f
@ -10,6 +10,11 @@ namespace FastGithub.Configuration
|
||||
/// </summary>
|
||||
public static class ReverseProxyPort
|
||||
{
|
||||
/// <summary>
|
||||
/// ssh端口
|
||||
/// </summary>
|
||||
public static int Ssh { get; } = GetAvailableTcpPort(22);
|
||||
|
||||
/// <summary>
|
||||
/// http端口
|
||||
/// </summary>
|
||||
|
||||
@ -55,11 +55,12 @@ namespace FastGithub
|
||||
/// <param name="kestrel"></param>
|
||||
public static void ListenSshReverseProxy(this KestrelServerOptions kestrel)
|
||||
{
|
||||
const int SSH_PORT = 22;
|
||||
if (CanListenTcp(SSH_PORT) == true)
|
||||
var sshPort = ReverseProxyPort.Ssh;
|
||||
kestrel.Listen(IPAddress.Loopback, sshPort, listen => listen.UseConnectionHandler<SshReverseProxyHandler>());
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
kestrel.Listen(IPAddress.Loopback, SSH_PORT, listen => listen.UseConnectionHandler<SshReverseProxyHandler>());
|
||||
kestrel.GetLogger().LogInformation($"已监听ssh://{IPAddress.Loopback}:{SSH_PORT},github的ssh反向代理服务启动完成");
|
||||
kestrel.GetLogger().LogInformation($"已监听ssh://{IPAddress.Loopback}:{sshPort},github的ssh反向代理服务启动完成");
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,9 +71,10 @@ namespace FastGithub
|
||||
public static void ListenHttpReverseProxy(this KestrelServerOptions kestrel)
|
||||
{
|
||||
var httpPort = ReverseProxyPort.Http;
|
||||
if (CanListenTcp(httpPort) == true)
|
||||
{
|
||||
kestrel.Listen(IPAddress.Loopback, httpPort);
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
kestrel.GetLogger().LogInformation($"已监听http://{IPAddress.Loopback}:{httpPort},http反向代理服务启动完成");
|
||||
}
|
||||
}
|
||||
@ -82,19 +84,13 @@ namespace FastGithub
|
||||
/// </summary>
|
||||
/// <param name="kestrel"></param>
|
||||
/// <exception cref="FastGithubException"></exception>
|
||||
/// <returns></returns>
|
||||
public static int ListenHttpsReverseProxy(this KestrelServerOptions kestrel)
|
||||
public static void ListenHttpsReverseProxy(this KestrelServerOptions kestrel)
|
||||
{
|
||||
var httpsPort = ReverseProxyPort.Https;
|
||||
if (CanListenTcp(httpsPort) == false)
|
||||
{
|
||||
throw new FastGithubException($"tcp端口{httpsPort}已经被其它进程占用");
|
||||
}
|
||||
|
||||
var certService = kestrel.ApplicationServices.GetRequiredService<CertService>();
|
||||
certService.CreateCaCertIfNotExists();
|
||||
certService.InstallAndTrustCaCert();
|
||||
|
||||
var httpsPort = ReverseProxyPort.Https;
|
||||
kestrel.Listen(IPAddress.Loopback, httpsPort,
|
||||
listen => listen.UseHttps(https =>
|
||||
https.ServerCertificateSelector = (ctx, domain) =>
|
||||
@ -105,8 +101,6 @@ namespace FastGithub
|
||||
var logger = kestrel.GetLogger();
|
||||
logger.LogInformation($"已监听https://{IPAddress.Loopback}:{httpsPort},https反向代理服务启动完成");
|
||||
}
|
||||
|
||||
return httpsPort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -4,7 +4,7 @@ using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// dns拦截后台服务
|
||||
|
||||
@ -13,7 +13,7 @@ using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using WinDivertSharp;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// dns拦截器
|
||||
@ -165,7 +165,7 @@ namespace FastGithub.Dns
|
||||
}
|
||||
|
||||
WinDivert.WinDivertHelperCalcChecksums(winDivertBuffer, packetLength, ref winDivertAddress, WinDivertChecksumHelperParam.All);
|
||||
this.logger.LogInformation($"已拦截dns查询{domain}并伪造解析结果为{IPAddress.Loopback}");
|
||||
this.logger.LogInformation($"{domain} => {IPAddress.Loopback}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// host文件冲解决者
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// http拦截后台服务
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class HttpInterceptHostedService : BackgroundService
|
||||
{
|
||||
private readonly HttpInterceptor httpsInterceptor;
|
||||
|
||||
/// <summary>
|
||||
/// http拦截后台服务
|
||||
/// </summary>
|
||||
/// <param name="httpInterceptor"></param>
|
||||
public HttpInterceptHostedService(HttpInterceptor httpInterceptor)
|
||||
{
|
||||
this.httpsInterceptor = httpInterceptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https后台
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await Task.Yield();
|
||||
this.httpsInterceptor.Intercept(stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,95 +1,22 @@
|
||||
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
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// http拦截器
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class HttpInterceptor
|
||||
sealed class HttpInterceptor : TcpInterceptor
|
||||
{
|
||||
private readonly ILogger<HttpInterceptor> logger;
|
||||
private readonly ushort http80Port = BinaryPrimitives.ReverseEndianness((ushort)80);
|
||||
private readonly ushort httpReverseProxyPort = BinaryPrimitives.ReverseEndianness((ushort)ReverseProxyPort.Http);
|
||||
|
||||
/// <summary>
|
||||
/// http拦截器
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
public HttpInterceptor(ILogger<HttpInterceptor> logger)
|
||||
: base(80, ReverseProxyPort.Http, logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截80端口的数据包
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 443端口转发到https反向代理端口
|
||||
/// </summary>
|
||||
/// <param name="winDivertBuffer"></param>
|
||||
/// <param name="winDivertAddress"></param>
|
||||
/// <param name="packetLength"></param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
{
|
||||
/// <summary>
|
||||
/// https拦截后台服务
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class HttpsInterceptHostedService : BackgroundService
|
||||
{
|
||||
private readonly HttpsInterceptor httpsInterceptor;
|
||||
|
||||
/// <summary>
|
||||
/// https拦截后台服务
|
||||
/// </summary>
|
||||
/// <param name="httpsInterceptor"></param>
|
||||
public HttpsInterceptHostedService(HttpsInterceptor httpsInterceptor)
|
||||
{
|
||||
this.httpsInterceptor = httpsInterceptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https后台
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await Task.Yield();
|
||||
this.httpsInterceptor.Intercept(stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,95 +1,22 @@
|
||||
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
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// https拦截器
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class HttpsInterceptor
|
||||
sealed class HttpsInterceptor : TcpInterceptor
|
||||
{
|
||||
private readonly ILogger<HttpsInterceptor> logger;
|
||||
private readonly ushort https443Port = BinaryPrimitives.ReverseEndianness((ushort)443);
|
||||
private readonly ushort httpsReverseProxyPort = BinaryPrimitives.ReverseEndianness((ushort)ReverseProxyPort.Https);
|
||||
|
||||
/// <summary>
|
||||
/// https拦截器
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
public HttpsInterceptor(ILogger<HttpsInterceptor> logger)
|
||||
: base(443, ReverseProxyPort.Https, logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截443端口的数据包
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
public void Intercept(CancellationToken cancellationToken)
|
||||
{
|
||||
if (ReverseProxyPort.Https == 443)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 443端口转发到https反向代理端口
|
||||
/// </summary>
|
||||
/// <param name="winDivertBuffer"></param>
|
||||
/// <param name="winDivertAddress"></param>
|
||||
/// <param name="packetLength"></param>
|
||||
unsafe private void ModifyHttpsPacket(WinDivertBuffer winDivertBuffer, ref WinDivertAddress winDivertAddress, ref uint packetLength)
|
||||
{
|
||||
var packet = WinDivert.WinDivertHelperParsePacket(winDivertBuffer, packetLength);
|
||||
if (packet.TcpHeader->DstPort == https443Port)
|
||||
{
|
||||
packet.TcpHeader->DstPort = this.httpsReverseProxyPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.TcpHeader->SrcPort = https443Port;
|
||||
}
|
||||
winDivertAddress.Impostor = true;
|
||||
WinDivert.WinDivertHelperCalcChecksums(winDivertBuffer, packetLength, ref winDivertAddress, WinDivertChecksumHelperParam.All);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// Dns冲突解决者
|
||||
|
||||
16
FastGithub.PacketIntercept/ITcpInterceptor.cs
Normal file
16
FastGithub.PacketIntercept/ITcpInterceptor.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Threading;
|
||||
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// tcp拦截器接口
|
||||
/// </summary>
|
||||
interface ITcpInterceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// 拦截tcp
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
void Intercept(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@ using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.Dns
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// 代理冲突解决者
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
using FastGithub.Dns;
|
||||
using FastGithub.PacketIntercept;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System.Runtime.Versioning;
|
||||
@ -20,14 +20,15 @@ namespace FastGithub
|
||||
{
|
||||
services.AddSingleton<IConflictSolver, HostsConflictSolver>();
|
||||
services.AddSingleton<IConflictSolver, ProxyConflictSolver>();
|
||||
|
||||
services.TryAddSingleton<DnsInterceptor>();
|
||||
services.TryAddSingleton<HttpInterceptor>();
|
||||
services.TryAddSingleton<HttpsInterceptor>();
|
||||
|
||||
services.AddHostedService<DnsInterceptHostedService>();
|
||||
services.AddHostedService<HttpInterceptHostedService>();
|
||||
return services.AddHostedService<HttpsInterceptHostedService>();
|
||||
|
||||
services.AddSingleton<ITcpInterceptor, SshInterceptor>();
|
||||
services.AddSingleton<ITcpInterceptor, HttpInterceptor>();
|
||||
services.AddSingleton<ITcpInterceptor, HttpsInterceptor>();
|
||||
services.AddHostedService<TcpInterceptHostedService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
FastGithub.PacketIntercept/SshInterceptor.cs
Normal file
22
FastGithub.PacketIntercept/SshInterceptor.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using FastGithub.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// ssh拦截器
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class SshInterceptor : TcpInterceptor
|
||||
{
|
||||
/// <summary>
|
||||
/// ssh拦截器
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
public SshInterceptor(ILogger<HttpInterceptor> logger)
|
||||
: base(22, ReverseProxyPort.Ssh, logger)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
50
FastGithub.PacketIntercept/TcpInterceptHostedService.cs
Normal file
50
FastGithub.PacketIntercept/TcpInterceptHostedService.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// tcp拦截后台服务
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
sealed class TcpInterceptHostedService : BackgroundService
|
||||
{
|
||||
private readonly IEnumerable<ITcpInterceptor> tcpInterceptors;
|
||||
|
||||
/// <summary>
|
||||
/// tcp拦截后台服务
|
||||
/// </summary>
|
||||
/// <param name="tcpInterceptors"></param>
|
||||
public TcpInterceptHostedService(IEnumerable<ITcpInterceptor> tcpInterceptors)
|
||||
{
|
||||
this.tcpInterceptors = tcpInterceptors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https后台
|
||||
/// </summary>
|
||||
/// <param name="stoppingToken"></param>
|
||||
/// <returns></returns>
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
var tasks = this.tcpInterceptors.Select(item => this.InterceptAsync(item, stoppingToken));
|
||||
return Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截
|
||||
/// </summary>
|
||||
/// <param name="interceptor"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task InterceptAsync(ITcpInterceptor interceptor, CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Yield();
|
||||
interceptor.Intercept(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
FastGithub.PacketIntercept/TcpInterceptor.cs
Normal file
101
FastGithub.PacketIntercept/TcpInterceptor.cs
Normal file
@ -0,0 +1,101 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Net;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
using WinDivertSharp;
|
||||
|
||||
namespace FastGithub.PacketIntercept
|
||||
{
|
||||
/// <summary>
|
||||
/// tcp拦截器
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
abstract class TcpInterceptor : ITcpInterceptor
|
||||
{
|
||||
private readonly string filter;
|
||||
private readonly ushort oldServerPort;
|
||||
private readonly ushort newServerPort;
|
||||
private readonly ILogger logger;
|
||||
|
||||
/// <summary>
|
||||
/// tcp拦截器
|
||||
/// </summary>
|
||||
/// <param name="oldServerPort">修改前的服务器端口</param>
|
||||
/// <param name="newServerPort">修改后的服务器端口</param>
|
||||
/// <param name="logger"></param>
|
||||
public TcpInterceptor(int oldServerPort, int newServerPort, ILogger logger)
|
||||
{
|
||||
this.filter = $"loopback and (tcp.DstPort == {oldServerPort} or tcp.SrcPort == {newServerPort})";
|
||||
this.oldServerPort = BinaryPrimitives.ReverseEndianness((ushort)oldServerPort);
|
||||
this.newServerPort = BinaryPrimitives.ReverseEndianness((ushort)newServerPort);
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拦截指定端口的数据包
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken"></param>
|
||||
public void Intercept(CancellationToken cancellationToken)
|
||||
{
|
||||
if (this.oldServerPort == this.newServerPort)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var handle = WinDivert.WinDivertOpen(this.filter, WinDivertLayer.Network, 0, WinDivertOpenFlags.None);
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.LogInformation($"tcp://{IPAddress.Loopback}:{BinaryPrimitives.ReverseEndianness(this.oldServerPort)} => tcp://{IPAddress.Loopback}:{BinaryPrimitives.ReverseEndianness(this.newServerPort)}");
|
||||
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.ModifyTcpPacket(winDivertBuffer, ref winDivertAddress, ref packetLength);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
this.logger.LogWarning(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WinDivert.WinDivertSend(handle, winDivertBuffer, packetLength, ref winDivertAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 修改tcp数据端口的端口
|
||||
/// </summary>
|
||||
/// <param name="winDivertBuffer"></param>
|
||||
/// <param name="winDivertAddress"></param>
|
||||
/// <param name="packetLength"></param>
|
||||
unsafe private void ModifyTcpPacket(WinDivertBuffer winDivertBuffer, ref WinDivertAddress winDivertAddress, ref uint packetLength)
|
||||
{
|
||||
var packet = WinDivert.WinDivertHelperParsePacket(winDivertBuffer, packetLength);
|
||||
if (packet.TcpHeader->DstPort == oldServerPort)
|
||||
{
|
||||
packet.TcpHeader->DstPort = this.newServerPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.TcpHeader->SrcPort = oldServerPort;
|
||||
}
|
||||
winDivertAddress.Impostor = true;
|
||||
WinDivert.WinDivertHelperCalcChecksums(winDivertBuffer, packetLength, ref winDivertAddress, WinDivertChecksumHelperParam.All);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user