Commit a988e27d authored by justcoding121's avatar justcoding121

Merge branch 'develop' into beta

parents f2817483 1ce0f7fa
......@@ -32,20 +32,18 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer = new ProxyServer();
//generate root certificate without storing it in file system
//proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;
//proxyServer.CertificateManager.CreateTrustedRootCertificate(false);
//proxyServer.CertificateManager.TrustRootCertificate();
proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
proxyServer.TrustRootCertificate = true;
proxyServer.ForwardToUpstreamGateway = true;
//optionally set the Certificate Engine
//Under Mono or Non-Windows runtimes only BouncyCastle will be supported
//proxyServer.CertificateEngine = Network.CertificateEngine.DefaultWindows;
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
//optionally set the Root Certificate
//proxyServer.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable);
//proxyServer.CertificateManager.RootCertificate = new X509Certificate2("myCert.pfx", string.Empty, X509KeyStorageFlags.Exportable);
}
public void StartProxy()
......@@ -68,9 +66,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example google.com and dropbox.com
//Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnect += OnBeforeTunnelConnect;
......@@ -130,10 +126,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task<bool> OnBeforeTunnelConnect(string hostname)
{
if (hostname.Contains("amazon.com") || hostname.Contains("paypal.com"))
if (hostname.Contains("dropbox.com"))
{
//exclude bing.com and google.com from being decrypted
//instead it will be relayed via a secure TCP tunnel
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example dropbox.com
return await Task.FromResult(true);
}
else
......@@ -183,7 +180,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//Filter URL
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("yahoo.com"))
{
await e.Ok("<!DOCTYPE html>" +
e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" +
"Website Blocked" +
"</h1>" +
......@@ -195,7 +192,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
////Redirect example
//if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
//{
// await e.Redirect("https://www.paypal.com");
// e.Redirect("https://www.paypal.com");
//}
}
......
......@@ -62,29 +62,25 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public MainWindow()
{
proxyServer = new ProxyServer();
//proxyServer.CertificateEngine = CertificateEngine.DefaultWindows;
//proxyServer.CertificateManager.CertificateEngine = CertificateEngine.DefaultWindows;
////Set a password for the .pfx file
//proxyServer.PfxPassword = "PfxPassword";
//proxyServer.CertificateManager.PfxPassword = "PfxPassword";
////Set Name(path) of the Root certificate file
//proxyServer.PfxFilePath = @"C:\NameFolder\rootCert.pfx";
//proxyServer.CertificateManager.PfxFilePath = @"C:\NameFolder\rootCert.pfx";
////do you want Replace an existing Root certificate file(.pfx) if password is incorrect(RootCertificate=null)? yes====>true
//proxyServer.OverwritePfxFile = true;
//proxyServer.CertificateManager.OverwritePfxFile = true;
////save all fake certificates in folder "crts"(will be created in proxy dll directory)
////if create new Root certificate file(.pfx) ====> delete folder "crts"
//proxyServer.SaveFakeCertificates = true;
//Trust Root Certificate
proxyServer.TrustRootCertificate = true;
proxyServer.TrustRootCertificateAsAdministrator = true;
//proxyServer.CertificateManager.SaveFakeCertificates = true;
proxyServer.ForwardToUpstreamGateway = true;
////if you need Load or Create Certificate now. ////// "true" if you need Enable===> Trust the RootCertificate used by this proxy server
//proxyServer.EnsureRootCertificate(true);
//proxyServer.CertificateManager.EnsureRootCertificate(true);
////or load directly certificate(As Administrator if need this)
////and At the same time chose path and password
......
......@@ -52,11 +52,11 @@ Setup HTTP proxy:
var proxyServer = new ProxyServer();
//locally trust root certificate used by this proxy
proxyServer.TrustRootCertificate = true;
proxyServer.CertificateManager.TrustRootCertificate = true;
//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
//proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
......@@ -66,17 +66,17 @@ proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{
//Exclude HTTPS addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example dropbox.com
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown
//Use self-issued generic certificate on all HTTPS requests
//Optimizes performance by not creating a certificate for each HTTPS-enabled domain
//Use self-issued generic certificate on all https requests
//Optimizes performance by not creating a certificate for each https-enabled domain
//Useful when certificate trust is not required by proxy clients
// GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};
//Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnect += OnBeforeTunnelConnect;
//An explicit endpoint is where the client knows about the existence of a proxy
//So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint);
......@@ -109,6 +109,7 @@ proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
Console.Read();
//Unsubscribe & Quit
explicitEndPoint.BeforeTunnelConnect -= OnBeforeTunnelConnect;
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
......@@ -125,6 +126,21 @@ Sample request and response event handlers
private IDictionary<Guid, string> requestBodyHistory
= new ConcurrentDictionary<Guid, string>();
private async Task<bool> OnBeforeTunnelConnect(string hostname)
{
if (hostname.Contains("dropbox.com"))
{
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example dropbox.com
return await Task.FromResult(true);
}
else
{
return await Task.FromResult(false);
}
}
public async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine(e.WebSession.Request.Url);
......@@ -152,7 +168,7 @@ public async Task OnRequest(object sender, SessionEventArgs e)
//Filter URL
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
{
await e.Ok("<!DOCTYPE html>" +
e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" +
"Website Blocked" +
"</h1>" +
......@@ -163,7 +179,7 @@ public async Task OnRequest(object sender, SessionEventArgs e)
//Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{
await e.Redirect("https://www.paypal.com");
e.Redirect("https://www.paypal.com");
}
}
......
......@@ -51,7 +51,6 @@ namespace Titanium.Web.Proxy.IntegrationTests
public ProxyTestController()
{
proxyServer = new ProxyServer();
proxyServer.TrustRootCertificate = true;
}
public void StartProxy(int proxyPort)
......
......@@ -15,28 +15,53 @@ namespace Titanium.Web.Proxy.UnitTests
private readonly Random random = new Random();
[TestMethod]
public async Task Simple_Create_Certificate_Stress_Test()
public async Task Simple_Create_Certificate_Test()
{
var tasks = new List<Task>();
var mgr = new CertificateManager(new Lazy<Action<Exception>>(() => (e => { })).Value);
mgr.ClearIdleCertificates(1);
mgr.ClearIdleCertificates();
for (int i = 0; i < 1000; i++)
foreach (string host in hostNames)
{
foreach (string host in hostNames)
tasks.Add(Task.Run(async () =>
{
tasks.Add(Task.Run(async () =>
{
await Task.Delay(random.Next(0, 10) * 1000);
//get the connection
var certificate = mgr.CreateCertificate(host, false);
//get the connection
var certificate = await mgr.CreateCertificateAsync(host);
Assert.IsNotNull(certificate);
}));
}
Assert.IsNotNull(certificate);
}));
}
await Task.WhenAll(tasks.ToArray());
mgr.StopClearIdleCertificates();
}
//uncomment this to compare WinCert maker performance with BC (BC takes more time for same test above)
//cannot run this test in build server since trusting the certificate won't happen successfully
//[TestMethod]
public async Task Simple_Create_Win_Certificate_Test()
{
var tasks = new List<Task>();
var mgr = new CertificateManager(new Lazy<Action<Exception>>(() => (e => { })).Value);
mgr.CreateRootCertificate(true);
mgr.TrustRootCertificate();
mgr.ClearIdleCertificates();
mgr.CertificateEngine = CertificateEngine.DefaultWindows;
foreach (string host in hostNames)
{
tasks.Add(Task.Run(async () =>
{
//get the connection
var certificate = await mgr.CreateCertificateAsync(host);
Assert.IsNotNull(certificate);
}));
}
await Task.WhenAll(tasks.ToArray());
......
......@@ -531,7 +531,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
/// <param name="html"></param>
/// <param name="headers"></param>
public async Task Ok(string html, Dictionary<string, HttpHeader> headers = null)
public void Ok(string html, Dictionary<string, HttpHeader> headers = null)
{
var response = new OkResponse();
if (headers != null)
......@@ -542,7 +542,7 @@ namespace Titanium.Web.Proxy.EventArguments
response.HttpVersion = WebSession.Request.HttpVersion;
response.Body = response.Encoding.GetBytes(html ?? string.Empty);
await Respond(response);
Respond(response);
}
/// <summary>
......@@ -552,14 +552,14 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
/// <param name="result"></param>
/// <param name="headers"></param>
public async Task Ok(byte[] result, Dictionary<string, HttpHeader> headers = null)
public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null)
{
var response = new OkResponse();
response.Headers.AddHeaders(headers);
response.HttpVersion = WebSession.Request.HttpVersion;
response.Body = result;
await Respond(response);
Respond(response);
}
/// <summary>
......@@ -572,14 +572,14 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="status"></param>
/// <param name="headers"></param>
/// <returns></returns>
public async Task GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null)
public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null)
{
var response = new GenericResponse(status);
response.HttpVersion = WebSession.Request.HttpVersion;
response.Headers.AddHeaders(headers);
response.Body = response.Encoding.GetBytes(html ?? string.Empty);
await Respond(response);
Respond(response);
}
/// <summary>
......@@ -592,14 +592,14 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="status"></param>
/// <param name="headers"></param>
/// <returns></returns>
public async Task GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers)
public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers)
{
var response = new GenericResponse(status);
response.HttpVersion = WebSession.Request.HttpVersion;
response.Headers.AddHeaders(headers);
response.Body = result;
await Respond(response);
Respond(response);
}
/// <summary>
......@@ -607,18 +607,18 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task Redirect(string url)
public void Redirect(string url)
{
var response = new RedirectResponse();
response.HttpVersion = WebSession.Request.HttpVersion;
response.Headers.AddHeader(KnownHeaders.Location, url);
response.Body = emptyData;
await Respond(response);
Respond(response);
}
/// a generic responder method
public async Task Respond(Response response)
public void Respond(Response response)
{
if (WebSession.Request.RequestLocked)
{
......
This diff is collapsed.
......@@ -132,7 +132,7 @@ namespace Titanium.Web.Proxy
string certName = HttpHelper.GetWildCardDomainName(connectHostname);
var certificate = endPoint.GenericCertificate ?? CertificateManager.CreateCertificate(certName, false);
var certificate = endPoint.GenericCertificate ?? await CertificateManager.CreateCertificateAsync(certName);
//Successfully managed to authenticate the client using the fake certificate
await sslStream.AuthenticateAsServerAsync(certificate, false, SupportedSslProtocols, false);
......@@ -252,7 +252,7 @@ namespace Titanium.Web.Proxy
string sniHostName = clientHelloInfo.GetServerName();
string certName = HttpHelper.GetWildCardDomainName(sniHostName ?? endPoint.GenericCertificateName);
var certificate = CertificateManager.CreateCertificate(certName, false);
var certificate = await CertificateManager.CreateCertificateAsync(certName);
//Successfully managed to authenticate the client using the fake certificate
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.3" />
<PackageReference Include="StreamExtended" Version="1.0.135-beta" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.4.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.4.1</Version>
</PackageReference>
</ItemGroup>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.8.1.4" />
<PackageReference Include="StreamExtended" Version="1.0.135-beta" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.4.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.4.1</Version>
</PackageReference>
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -15,7 +15,7 @@
<tags></tags>
<dependencies>
<dependency id="StreamExtended" version="1.0.110-beta" />
<dependency id="Portable.BouncyCastle" version="1.8.1.3" />
<dependency id="Portable.BouncyCastle" version="1.8.1.4" />
</dependencies>
</metadata>
<files>
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="net45" />
<package id="Portable.BouncyCastle" version="1.8.1.4" targetFramework="net45" />
<package id="StreamExtended" version="1.0.110-beta" targetFramework="net45" />
</packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment