109 lines
3.5 KiB
C#
109 lines
3.5 KiB
C#
|
namespace FreeSR.Tool.Proxy
|
|||
|
{
|
|||
|
using System;
|
|||
|
using System.Net;
|
|||
|
using System.Net.Security;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using Titanium.Web.Proxy;
|
|||
|
using Titanium.Web.Proxy.EventArguments;
|
|||
|
using Titanium.Web.Proxy.Models;
|
|||
|
|
|||
|
internal class ProxyService
|
|||
|
{
|
|||
|
private const string QueryGatewayRequestString = "query_gateway";
|
|||
|
|
|||
|
private static readonly string[] s_redirectDomains =
|
|||
|
{
|
|||
|
".bhsr.com",
|
|||
|
".starrails.com",
|
|||
|
".hoyoverse.com",
|
|||
|
".mihoyo.com"
|
|||
|
};
|
|||
|
|
|||
|
private readonly ProxyServer _webProxyServer;
|
|||
|
private readonly string _targetRedirectHost;
|
|||
|
private readonly int _targetRedirectPort;
|
|||
|
|
|||
|
public ProxyService(string targetRedirectHost, int targetRedirectPort)
|
|||
|
{
|
|||
|
_webProxyServer = new ProxyServer();
|
|||
|
_webProxyServer.CertificateManager.EnsureRootCertificate();
|
|||
|
|
|||
|
_webProxyServer.BeforeRequest += BeforeRequest;
|
|||
|
_webProxyServer.ServerCertificateValidationCallback += OnCertValidation;
|
|||
|
|
|||
|
_targetRedirectHost = targetRedirectHost;
|
|||
|
_targetRedirectPort = targetRedirectPort;
|
|||
|
|
|||
|
SetEndPoint(new ExplicitProxyEndPoint(IPAddress.Any, 8080, true));
|
|||
|
}
|
|||
|
|
|||
|
private void SetEndPoint(ExplicitProxyEndPoint explicitEP)
|
|||
|
{
|
|||
|
explicitEP.BeforeTunnelConnectRequest += BeforeTunnelConnectRequest;
|
|||
|
|
|||
|
_webProxyServer.AddEndPoint(explicitEP);
|
|||
|
_webProxyServer.Start();
|
|||
|
|
|||
|
_webProxyServer.SetAsSystemHttpProxy(explicitEP);
|
|||
|
_webProxyServer.SetAsSystemHttpsProxy(explicitEP);
|
|||
|
}
|
|||
|
|
|||
|
public void Shutdown()
|
|||
|
{
|
|||
|
_webProxyServer.Stop();
|
|||
|
_webProxyServer.Dispose();
|
|||
|
}
|
|||
|
|
|||
|
private Task BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs args)
|
|||
|
{
|
|||
|
string hostname = args.HttpClient.Request.RequestUri.Host;
|
|||
|
Console.WriteLine(hostname);
|
|||
|
args.DecryptSsl = ShouldRedirect(hostname);
|
|||
|
|
|||
|
return Task.CompletedTask;
|
|||
|
}
|
|||
|
|
|||
|
private Task OnCertValidation(object sender, CertificateValidationEventArgs args)
|
|||
|
{
|
|||
|
if (args.SslPolicyErrors == SslPolicyErrors.None)
|
|||
|
args.IsValid = true;
|
|||
|
|
|||
|
return Task.CompletedTask;
|
|||
|
}
|
|||
|
|
|||
|
private Task BeforeRequest(object sender, SessionEventArgs args)
|
|||
|
{
|
|||
|
string hostname = args.HttpClient.Request.RequestUri.Host;
|
|||
|
if (ShouldRedirect(hostname) || (hostname == _targetRedirectHost && args.HttpClient.Request.RequestUri.AbsolutePath.Contains(QueryGatewayRequestString)))
|
|||
|
{
|
|||
|
string requestUrl = args.HttpClient.Request.Url;
|
|||
|
Uri local = new Uri($"http://{_targetRedirectHost}:{_targetRedirectPort}/");
|
|||
|
|
|||
|
string replacedUrl = new UriBuilder(requestUrl)
|
|||
|
{
|
|||
|
Scheme = local.Scheme,
|
|||
|
Host = local.Host,
|
|||
|
Port = local.Port
|
|||
|
}.Uri.ToString();
|
|||
|
|
|||
|
Console.WriteLine("Redirecting: " + replacedUrl);
|
|||
|
args.HttpClient.Request.Url = replacedUrl;
|
|||
|
}
|
|||
|
|
|||
|
return Task.CompletedTask;
|
|||
|
}
|
|||
|
|
|||
|
private static bool ShouldRedirect(string hostname)
|
|||
|
{
|
|||
|
foreach (string domain in s_redirectDomains)
|
|||
|
{
|
|||
|
if (hostname.EndsWith(domain))
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|