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

Commit ac1406a

Browse files
Merge pull request #548 from justcoding121/master
Fix reverse proxy
2 parents 881e9f2 + e08721c commit ac1406a

24 files changed

+740
-422
lines changed

appveyor.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ cache: .build\cleanup-cache.txt
2727

2828
# to run your custom scripts instead of automatic MSBuild
2929
build_script:
30-
- cmd: build.bat Package
30+
- cmd: build.bat
3131

3232
assembly_info:
3333
patch: true
@@ -39,6 +39,8 @@ assembly_info:
3939
# to disable automatic tests
4040
test: on
4141

42+
test_script:
43+
- cmd: test.bat
4244
# skip building commits that add tags (such as release tag)
4345
skip_tags: true
4446

docs/api/Titanium.Web.Proxy.Network.CertificateManager.html

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,54 @@ <h5 class="returns">Returns</h5>
552552
</tr>
553553
</tbody>
554554
</table>
555+
<span class="small pull-right mobile-hide">
556+
<span class="divider">|</span>
557+
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Network_CertificateManager_CreateServerCertificate_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
558+
</span>
559+
<span class="small pull-right mobile-hide">
560+
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Network/CertificateManager.cs/#L439">View Source</a>
561+
</span>
562+
<a id="Titanium_Web_Proxy_Network_CertificateManager_CreateServerCertificate_" data-uid="Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate*"></a>
563+
<h4 id="Titanium_Web_Proxy_Network_CertificateManager_CreateServerCertificate_System_String_" data-uid="Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate(System.String)">CreateServerCertificate(String)</h4>
564+
<div class="markdown level1 summary"><p>Creates a server certificate signed by the root certificate.</p>
565+
</div>
566+
<div class="markdown level1 conceptual"></div>
567+
<h5 class="decalaration">Declaration</h5>
568+
<div class="codewrapper">
569+
<pre><code class="lang-csharp hljs">public Task&lt;X509Certificate2&gt; CreateServerCertificate(string certificateName)</code></pre>
570+
</div>
571+
<h5 class="parameters">Parameters</h5>
572+
<table class="table table-bordered table-striped table-condensed">
573+
<thead>
574+
<tr>
575+
<th>Type</th>
576+
<th>Name</th>
577+
<th>Description</th>
578+
</tr>
579+
</thead>
580+
<tbody>
581+
<tr>
582+
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
583+
<td><span class="parametername">certificateName</span></td>
584+
<td></td>
585+
</tr>
586+
</tbody>
587+
</table>
588+
<h5 class="returns">Returns</h5>
589+
<table class="table table-bordered table-striped table-condensed">
590+
<thead>
591+
<tr>
592+
<th>Type</th>
593+
<th>Description</th>
594+
</tr>
595+
</thead>
596+
<tbody>
597+
<tr>
598+
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.threading.tasks.task-1">Task</a>&lt;<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.security.cryptography.x509certificates.x509certificate2">X509Certificate2</a>&gt;</td>
599+
<td></td>
600+
</tr>
601+
</tbody>
602+
</table>
555603
<span class="small pull-right mobile-hide">
556604
<span class="divider">|</span>
557605
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Network_CertificateManager_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Network.CertificateManager.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>

