Commit b85fbbbc authored by justcoding121's avatar justcoding121 Committed by justcoding121

Merge pull request #210 from honfika/develop

#205 IncludedHttpsHostNameRegex  and #207 Inconsistent naming fixes
parents 62b88fe6 2c8b7b8c
...@@ -37,9 +37,15 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -37,9 +37,15 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
//Exclude Https addresses you don't want to proxy //Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning //Useful for clients that use certificate pinning
//for example dropbox.com //for example google.com and dropbox.com
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" } // ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
//Include Https addresses you want to proxy (others will be excluded)
//for example github.com
// IncludedHttpsHostNameRegex = new List<string>() { "github.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 //Use self-issued generic certificate on all https requests
//Optimizes performance by not creating a certificate for each https-enabled domain //Optimizes performance by not creating a certificate for each https-enabled domain
//Useful when certificate trust is not required by proxy clients //Useful when certificate trust is not required by proxy clients
......
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
...@@ -13,14 +14,14 @@ namespace Titanium.Web.Proxy.Models ...@@ -13,14 +14,14 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="IpAddress"></param> /// <param name="ipAddress"></param>
/// <param name="Port"></param> /// <param name="port"></param>
/// <param name="EnableSsl"></param> /// <param name="enableSsl"></param>
protected ProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
{ {
this.IpAddress = IpAddress; this.IpAddress = ipAddress;
this.Port = Port; this.Port = port;
this.EnableSsl = EnableSsl; this.EnableSsl = enableSsl;
} }
/// <summary> /// <summary>
...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy.Models
|| Equals(IpAddress, IPAddress.IPv6Loopback) || Equals(IpAddress, IPAddress.IPv6Loopback)
|| Equals(IpAddress, IPAddress.IPv6None); || Equals(IpAddress, IPAddress.IPv6None);
internal TcpListener listener { get; set; } internal TcpListener Listener { get; set; }
} }
/// <summary> /// <summary>
...@@ -52,13 +53,46 @@ namespace Titanium.Web.Proxy.Models ...@@ -52,13 +53,46 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class ExplicitProxyEndPoint : ProxyEndPoint public class ExplicitProxyEndPoint : ProxyEndPoint
{ {
private List<string> _excludedHttpsHostNameRegex;
private List<string> _includedHttpsHostNameRegex;
internal bool IsSystemHttpProxy { get; set; } internal bool IsSystemHttpProxy { get; set; }
internal bool IsSystemHttpsProxy { get; set; } internal bool IsSystemHttpsProxy { get; set; }
/// <summary> /// <summary>
/// List of host names to exclude using Regular Expressions. /// List of host names to exclude using Regular Expressions.
/// </summary> /// </summary>
public List<string> ExcludedHttpsHostNameRegex { get; set; } public List<string> ExcludedHttpsHostNameRegex
{
get { return _excludedHttpsHostNameRegex; }
set
{
if (IncludedHttpsHostNameRegex != null)
{
throw new ArgumentException("Cannot set excluded when included is set");
}
_excludedHttpsHostNameRegex = value;
}
}
/// <summary>
/// List of host names to exclude using Regular Expressions.
/// </summary>
public List<string> IncludedHttpsHostNameRegex
{
get { return _includedHttpsHostNameRegex; }
set
{
if (ExcludedHttpsHostNameRegex != null)
{
throw new ArgumentException("Cannot set included when excluded is set");
}
_includedHttpsHostNameRegex = value;
}
}
/// <summary> /// <summary>
/// Generic certificate to use for SSL decryption. /// Generic certificate to use for SSL decryption.
...@@ -68,11 +102,11 @@ namespace Titanium.Web.Proxy.Models ...@@ -68,11 +102,11 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="IpAddress"></param> /// <param name="ipAddress"></param>
/// <param name="Port"></param> /// <param name="port"></param>
/// <param name="EnableSsl"></param> /// <param name="enableSsl"></param>
public ExplicitProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
: base(IpAddress, Port, EnableSsl) : base(ipAddress, port, enableSsl)
{ {
} }
...@@ -94,11 +128,11 @@ namespace Titanium.Web.Proxy.Models ...@@ -94,11 +128,11 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
/// <param name="IpAddress"></param> /// <param name="ipAddress"></param>
/// <param name="Port"></param> /// <param name="port"></param>
/// <param name="EnableSsl"></param> /// <param name="enableSsl"></param>
public TransparentProxyEndPoint(IPAddress IpAddress, int Port, bool EnableSsl) public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
: base(IpAddress, Port, EnableSsl) : base(ipAddress, port, enableSsl)
{ {
this.GenericCertificateName = "localhost"; this.GenericCertificateName = "localhost";
} }
......
...@@ -43,9 +43,10 @@ namespace Titanium.Web.Proxy.Network ...@@ -43,9 +43,10 @@ namespace Titanium.Web.Proxy.Network
private readonly Action<Exception> exceptionFunc; private readonly Action<Exception> exceptionFunc;
internal string Issuer { get; } internal string Issuer { get; }
internal string RootCertificateName { get; } internal string RootCertificateName { get; }
internal X509Certificate2 rootCertificate { get; set; } internal X509Certificate2 RootCertificate { get; set; }
internal CertificateManager(CertificateEngine engine, internal CertificateManager(CertificateEngine engine,
string issuer, string issuer,
...@@ -107,32 +108,32 @@ namespace Titanium.Web.Proxy.Network ...@@ -107,32 +108,32 @@ namespace Titanium.Web.Proxy.Network
/// <returns>true if succeeded, else false</returns> /// <returns>true if succeeded, else false</returns>
internal bool CreateTrustedRootCertificate() internal bool CreateTrustedRootCertificate()
{ {
rootCertificate = GetRootCertificate(); RootCertificate = GetRootCertificate();
if (rootCertificate != null) if (RootCertificate != null)
{ {
return true; return true;
} }
try try
{ {
rootCertificate = CreateCertificate(RootCertificateName, true); RootCertificate = CreateCertificate(RootCertificateName, true);
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); exceptionFunc(e);
} }
if (rootCertificate != null) if (RootCertificate != null)
{ {
try try
{ {
var fileName = GetRootCertificatePath(); var fileName = GetRootCertificatePath();
File.WriteAllBytes(fileName, rootCertificate.Export(X509ContentType.Pkcs12)); File.WriteAllBytes(fileName, RootCertificate.Export(X509ContentType.Pkcs12));
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); exceptionFunc(e);
} }
} }
return rootCertificate != null; return RootCertificate != null;
} }
/// <summary> /// <summary>
...@@ -159,7 +160,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -159,7 +160,7 @@ namespace Titanium.Web.Proxy.Network
{ {
try try
{ {
certificate = certEngine.MakeCertificate(certificateName, isRootCertificate, rootCertificate); certificate = certEngine.MakeCertificate(certificateName, isRootCertificate, RootCertificate);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -226,7 +227,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -226,7 +227,7 @@ namespace Titanium.Web.Proxy.Network
internal void TrustRootCertificate(StoreLocation storeLocation, internal void TrustRootCertificate(StoreLocation storeLocation,
Action<Exception> exceptionFunc) Action<Exception> exceptionFunc)
{ {
if (rootCertificate == null) if (RootCertificate == null)
{ {
exceptionFunc( exceptionFunc(
new Exception("Could not set root certificate" new Exception("Could not set root certificate"
...@@ -243,8 +244,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -243,8 +244,8 @@ namespace Titanium.Web.Proxy.Network
x509RootStore.Open(OpenFlags.ReadWrite); x509RootStore.Open(OpenFlags.ReadWrite);
x509PersonalStore.Open(OpenFlags.ReadWrite); x509PersonalStore.Open(OpenFlags.ReadWrite);
x509RootStore.Add(rootCertificate); x509RootStore.Add(RootCertificate);
x509PersonalStore.Add(rootCertificate); x509PersonalStore.Add(RootCertificate);
} }
catch (Exception e) catch (Exception e)
{ {
......
...@@ -13,14 +13,14 @@ namespace Titanium.Web.Proxy ...@@ -13,14 +13,14 @@ namespace Titanium.Web.Proxy
public partial class ProxyServer public partial class ProxyServer
{ {
private async Task<bool> CheckAuthorization(StreamWriter clientStreamWriter, IEnumerable<HttpHeader> Headers) private async Task<bool> CheckAuthorization(StreamWriter clientStreamWriter, IEnumerable<HttpHeader> headers)
{ {
if (AuthenticateUserFunc == null) if (AuthenticateUserFunc == null)
{ {
return true; return true;
} }
var httpHeaders = Headers as HttpHeader[] ?? Headers.ToArray(); var httpHeaders = headers as HttpHeader[] ?? headers.ToArray();
try try
{ {
......
...@@ -491,12 +491,12 @@ namespace Titanium.Web.Proxy ...@@ -491,12 +491,12 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
private void Listen(ProxyEndPoint endPoint) private void Listen(ProxyEndPoint endPoint)
{ {
endPoint.listener = new TcpListener(endPoint.IpAddress, endPoint.Port); endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
endPoint.listener.Start(); endPoint.Listener.Start();
endPoint.Port = ((IPEndPoint)endPoint.listener.LocalEndpoint).Port; endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;
// accept clients asynchronously // accept clients asynchronously
endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
} }
/// <summary> /// <summary>
...@@ -505,9 +505,9 @@ namespace Titanium.Web.Proxy ...@@ -505,9 +505,9 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param> /// <param name="endPoint"></param>
private void QuitListen(ProxyEndPoint endPoint) private void QuitListen(ProxyEndPoint endPoint)
{ {
endPoint.listener.Stop(); endPoint.Listener.Stop();
endPoint.listener.Server.Close(); endPoint.Listener.Server.Close();
endPoint.listener.Server.Dispose(); endPoint.Listener.Server.Dispose();
} }
/// <summary> /// <summary>
...@@ -541,7 +541,7 @@ namespace Titanium.Web.Proxy ...@@ -541,7 +541,7 @@ namespace Titanium.Web.Proxy
try try
{ {
//based on end point type call appropriate request handlers //based on end point type call appropriate request handlers
tcpClient = endPoint.listener.EndAcceptTcpClient(asyn); tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn);
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
...@@ -595,7 +595,7 @@ namespace Titanium.Web.Proxy ...@@ -595,7 +595,7 @@ namespace Titanium.Web.Proxy
} }
// Get the listener that handles the client request. // Get the listener that handles the client request.
endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint); endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
} }
/// <summary> /// <summary>
......
...@@ -72,8 +72,17 @@ namespace Titanium.Web.Proxy ...@@ -72,8 +72,17 @@ namespace Titanium.Web.Proxy
} }
//filter out excluded host names //filter out excluded host names
var excluded = endPoint.ExcludedHttpsHostNameRegex != null bool excluded = false;
&& endPoint.ExcludedHttpsHostNameRegex.Any(x => Regex.IsMatch(httpRemoteUri.Host, x));
if (endPoint.ExcludedHttpsHostNameRegex != null)
{
excluded = endPoint.ExcludedHttpsHostNameRegex.Any(x => Regex.IsMatch(httpRemoteUri.Host, x));
}
if (endPoint.IncludedHttpsHostNameRegex != null)
{
excluded = !endPoint.IncludedHttpsHostNameRegex.Any(x => Regex.IsMatch(httpRemoteUri.Host, x));
}
List<HttpHeader> connectRequestHeaders = null; List<HttpHeader> connectRequestHeaders = null;
...@@ -212,7 +221,7 @@ namespace Titanium.Web.Proxy ...@@ -212,7 +221,7 @@ namespace Titanium.Web.Proxy
endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null); endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null);
} }
private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, ExternalProxy customUpStreamHttpProxy, ExternalProxy customUpStreamHttpsProxy, bool CloseConnection) private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, ExternalProxy customUpStreamHttpProxy, ExternalProxy customUpStreamHttpsProxy, bool closeConnection)
{ {
try try
{ {
...@@ -331,7 +340,7 @@ namespace Titanium.Web.Proxy ...@@ -331,7 +340,7 @@ namespace Titanium.Web.Proxy
return; return;
} }
if (CloseConnection) if (closeConnection)
{ {
//dispose //dispose
connection?.Dispose(); connection?.Dispose();
......
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