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

Commit 08167b4

Browse files
Merge pull request #496 from justcoding121/master
Dns resolve from code
2 parents c3fc1d3 + fb33def commit 08167b4

File tree

6 files changed

+61
-36
lines changed

6 files changed

+61
-36
lines changed

.vscode/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"**/*.Basic.csproj/": true,
1616
"**/*.Docs.csproj/": true,
1717
"**/*.Proxy.csproj/": true,
18-
"**/*.Proxy.csproj" : true
18+
"**/*.Mono.csproj" : true
1919
},
2020
"search.exclude": {
2121
"**/.build": true,
@@ -32,6 +32,6 @@
3232
"**/*.Basic.csproj/": true,
3333
"**/*.Docs.csproj/": true,
3434
"**/*.Proxy.csproj/": true,
35-
"**/*.Proxy.csproj" : true
35+
"**/*.Mono.csproj" : true
3636
}
3737
}

omnisharp.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"fileOptions": {
33
"excludeSearchPatterns": [
4+
"**/*.sln",
45
"**/*.Docs.csproj",
56
"**/tests/",
67
"**/Titanium.Web.Proxy.Examples.Wpf/",

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

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
2222
/// </summary>
2323
internal class TcpConnectionFactory : IDisposable
2424
{
25+
2526
//Tcp server connection pool cache
2627
private readonly ConcurrentDictionary<string, ConcurrentQueue<TcpServerConnection>> cache
2728
= new ConcurrentDictionary<string, ConcurrentQueue<TcpServerConnection>>();
@@ -74,10 +75,10 @@ internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
7475
/// <summary>
7576
/// Gets the connection cache key.
7677
/// </summary>
77-
/// <param name="args">The session event arguments.</param>
78+
/// <param name="session">The session event arguments.</param>
7879
/// <param name="applicationProtocol"></param>
7980
/// <returns></returns>
80-
internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEventArgsBase args,
81+
internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEventArgsBase session,
8182
SslApplicationProtocol applicationProtocol)
8283
{
8384
List<SslApplicationProtocol> applicationProtocols = null;
@@ -88,32 +89,32 @@ internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEve
8889

8990
ExternalProxy customUpStreamProxy = null;
9091

91-
bool isHttps = args.IsHttps;
92+
bool isHttps = session.IsHttps;
9293
if (server.GetCustomUpStreamProxyFunc != null)
9394
{
94-
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(args);
95+
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session);
9596
}
9697

97-
args.CustomUpStreamProxyUsed = customUpStreamProxy;
98+
session.CustomUpStreamProxyUsed = customUpStreamProxy;
9899

99100
return GetConnectionCacheKey(
100-
args.WebSession.Request.RequestUri.Host,
101-
args.WebSession.Request.RequestUri.Port,
101+
session.WebSession.Request.RequestUri.Host,
102+
session.WebSession.Request.RequestUri.Port,
102103
isHttps, applicationProtocols,
103-
server, args.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
104+
server, session.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
104105
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy));
105106
}
106107

107108

108109
/// <summary>
109110
/// Create a server connection.
110111
/// </summary>
111-
/// <param name="args">The session event arguments.</param>
112+
/// <param name="session">The session event arguments.</param>
112113
/// <param name="isConnect">Is this a CONNECT request.</param>
113114
/// <param name="applicationProtocol"></param>
114115
/// <param name="cancellationToken">The cancellation token for this async task.</param>
115116
/// <returns></returns>
116-
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase args, bool isConnect,
117+
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect,
117118
SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken)
118119
{
119120
List<SslApplicationProtocol> applicationProtocols = null;
@@ -122,36 +123,36 @@ internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, Sessi
122123
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
123124
}
124125

125-
return GetServerConnection(server, args, isConnect, applicationProtocols, noCache, cancellationToken);
126+
return GetServerConnection(server, session, isConnect, applicationProtocols, noCache, cancellationToken);
126127
}
127128

