Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit 67c1e26

Browse files
committed
try to use the same ssl protocol which is used by the client connection
1 parent 98925e2 commit 67c1e26

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

src/Titanium.Web.Proxy/ExplicitClientHandler.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
134134

135135
if (decryptSsl && isClientHello)
136136
{
137+
clientConnection.SslProtocol = clientHelloInfo.SslProtocol;
137138
connectRequest.RequestUri = new Uri("https://" + httpUrl);
138139

139140
bool http2Supported = false;
@@ -165,15 +166,15 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
165166
IPAddress[] ipAddresses = null;
166167
try
167168
{
168-
//make sure the host can be resolved before creating the prefetch task
169+
// make sure the host can be resolved before creating the prefetch task
169170
ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
170171
}
171172
catch (SocketException) { }
172173

173174
if (ipAddresses != null && ipAddresses.Length > 0)
174175
{
175-
//don't pass cancellation token here
176-
//it could cause floating server connections when client exits
176+
// don't pass cancellation token here
177+
// it could cause floating server connections when client exits
177178
prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(this, connectArgs,
178179
isConnect: true, applicationProtocols: null, noCache: false,
179180
cancellationToken: CancellationToken.None);

src/Titanium.Web.Proxy/Network/Tcp/TcpClientConnection.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Net.Security;
66
#endif
77
using System.Net.Sockets;
8+
using System.Security.Authentication;
89
using System.Threading.Tasks;
910
using Titanium.Web.Proxy.Extensions;
1011
using Titanium.Web.Proxy.Helpers;
@@ -32,6 +33,8 @@ internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient)
3233

3334
public EndPoint RemoteEndPoint => tcpClient.Client.RemoteEndPoint;
3435

36+
internal SslProtocols SslProtocol { get; set; }
37+
3538
internal SslApplicationProtocol NegotiatedApplicationProtocol { get; set; }
3639

3740
private readonly TcpClient tcpClient;

src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ internal TcpConnectionFactory(ProxyServer server)
4848

4949
internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
5050
bool isHttps, List<SslApplicationProtocol> applicationProtocols,
51-
ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy)
51+
IPEndPoint upStreamEndPoint, ExternalProxy externalProxy)
5252
{
53-
//http version is ignored since its an application level decision b/w HTTP 1.0/1.1
54-
//also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response.
55-
//That can create cache miss for same server connection unnecessarily especially when prefetching with Connect.
56-
//http version 2 is separated using applicationProtocols below.
53+
// http version is ignored since its an application level decision b/w HTTP 1.0/1.1
54+
// also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response.
55+
// That can create cache miss for same server connection unnecessarily especially when prefetching with Connect.
56+
// http version 2 is separated using applicationProtocols below.
5757
var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}-" +
5858
//when creating Tcp client isConnect won't matter
5959
$"{isHttps}-");
@@ -103,17 +103,19 @@ internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEve
103103
session.HttpClient.Request.RequestUri.Host,
104104
session.HttpClient.Request.RequestUri.Port,
105105
isHttps, applicationProtocols,
106-
server, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
106+
session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
107107
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy));
108108
}
109109

110110

111111
/// <summary>
112112
/// Create a server connection.
113113
/// </summary>
114+
/// <param name="server">The proxy server.</param>
114115
/// <param name="session">The session event arguments.</param>
115116
/// <param name="isConnect">Is this a CONNECT request.</param>
116117
/// <param name="applicationProtocol"></param>
118+
/// <param name="noCache">if set to <c>true</c> [no cache].</param>
117119
/// <param name="cancellationToken">The cancellation token for this async task.</param>
118120
/// <returns></returns>
119121
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect,
@@ -131,9 +133,11 @@ internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, Sessi
131133
/// <summary>
132134
/// Create a server connection.
133135
/// </summary>
136+
/// <param name="server">The proxy server.</param>
134137
/// <param name="session">The session event arguments.</param>
135138
/// <param name="isConnect">Is this a CONNECT request.</param>
136139
/// <param name="applicationProtocols"></param>
140+
/// <param name="noCache">if set to <c>true</c> [no cache].</param>
137141
/// <param name="cancellationToken">The cancellation token for this async task.</param>
138142
/// <returns></returns>
139143
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect,
@@ -168,6 +172,7 @@ internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server,
168172
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
169173
/// <param name="isConnect">Is this a CONNECT request.</param>
170174
/// <param name="proxyServer">The current ProxyServer instance.</param>
175+
/// <param name="session">The session.</param>
171176
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
172177
/// <param name="externalProxy">The external proxy to make request via.</param>
173178
/// <param name="noCache">Not from cache/create new connection.</param>
@@ -178,9 +183,9 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
178183
ProxyServer proxyServer, SessionEventArgsBase session, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
179184
bool noCache, CancellationToken cancellationToken)
180185
{
186+
var sslProtocol = session.ProxyClient.Connection.SslProtocol;
181187
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
182-
isHttps, applicationProtocols,
183-
proxyServer, upStreamEndPoint, externalProxy);
188+
isHttps, applicationProtocols, upStreamEndPoint, externalProxy);
184189

185190
if (proxyServer.EnableConnectionPool && !noCache)
186191
{
@@ -204,7 +209,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
204209
}
205210
}
206211

207-
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps,
212+
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol,
208213
applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cancellationToken);
209214

210215
connection.CacheKey = cacheKey;
@@ -219,6 +224,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
219224
/// <param name="remotePort">The remote port.</param>
220225
/// <param name="httpVersion">The http version to use.</param>
221226
/// <param name="isHttps">Is this a HTTPS request.</param>
227+
/// <param name="sslProtocol">The SSL protocol.</param>
222228
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
223229
/// <param name="isConnect">Is this a CONNECT request.</param>
224230
/// <param name="proxyServer">The current ProxyServer instance.</param>
@@ -228,7 +234,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
228234
/// <param name="cancellationToken">The cancellation token for this async task.</param>
229235
/// <returns></returns>
230236
private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort,
231-
Version httpVersion, bool isHttps, List<SslApplicationProtocol> applicationProtocols, bool isConnect,
237+
Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol> applicationProtocols, bool isConnect,
232238
ProxyServer proxyServer, SessionEventArgsBase session, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
233239
CancellationToken cancellationToken)
234240
{
@@ -269,7 +275,7 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
269275
SslApplicationProtocol negotiatedApplicationProtocol = default;
270276

271277
bool retry = true;
272-
var enabledSslProtocols = proxyServer.SupportedSslProtocols;
278+
var enabledSslProtocols = sslProtocol;
273279

274280
retry:
275281
try
@@ -386,7 +392,7 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
386392

387393
}
388394
}
389-
catch (IOException ex) when (ex.HResult == unchecked((int)0x80131620) && retry)
395+
catch (IOException ex) when (ex.HResult == unchecked((int)0x80131620) && retry && enabledSslProtocols >= SslProtocols.Tls11)
390396
{
391397
enabledSslProtocols = SslProtocols.Tls;
392398
retry = false;

src/Titanium.Web.Proxy/TransparentClientHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
6262

6363
if (endPoint.DecryptSsl && args.DecryptSsl)
6464
{
65+
clientConnection.SslProtocol = clientHelloInfo.SslProtocol;
6566

66-
//do client authentication using certificate
67+
// do client authentication using certificate
6768
X509Certificate2 certificate = null;
6869
try
6970
{

0 commit comments

Comments
 (0)