docs/index.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/xrefmap.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,6 +3035,19 @@ references:
30353035
isSpec: "True"
30363036
fullName: Titanium.Web.Proxy.Network.CertificateManager.CreateRootCertificate
30373037
nameWithType: CertificateManager.CreateRootCertificate
3038+
- uid: Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate(System.String)
3039+
name: CreateServerCertificate(String)
3040+
href: api/Titanium.Web.Proxy.Network.CertificateManager.html#Titanium_Web_Proxy_Network_CertificateManager_CreateServerCertificate_System_String_
3041+
commentId: M:Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate(System.String)
3042+
fullName: Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate(System.String)
3043+
nameWithType: CertificateManager.CreateServerCertificate(String)
3044+
- uid: Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate*
3045+
name: CreateServerCertificate
3046+
href: api/Titanium.Web.Proxy.Network.CertificateManager.html#Titanium_Web_Proxy_Network_CertificateManager_CreateServerCertificate_
3047+
commentId: Overload:Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate
3048+
isSpec: "True"
3049+
fullName: Titanium.Web.Proxy.Network.CertificateManager.CreateServerCertificate
3050+
nameWithType: CertificateManager.CreateServerCertificate
30383051
- uid: Titanium.Web.Proxy.Network.CertificateManager.Dispose
30393052
name: Dispose()
30403053
href: api/Titanium.Web.Proxy.Network.CertificateManager.html#Titanium_Web_Proxy_Network_CertificateManager_Dispose

