Commit 2bd909fa authored by Honfika's avatar Honfika

Add the Excluded property to the TunnelConnectRequest event

parent 4d4ab9ac
...@@ -69,9 +69,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -69,9 +69,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
}; };
//Fired when a CONNECT request is received //Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnect += OnBeforeTunnelConnect;
explicitEndPoint.TunnelConnectRequest += OnTunnelConnectRequest; explicitEndPoint.TunnelConnectRequest += OnTunnelConnectRequest;
explicitEndPoint.TunnelConnectResponse += OnTunnelConnectResponse; explicitEndPoint.TunnelConnectResponse += OnTunnelConnectResponse;
...@@ -111,7 +108,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -111,7 +108,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void Stop() public void Stop()
{ {
explicitEndPoint.BeforeTunnelConnect -= OnBeforeTunnelConnect;
explicitEndPoint.TunnelConnectRequest -= OnTunnelConnectRequest; explicitEndPoint.TunnelConnectRequest -= OnTunnelConnectRequest;
explicitEndPoint.TunnelConnectResponse -= OnTunnelConnectResponse; explicitEndPoint.TunnelConnectResponse -= OnTunnelConnectResponse;
...@@ -126,26 +122,20 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -126,26 +122,20 @@ namespace Titanium.Web.Proxy.Examples.Basic
//proxyServer.CertificateManager.RemoveTrustedRootCertificates(); //proxyServer.CertificateManager.RemoveTrustedRootCertificates();
} }
private async Task<bool> OnBeforeTunnelConnect(string hostname) private async Task OnTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
string hostname = e.WebSession.Request.Host;
Console.WriteLine("Tunnel to: " + hostname);
if (hostname.Contains("dropbox.com")) if (hostname.Contains("dropbox.com"))
{ {
//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 dropbox.com
return await Task.FromResult(true); e.Excluded = true;
}
else
{
return await Task.FromResult(false);
} }
} }
private async Task OnTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
Console.WriteLine("Tunnel to: " + e.WebSession.Request.Host);
}
private async Task OnTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e) private async Task OnTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{ {
} }
......
...@@ -6,7 +6,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -6,7 +6,9 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
public class TunnelConnectSessionEventArgs : SessionEventArgs public class TunnelConnectSessionEventArgs : SessionEventArgs
{ {
public bool IsHttpsConnect { get; set; } public bool Excluded { get; set; }
public bool IsHttpsConnect { get; internal set; }
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, Action<Exception> exceptionFunc) internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, Action<Exception> exceptionFunc)
: base(bufferSize, endPoint, exceptionFunc) : base(bufferSize, endPoint, exceptionFunc)
......
using System; using System;
using System.Collections.Generic; using System.Net;
using System.Linq; using System.Security.Cryptography.X509Certificates;
using System.Net; using System.Threading.Tasks;
using System.Net.Sockets; using Titanium.Web.Proxy.EventArguments;
using System.Security.Cryptography.X509Certificates; using Titanium.Web.Proxy.Extensions;
using System.Text.RegularExpressions;
using System.Threading.Tasks; namespace Titanium.Web.Proxy.Models
using Titanium.Web.Proxy.EventArguments; {
using Titanium.Web.Proxy.Extensions; /// <summary>
/// A proxy endpoint that the client is aware of
namespace Titanium.Web.Proxy.Models /// So client application know that it is communicating with a proxy server
{ /// </summary>
/// <summary> public class ExplicitProxyEndPoint : ProxyEndPoint
/// An abstract endpoint where the proxy listens {
/// </summary> internal bool IsSystemHttpProxy { get; set; }
public abstract class ProxyEndPoint
{ internal bool IsSystemHttpsProxy { get; set; }
/// <summary>
/// Constructor. /// <summary>
/// </summary> /// Generic certificate to use for SSL decryption.
/// <param name="ipAddress"></param> /// </summary>
/// <param name="port"></param> public X509Certificate2 GenericCertificate { get; set; }
/// <param name="enableSsl"></param>
protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) /// <summary>
{ /// Intercept tunnel connect request
IpAddress = ipAddress; /// Valid only for explicit endpoints
Port = port; /// Set the <see cref="TunnelConnectSessionEventArgs.Excluded"/> property to true if this HTTP connect request should'nt be decrypted and instead be relayed
EnableSsl = enableSsl; /// </summary>
} public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectRequest;
/// <summary> /// <summary>
/// underlying TCP Listener object /// Intercept tunnel connect response
/// </summary> /// Valid only for explicit endpoints
internal TcpListener Listener { get; set; } /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectResponse;
/// <summary>
/// Ip Address we are listening. /// <summary>
/// </summary> /// Constructor.
public IPAddress IpAddress { get; internal set; } /// </summary>
/// <param name="ipAddress"></param>
/// <summary> /// <param name="port"></param>
/// Port we are listening. /// <param name="enableSsl"></param>
/// </summary> public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) : base(ipAddress, port, enableSsl)
public int Port { get; internal set; } {
}
/// <summary>
/// Enable SSL? internal async Task InvokeTunnectConnectRequest(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc)
/// </summary> {
public bool EnableSsl { get; internal set; } if (TunnelConnectRequest != null)
{
/// <summary> await TunnelConnectRequest.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
/// Is IPv6 enabled? }
/// </summary> }
public bool IpV6Enabled => Equals(IpAddress, IPAddress.IPv6Any)
|| Equals(IpAddress, IPAddress.IPv6Loopback) internal async Task InvokeTunnectConnectResponse(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc, bool isClientHello = false)
|| Equals(IpAddress, IPAddress.IPv6None); {
} if (TunnelConnectResponse != null)
{
/// <summary> connectArgs.IsHttpsConnect = isClientHello;
/// A proxy endpoint that the client is aware of await TunnelConnectResponse.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
/// So client application know that it is communicating with a proxy server }
/// </summary> }
public class ExplicitProxyEndPoint : ProxyEndPoint }
{ }
internal List<Regex> ExcludedHttpsHostNameRegexList; \ No newline at end of file
internal List<Regex> IncludedHttpsHostNameRegexList;
internal bool IsSystemHttpProxy { get; set; }
internal bool IsSystemHttpsProxy { get; set; }
/// <summary>
/// Generic certificate to use for SSL decryption.
/// </summary>
public X509Certificate2 GenericCertificate { get; set; }
/// <summary>
/// Return true if this HTTP connect request should'nt be decrypted and instead be relayed
/// Valid only for explicit endpoints
/// </summary>
public Func<string, Task<bool>> BeforeTunnelConnect;
/// <summary>
/// Intercept tunnel connect request
/// Valid only for explicit endpoints
/// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectRequest;
/// <summary>
/// Intercept tunnel connect response
/// Valid only for explicit endpoints
/// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectResponse;
/// <summary>
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) : base(ipAddress, port, enableSsl)
{
}
internal async Task InvokeTunnectConnectRequest(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc)
{
if (TunnelConnectRequest != null)
{
await TunnelConnectRequest.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
}
}
internal async Task InvokeTunnectConnectResponse(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc)
{
if (TunnelConnectResponse != null)
{
await TunnelConnectResponse.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
}
}
internal async Task InvokeTunnectConnectResponse(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc, bool isClientHello)
{
if (TunnelConnectResponse != null)
{
connectArgs.IsHttpsConnect = isClientHello;
await TunnelConnectResponse.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
}
}
}
/// <summary>
/// A proxy end point client is not aware of
/// Usefull when requests are redirected to this proxy end point through port forwarding
/// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint
{
/// <summary>
/// Name of the Certificate need to be sent (same as the hostname we want to proxy)
/// This is valid only when UseServerNameIndication is set to false
/// </summary>
public string GenericCertificateName { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) : base(ipAddress, port, enableSsl)
{
GenericCertificateName = "localhost";
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
namespace Titanium.Web.Proxy.Models
{
/// <summary>
/// An abstract endpoint where the proxy listens
/// </summary>
public abstract class ProxyEndPoint
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
{
IpAddress = ipAddress;
Port = port;
EnableSsl = enableSsl;
}
/// <summary>
/// underlying TCP Listener object
/// </summary>
internal TcpListener Listener { get; set; }
/// <summary>
/// Ip Address we are listening.
/// </summary>
public IPAddress IpAddress { get; }
/// <summary>
/// Port we are listening.
/// </summary>
public int Port { get; internal set; }
/// <summary>
/// Enable SSL?
/// </summary>
public bool EnableSsl { get; }
/// <summary>
/// Is IPv6 enabled?
/// </summary>
public bool IpV6Enabled => Equals(IpAddress, IPAddress.IPv6Any)
|| Equals(IpAddress, IPAddress.IPv6Loopback)
|| Equals(IpAddress, IPAddress.IPv6None);
}
}
using System.Net;
namespace Titanium.Web.Proxy.Models
{
/// <summary>
/// A proxy end point client is not aware of
/// Usefull when requests are redirected to this proxy end point through port forwarding
/// </summary>
public class TransparentProxyEndPoint : ProxyEndPoint
{
/// <summary>
/// Name of the Certificate need to be sent (same as the hostname we want to proxy)
/// This is valid only when UseServerNameIndication is set to false
/// </summary>
public string GenericCertificateName { get; set; }
/// <summary>
/// Constructor.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) : base(ipAddress, port, enableSsl)
{
GenericCertificateName = "localhost";
}
}
}
\ No newline at end of file
...@@ -64,14 +64,6 @@ namespace Titanium.Web.Proxy ...@@ -64,14 +64,6 @@ namespace Titanium.Web.Proxy
var httpRemoteUri = new Uri("http://" + httpUrl); var httpRemoteUri = new Uri("http://" + httpUrl);
connectHostname = httpRemoteUri.Host; connectHostname = httpRemoteUri.Host;
//filter out excluded host names
bool excluded = false;
if(endPoint.BeforeTunnelConnect!=null)
{
excluded = await endPoint.BeforeTunnelConnect(connectHostname);
}
connectRequest = new ConnectRequest connectRequest = new ConnectRequest
{ {
RequestUri = httpRemoteUri, RequestUri = httpRemoteUri,
...@@ -86,7 +78,9 @@ namespace Titanium.Web.Proxy ...@@ -86,7 +78,9 @@ namespace Titanium.Web.Proxy
connectArgs.ProxyClient.ClientStream = clientStream; connectArgs.ProxyClient.ClientStream = clientStream;
await endPoint.InvokeTunnectConnectRequest(this, connectArgs, ExceptionFunc); await endPoint.InvokeTunnectConnectRequest(this, connectArgs, ExceptionFunc);
//filter out excluded host names
bool excluded = connectArgs.Excluded;
if (await CheckAuthorization(clientStreamWriter, connectArgs) == false) if (await CheckAuthorization(clientStreamWriter, connectArgs) == false)
{ {
......
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