From 45beebe74127e615f9ea8b79593a6ecb5d44ee4d Mon Sep 17 00:00:00 2001
From: Keigo YAMAZAKI <keigo.yamazaki@gmail.com>
Date: Thu, 29 Jun 2023 11:08:50 +0900
Subject: [PATCH] Add fixed remote server setting to transparentEndPoint.

---
 .../ProxyTestController.cs                         | 14 +++++++++++---
 .../Models/SocksProxyEndPoint.cs                   | 10 ++++++++++
 .../Models/TransparentBaseProxyEndPoint.cs         | 10 ++++++++++
 .../Models/TransparentProxyEndPoint.cs             | 10 ++++++++++
 .../Network/TcpConnection/TcpConnectionFactory.cs  |  8 ++++++++
 5 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
index 01a6ee0f2..da33dbf35 100644
--- a/examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+++ b/examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
@@ -104,14 +104,22 @@ public void StartProxy()
             // Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
             // A transparent endpoint usually requires a network router port forwarding HTTP(S) packets
             // or by DNS to send data to this endPoint.
-            //var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
+            //var transparentEndPointHttp = new TransparentProxyEndPoint(IPAddress.Any, 80, false)
+            //{
+            //    OverrideForwardHostName = "198.51.100.1",
+            //    OverrideForwardPort = 80
+            //};
+            //var transparentEndPointHttps = new TransparentProxyEndPoint(IPAddress.Any, 443, true)
             //{
             //    // Generic Certificate hostname to use
             //    // When SNI is disabled by client
-            //    GenericCertificateName = "localhost"
+            //    GenericCertificateName = "www.example.com",
+            //    OverrideForwardHostName = "198.51.100.1",
+            //    OverrideForwardPort = 443
             //};
+            //proxyServer.AddEndPoint(transparentEndPointHttp);
+            //proxyServer.AddEndPoint(transparentEndPointHttps);
 
-            //proxyServer.AddEndPoint(transparentEndPoint);
             //proxyServer.UpStreamHttpProxy = new ExternalProxy("localhost", 8888);
             //proxyServer.UpStreamHttpsProxy = new ExternalProxy("localhost", 8888);
 
diff --git a/src/Titanium.Web.Proxy/Models/SocksProxyEndPoint.cs b/src/Titanium.Web.Proxy/Models/SocksProxyEndPoint.cs
index 11d29373c..d57b9483e 100644
--- a/src/Titanium.Web.Proxy/Models/SocksProxyEndPoint.cs
+++ b/src/Titanium.Web.Proxy/Models/SocksProxyEndPoint.cs
@@ -31,6 +31,16 @@ public SocksProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true)
     /// </summary>
     public override string GenericCertificateName { get; set; }
 
+    /// <summary>
+    ///     The hostname (or IP-address) of the fixed forwarding remote server.
+    /// </summary>
+    public override string OverrideForwardHostName { get; set; } = "";
+
+    /// <summary>
+    ///     The port of the fixed forwarding remote server.
+    /// </summary>
+    public override int OverrideForwardPort { get; set; } = -1;
+
     /// <summary>
     ///     Before Ssl authentication this event is fired.
     /// </summary>
diff --git a/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs b/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
index f8bddc321..b499f785c 100644
--- a/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
+++ b/src/Titanium.Web.Proxy/Models/TransparentBaseProxyEndPoint.cs
@@ -18,6 +18,16 @@ protected TransparentBaseProxyEndPoint(IPAddress ipAddress, int port, bool decry
     /// </summary>
     public abstract string GenericCertificateName { get; set; }
 
+    /// <summary>
+    ///     The hostname (or IP-address) of the fixed forwarding remote server.
+    /// </summary>
+    public abstract string OverrideForwardHostName { get; set; }
+
+    /// <summary>
+    ///     The port of the fixed forwarding remote server.
+    /// </summary>
+    public abstract int OverrideForwardPort { get; set; }
+
     internal abstract Task InvokeBeforeSslAuthenticate(ProxyServer proxyServer,
         BeforeSslAuthenticateEventArgs connectArgs, ExceptionHandler? exceptionFunc);
 }
\ No newline at end of file
diff --git a/src/Titanium.Web.Proxy/Models/TransparentProxyEndPoint.cs b/src/Titanium.Web.Proxy/Models/TransparentProxyEndPoint.cs
index 0e1729940..f3712b7d9 100644
--- a/src/Titanium.Web.Proxy/Models/TransparentProxyEndPoint.cs
+++ b/src/Titanium.Web.Proxy/Models/TransparentProxyEndPoint.cs
@@ -31,6 +31,16 @@ public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl =
     /// </summary>
     public override string GenericCertificateName { get; set; }
 
+    /// <summary>
+    ///     The hostname (or IP-address) of the fixed forwarding remote server.
+    /// </summary>
+    public override string OverrideForwardHostName { get; set; } = "";
+
+    /// <summary>
+    ///     The port of the fixed forwarding remote server.
+    /// </summary>
+    public override int OverrideForwardPort { get; set; } = -1;
+
     /// <summary>
     ///     Before Ssl authentication this event is fired.
     /// </summary>
diff --git a/src/Titanium.Web.Proxy/Network/TcpConnection/TcpConnectionFactory.cs b/src/Titanium.Web.Proxy/Network/TcpConnection/TcpConnectionFactory.cs
index b7292dd6b..94a083c63 100644
--- a/src/Titanium.Web.Proxy/Network/TcpConnection/TcpConnectionFactory.cs
+++ b/src/Titanium.Web.Proxy/Network/TcpConnection/TcpConnectionFactory.cs
@@ -205,6 +205,14 @@ internal Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer,
             port = uri.Port;
         }
 
+        if (session.IsTransparent && !string.IsNullOrEmpty(((TransparentBaseProxyEndPoint)session.ProxyEndPoint).OverrideForwardHostName))
+        {
+            host = ((TransparentBaseProxyEndPoint)session.ProxyEndPoint).OverrideForwardHostName;
+    
+            if (((TransparentBaseProxyEndPoint)session.ProxyEndPoint).OverrideForwardPort > 0)
+                port = ((TransparentBaseProxyEndPoint)session.ProxyEndPoint).OverrideForwardPort;
+        }
+
         var upStreamEndPoint = session.HttpClient.UpStreamEndPoint ?? proxyServer.UpStreamEndPoint;
         var upStreamProxy = customUpStreamProxy ??
                             (isHttps ? proxyServer.UpStreamHttpsProxy : proxyServer.UpStreamHttpProxy);