128129
/// <summary>
129130
/// Create a server connection.
130131
/// </summary>
131-
/// <param name="args">The session event arguments.</param>
132+
/// <param name="session">The session event arguments.</param>
132133
/// <param name="isConnect">Is this a CONNECT request.</param>
133134
/// <param name="applicationProtocols"></param>
134135
/// <param name="cancellationToken">The cancellation token for this async task.</param>
135136
/// <returns></returns>
136-
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase args, bool isConnect,
137+
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect,
137138
List<SslApplicationProtocol> applicationProtocols, bool noCache, CancellationToken cancellationToken)
138139
{
139140
ExternalProxy customUpStreamProxy = null;
140141

141-
bool isHttps = args.IsHttps;
142+
bool isHttps = session.IsHttps;
142143
if (server.GetCustomUpStreamProxyFunc != null)
143144
{
144-
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(args);
145+
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session);
145146
}
146147

147-
args.CustomUpStreamProxyUsed = customUpStreamProxy;
148+
session.CustomUpStreamProxyUsed = customUpStreamProxy;
148149

149150
return await GetServerConnection(
150-
args.WebSession.Request.RequestUri.Host,
151-
args.WebSession.Request.RequestUri.Port,
152-
args.WebSession.Request.HttpVersion,
151+
session.WebSession.Request.RequestUri.Host,
152+
session.WebSession.Request.RequestUri.Port,
153+
session.WebSession.Request.HttpVersion,
153154
isHttps, applicationProtocols, isConnect,
154-
server, args.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
155+
server, session, session.WebSession.UpStreamEndPoint ?? server.UpStreamEndPoint,
155156
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy),
156157
noCache, cancellationToken);
157158
}
@@ -172,7 +173,7 @@ internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server,
172173
/// <returns></returns>
173174
internal async Task<TcpServerConnection> GetServerConnection(string remoteHostName, int remotePort,
174175
Version httpVersion, bool isHttps, List<SslApplicationProtocol> applicationProtocols, bool isConnect,
175-
ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
176+
ProxyServer proxyServer, SessionEventArgsBase session, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
176177
bool noCache, CancellationToken cancellationToken)
177178
{
178179
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
@@ -203,7 +204,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
203204
}
204205

205206
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps,
206-
applicationProtocols, isConnect, proxyServer, upStreamEndPoint, externalProxy, cancellationToken);
207+
applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cancellationToken);
207208

208209
connection.CacheKey = cacheKey;
209210

@@ -220,13 +221,14 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
220221
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
221222
/// <param name="isConnect">Is this a CONNECT request.</param>
222223
/// <param name="proxyServer">The current ProxyServer instance.</param>
224+
/// <param name="session">The http session.</param>
223225
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
224226
/// <param name="externalProxy">The external proxy to make request via.</param>
225227
/// <param name="cancellationToken">The cancellation token for this async task.</param>
226228
/// <returns></returns>
227229
private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort,
228230
Version httpVersion, bool isHttps, List<SslApplicationProtocol> applicationProtocols, bool isConnect,
229-
ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
231+
ProxyServer proxyServer, SessionEventArgsBase session, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
230232
CancellationToken cancellationToken)
231233
{
232234
//deny connection to proxy end points to avoid infinite connection loop.
@@ -282,16 +284,37 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
282284
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
283285
}
284286