src/Titanium.Web.Proxy.sln

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy", "Titan
2525
EndProject
2626
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.UnitTests", "..\tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj", "{B517E3D0-D03B-436F-AB03-34BA0D5321AF}"
2727
EndProject
28-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.IntegrationTests", "..\tests\Titanium.Web.Proxy.IntegrationTests\Titanium.Web.Proxy.IntegrationTests.csproj", "{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}"
29-
EndProject
3028
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Examples.Basic", "..\examples\Titanium.Web.Proxy.Examples.Basic\Titanium.Web.Proxy.Examples.Basic.csproj", "{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}"
3129
EndProject
3230
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Examples.Wpf", "..\examples\Titanium.Web.Proxy.Examples.Wpf\Titanium.Web.Proxy.Examples.Wpf.csproj", "{4406CE17-9A39-4F28-8363-6169A4F799C1}"
3331
EndProject
32+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.IntegrationTests", "..\tests\Titanium.Web.Proxy.IntegrationTests\Titanium.Web.Proxy.IntegrationTests.csproj", "{1D053D72-DCB4-4517-ACDD-D35ADC186950}"
33+
EndProject
3434
Global
3535
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3636
Debug|Any CPU = Debug|Any CPU
@@ -49,20 +49,12 @@ Global
4949
{91018B6D-A7A9-45BE-9CB3-79CBB8B169A6}.Release|x64.Build.0 = Release|x64
5050
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5151
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
52-
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|x64.ActiveCfg = Debug|x64
53-
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|x64.Build.0 = Debug|x64
52+
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|x64.ActiveCfg = Debug|Any CPU
53+
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Debug|x64.Build.0 = Debug|Any CPU
5454
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
5555
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|Any CPU.Build.0 = Release|Any CPU
56-
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|x64.ActiveCfg = Release|x64
57-
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|x64.Build.0 = Release|x64
58-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|Any CPU.Build.0 = Debug|Any CPU
60-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|x64.ActiveCfg = Debug|x64
61-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Debug|x64.Build.0 = Debug|x64
62-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|Any CPU.ActiveCfg = Release|Any CPU
63-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|Any CPU.Build.0 = Release|Any CPU
64-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|x64.ActiveCfg = Release|x64
65-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16}.Release|x64.Build.0 = Release|x64
56+
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|x64.ActiveCfg = Release|Any CPU
57+
{B517E3D0-D03B-436F-AB03-34BA0D5321AF}.Release|x64.Build.0 = Release|Any CPU
6658
{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
6759
{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
6860
{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}.Debug|x64.ActiveCfg = Debug|x64
@@ -79,18 +71,26 @@ Global
7971
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.Build.0 = Release|Any CPU
8072
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.ActiveCfg = Release|x64
8173
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.Build.0 = Release|x64
74+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
75+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|Any CPU.Build.0 = Debug|Any CPU
76+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|x64.ActiveCfg = Debug|Any CPU
77+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|x64.Build.0 = Debug|Any CPU
78+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Release|Any CPU.ActiveCfg = Release|Any CPU
79+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Release|Any CPU.Build.0 = Release|Any CPU
80+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Release|x64.ActiveCfg = Release|Any CPU
81+
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Release|x64.Build.0 = Release|Any CPU
8282
EndGlobalSection
8383
GlobalSection(SolutionProperties) = preSolution
8484
HideSolutionNode = FALSE
8585
EndGlobalSection
8686
GlobalSection(NestedProjects) = preSolution
8787
{B517E3D0-D03B-436F-AB03-34BA0D5321AF} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
88-
{32231301-B0FB-4F9E-98DF-B3E8A88F4C16} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
8988
{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
9089
{4406CE17-9A39-4F28-8363-6169A4F799C1} = {B6DBABDC-C985-4872-9C38-B4E5079CBC4B}
90+
{1D053D72-DCB4-4517-ACDD-D35ADC186950} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
9191
EndGlobalSection
9292
GlobalSection(ExtensibilityGlobals) = postSolution
93-
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
9493
SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
94+
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
9595
EndGlobalSection
9696
EndGlobal

src/Titanium.Web.Proxy/ExplicitClientHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
168168
string certName = HttpHelper.GetWildCardDomainName(connectHostname);
169169

170170
var certificate = endPoint.GenericCertificate ??
171-
await CertificateManager.CreateCertificateAsync(certName);
171+
await CertificateManager.CreateServerCertificate(certName);
172172

173173
// Successfully managed to authenticate the client using the fake certificate
174174
var options = new SslServerAuthenticationOptions();

src/Titanium.Web.Proxy/Network/CertificateManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,11 +432,11 @@ internal X509Certificate2 CreateCertificate(string certificateName, bool isRootC
432432
}
433433

434434
/// <summary>
435-
/// Create an SSL certificate async
435+
/// Creates a server certificate signed by the root certificate.
436436
/// </summary>
437437
/// <param name="certificateName"></param>
438438
/// <returns></returns>
439-
internal async Task<X509Certificate2> CreateCertificateAsync(string certificateName)
439+
public async Task<X509Certificate2> CreateServerCertificate(string certificateName)
440440
{
441441
// check in cache first
442442
if (cachedCertificates.TryGetValue(certificateName, out var cached))

src/Titanium.Web.Proxy/TransparentClientHandler.cs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
3434
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
3535
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
3636

37-
Task<TcpServerConnection> prefetchConnectionTask = null;
38-
bool closeServerConnection = false;
39-
bool calledRequestHandler = false;
40-
4137
try
4238
{
4339
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
@@ -63,16 +59,7 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
6359

6460
if (endPoint.DecryptSsl && args.DecryptSsl)
6561
{
66-
if(EnableTcpServerConnectionPrefetch)
67-
{
68-
//don't pass cancellation token here
69-
//it could cause floating server connections when client exits
70-
prefetchConnectionTask = tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
71-
httpVersion: null, isHttps: true, applicationProtocols: null, isConnect: false,
72-
proxyServer: this, session: null, upStreamEndPoint: UpStreamEndPoint, externalProxy: UpStreamHttpsProxy,
73-
noCache: false, cancellationToken: CancellationToken.None);
74-
}
75-
62+
7663
SslStream sslStream = null;
7764

7865
//do client authentication using fake certificate
@@ -82,7 +69,7 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
8269

8370
string certName = HttpHelper.GetWildCardDomainName(httpsHostName);
8471
var certificate = endPoint.GenericCertificate ??
85-
await CertificateManager.CreateCertificateAsync(certName);
72+
await CertificateManager.CreateServerCertificate(certName);
8673

8774
// Successfully managed to authenticate the client using the fake certificate
8875
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
@@ -140,39 +127,29 @@ await TcpHelper.SendRaw(clientStream, serverStream, BufferPool, BufferSize,
140127
return;
141128
}
142129
}
143-
calledRequestHandler = true;
144130
// HTTPS server created - we can now decrypt the client's traffic
145131
// Now create the request
146132
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
147-
cancellationTokenSource, isHttps ? httpsHostName : null, null, prefetchConnectionTask);
133+
cancellationTokenSource, isHttps ? httpsHostName : null, null, null);
148134
}
149135
catch (ProxyException e)
150136
{
151-
closeServerConnection = true;
152137
onException(clientStream, e);
153138
}
154139
catch (IOException e)
155140
{
156-
closeServerConnection = true;
157141
onException(clientStream, new Exception("Connection was aborted", e));
158142
}
159143
catch (SocketException e)
160144
{
161-
closeServerConnection = true;
162145
onException(clientStream, new Exception("Could not connect", e));
163146
}
164147
catch (Exception e)
165148
{
166-
closeServerConnection = true;
167149
onException(clientStream, new Exception("Error occured in whilst handling the client", e));
168150
}
169151
finally
170152
{
171-
if (!calledRequestHandler)
172-
{
173-
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
174-
}
175-
176153
clientStream.Dispose();
177154

178155
if (!cancellationTokenSource.IsCancellationRequested)

test.bat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@echo off
2+
3+
dotnet test "%APPVEYOR_BUILD_FOLDER%\tests\Titanium.Web.Proxy.IntegrationTests\Titanium.Web.Proxy.IntegrationTests.csproj" -c %CONFIGURATION%
4+
dotnet test "%APPVEYOR_BUILD_FOLDER%\tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj" -c %CONFIGURATION%
5+
exit /B %errorlevel%
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using System;
2+
using System.Net;
3+
using System.Net.Http;
4+
5+
namespace Titanium.Web.Proxy.IntegrationTests.Helpers
6+
{
7+
public static class TestHelper
8+
{
9+
public static HttpClient GetHttpClient(int localProxyPort)
10+
{
11+
var proxy = new TestProxy($"http://localhost:{localProxyPort}");
12+
13+
var handler = new HttpClientHandler
14+
{
15+
Proxy = proxy,
16+
UseProxy = true
17+
};
18+
19+
return new HttpClient(handler);
20+
}
21+
22+
public static HttpClient GetHttpClient()
23+
{
24+
return new HttpClient(new HttpClientHandler());
25+
}
26+
27+
public class TestProxy : IWebProxy
28+
{
29+
public Uri ProxyUri { get; set; }
30+
public ICredentials Credentials { get; set; }
31+
32+
public TestProxy(string proxyUri)
33+
: this(new Uri(proxyUri))
34+
{
35+
}
36+
37+
public TestProxy(Uri proxyUri)
38+
{
39+
this.ProxyUri = proxyUri;
40+
}
41+
42+
public Uri GetProxy(Uri destination)
43+
{
44+
return this.ProxyUri;
45+
}
46+
47+
public bool IsBypassed(Uri host)
48+
{
49+
return false;
50+
}
51+
52+
}
53+
}
54+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.Net;
3+
using System.Net.Http;
4+
using System.Threading.Tasks;
5+
using Microsoft.AspNetCore.Http;
6+
using Microsoft.VisualStudio.TestTools.UnitTesting;
7+
8+
namespace Titanium.Web.Proxy.IntegrationTests
9+
{
10+
[TestClass]
11+
public class HttpsTests
12+
{
13+
[TestMethod]
14+
public async Task Can_Handle_Https_Request()
15+
{
16+
var testSuite = new TestSuite();
17+
18+
var server = testSuite.GetServer();
19+
server.HandleRequest((context) =>
20+
{
21+
return context.Response.WriteAsync("I am server. I received your greetings.");
22+
});
23+
24+
var proxy = testSuite.GetProxy();
25+
var client = testSuite.GetClient(proxy);
26+
27+
var response = await client.PostAsync(new Uri(server.ListeningHttpsUrl),
28+
new StringContent("hello server. I am a client."));
29+
30+
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
31+
var body = await response.Content.ReadAsStringAsync();
32+
33+
Assert.AreEqual("I am server. I received your greetings.", body);
34+
}
35+
36+
}
37+
}

0 commit comments

Comments
 (0)