285-
// If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections
286-
if (useUpstreamProxy)
287+
var hostname = useUpstreamProxy ? externalProxy.HostName : remoteHostName;
288+
var port = useUpstreamProxy ? externalProxy.Port : remotePort;
289+
290+
var ipHostEntry = await Dns.GetHostEntryAsync(hostname);
291+
if (ipHostEntry == null || ipHostEntry.AddressList.Length == 0)
287292
{
288-
await tcpClient.ConnectAsync(externalProxy.HostName, externalProxy.Port);
293+
throw new Exception($"Could not resolve the hostname {hostname}");
289294
}
290-
else
295+
296+
session.TimeLine["Dns Resolved"] = DateTime.Now;
297+
298+
var ipAddresses = ipHostEntry.AddressList;
299+
300+
for (int i = 0; i < ipAddresses.Length; i++)
291301
{
292-
await tcpClient.ConnectAsync(remoteHostName, remotePort);
302+
try
303+
{
304+
await tcpClient.ConnectAsync(ipAddresses[i], port);
305+
break;
306+
}
307+
catch (Exception e)
308+
{
309+
if (i == ipAddresses.Length - 1)
310+
{
311+
throw new Exception($"Could not establish connection to {hostname}", e);
312+
}
313+
}
293314
}
294315

316+
session.TimeLine["Connection Established"] = DateTime.Now;
317+
295318
await proxyServer.InvokeConnectionCreateEvent(tcpClient, false);
296319

297320
stream = new CustomBufferedStream(tcpClient.GetStream(), proxyServer.BufferPool, proxyServer.BufferSize);
@@ -347,6 +370,7 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
347370
#if NETCOREAPP2_1
348371
negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
349372
#endif
373+
session.TimeLine["HTTPS Established"] = DateTime.Now;
350374
}
351375
}
352376
catch (Exception)

src/Titanium.Web.Proxy/ProxyServer.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,6 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName,
9494
bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false,
9595
bool trustRootCertificateAsAdmin = false)
9696
{
97-
// default values
98-
ConnectionTimeOutSeconds = 60;
9997

10098
if (BufferPool == null)
10199
{
@@ -186,7 +184,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName,
186184
/// This will also determine the pool eviction time when connection pool is enabled.
187185
/// Default value is 60 seconds.
188186
/// </summary>
189-
public int ConnectionTimeOutSeconds { get; set; }
187+
public int ConnectionTimeOutSeconds { get; set; } = 60;
190188

191189
/// <summary>
192190
/// Maximum number of concurrent connections per remote host in cache.

src/Titanium.Web.Proxy/RequestHandler.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response,
207207
//for connection pool, retry fails until cache is exhausted.
208208
var result = await retryPolicy<ServerConnectionException>().ExecuteAsync(async (serverConnection) =>
209209
{
210-
args.TimeLine["Server Connection Created"] = DateTime.Now;
210+
args.TimeLine["Connection Ready"] = DateTime.Now;
211211

212212
// if upgrading to websocket then relay the request without reading the contents
213213
if (request.UpgradeToWebSocket)
@@ -369,6 +369,8 @@ await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent
369369
}
370370
}
371371

372+
args.TimeLine["Request Sent"] = DateTime.Now;
373+
372374
// If not expectation failed response was returned by server then parse response
373375
if (!request.ExpectationFailed)
374376
{

src/Titanium.Web.Proxy/TransparentClientHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
6969
//it could cause floating server connections when client exits
7070
prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
7171
httpVersion: null, isHttps: true, applicationProtocols: null, isConnect: false,
72-
proxyServer: this, upStreamEndPoint: UpStreamEndPoint, externalProxy: UpStreamHttpsProxy,
72+
proxyServer: this, session: null, upStreamEndPoint: UpStreamEndPoint, externalProxy: UpStreamHttpsProxy,
7373
noCache: false, cancellationToken: CancellationToken.None);
7474
}
7575

@@ -102,7 +102,7 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
102102
{
103103
var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
104104
httpVersion: null, isHttps: false, applicationProtocols: null,
105-
isConnect: true, proxyServer: this, upStreamEndPoint: UpStreamEndPoint,
105+
isConnect: true, proxyServer: this, session:null, upStreamEndPoint: UpStreamEndPoint,
106106
externalProxy: UpStreamHttpsProxy, noCache: true, cancellationToken: cancellationToken);
107107

108108
try

0 commit comments

Comments
 (0)