Commit b62f9f14 authored by Jehonathan Thomas's avatar Jehonathan Thomas Committed by GitHub

Merge pull request #211 from justcoding121/develop

Beta release 
parents e2144f40 d0fc544f
...@@ -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
......
Titanium Titanium
======== ========
A light weight http(s) proxy server written in C# A light weight HTTP(S) proxy server written in C#
![Build Status](https://ci.appveyor.com/api/projects/status/rvlxv8xgj0m7lkr4?svg=true) ![Build Status](https://ci.appveyor.com/api/projects/status/rvlxv8xgj0m7lkr4?svg=true)
...@@ -11,10 +11,10 @@ Kindly report only issues/bugs here . For programming help or questions use [Sta ...@@ -11,10 +11,10 @@ Kindly report only issues/bugs here . For programming help or questions use [Sta
Features Features
======== ========
* Supports Http(s) and most features of HTTP 1.1 * Supports HTTP(S) and most features of HTTP 1.1
* Support redirect/block/update requests * Support redirect/block/update requests
* Supports updating response * Supports updating response
* Safely relays WebSocket requests over Http * Safely relays Web Socket requests over HTTP
* Support mutual SSL authentication * Support mutual SSL authentication
* Fully asynchronous proxy * Fully asynchronous proxy
* Supports proxy authentication * Supports proxy authentication
...@@ -23,7 +23,7 @@ Features ...@@ -23,7 +23,7 @@ Features
Usage Usage
===== =====
Refer the HTTP Proxy Server library in your project, look up Test project to learn usage. Refer the HTTP Proxy Server library in your project, look up Test project to learn usage. ([Wiki & Contribution guidelines](https://github.com/justcoding121/Titanium-Web-Proxy/wiki))
Install by nuget: Install by nuget:
...@@ -55,24 +55,24 @@ proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection; ...@@ -55,24 +55,24 @@ proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true) var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{ {
//Exclude Https addresses you don't want to proxy //Exclude HTTPS addresses you don't want to proxy
//Usefull for clients that use certificate pinning //Useful for clients that use certificate pinning
//for example dropbox.com //for example dropbox.com
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" } // ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
//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
//Usefull when certificate trust is not requiered by proxy clients //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")
}; };
//An explicit endpoint is where the client knows about the existance of a proxy //An explicit endpoint is where the client knows about the existence of a proxy
//So client sends request in a proxy friendly manner //So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint); proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start(); proxyServer.Start();
//Warning! Transparent endpoint is not tested end to end //Warning! Transparent endpoint is not tested end to end
//Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy) //Transparent endpoint is useful for reverse proxy (client is not aware of the existence of proxy)
//A transparent endpoint usually requires a network router port forwarding HTTP(S) packets to this endpoint //A transparent endpoint usually requires a network router port forwarding HTTP(S) packets to this endpoint
//Currently do not support Server Name Indication (It is not currently supported by SslStream class) //Currently do not support Server Name Indication (It is not currently supported by SslStream class)
//That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests //That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests
...@@ -110,6 +110,10 @@ proxyServer.Stop(); ...@@ -110,6 +110,10 @@ proxyServer.Stop();
Sample request and response event handlers Sample request and response event handlers
```csharp ```csharp
//To access requestBody from OnResponse handler
private Dictionary<Guid, string> requestBodyHistory;
public async Task OnRequest(object sender, SessionEventArgs e) public async Task OnRequest(object sender, SessionEventArgs e)
{ {
Console.WriteLine(e.WebSession.Request.Url); Console.WriteLine(e.WebSession.Request.Url);
...@@ -127,7 +131,10 @@ public async Task OnRequest(object sender, SessionEventArgs e) ...@@ -127,7 +131,10 @@ public async Task OnRequest(object sender, SessionEventArgs e)
//Get/Set request body as string //Get/Set request body as string
string bodyString = await e.GetRequestBodyAsString(); string bodyString = await e.GetRequestBodyAsString();
await e.SetRequestBodyString(bodyString); await e.SetRequestBodyString(bodyString);
//store request Body/request headers etc with request Id as key
//so that you can find it from response handler using request Id
requestBodyHistory[e.Id] = bodyString;
} }
//To cancel a request with a custom HTML content //To cancel a request with a custom HTML content
...@@ -170,6 +177,12 @@ public async Task OnResponse(object sender, SessionEventArgs e) ...@@ -170,6 +177,12 @@ public async Task OnResponse(object sender, SessionEventArgs e)
} }
} }
} }
//access request body/request headers etc by looking up using requestId
if(requestBodyHistory.ContainsKey(e.Id))
{
var requestBody = requestBodyHistory[e.Id];
}
} }
/// Allows overriding default certificate validation logic /// Allows overriding default certificate validation logic
...@@ -189,7 +202,7 @@ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs ...@@ -189,7 +202,7 @@ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs
return Task.FromResult(0); return Task.FromResult(0);
} }
``` ```
Future roadmap Future road map (Pull requests are welcome!)
============ ============
* Support Server Name Indication (SNI) for transparent endpoints * Support Server Name Indication (SNI) for transparent endpoints
* Support HTTP 2.0 * Support HTTP 2.0
......
...@@ -125,7 +125,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -125,7 +125,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// Removes all types of proxy settings (both http & https) /// Removes all types of proxy settings (both http and https)
/// </summary> /// </summary>
internal void DisableAllProxy() internal void DisableAllProxy()
{ {
......
...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/> /// <see href="http://msdn2.microsoft.com/en-us/library/aa366921.aspx"/>
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct TcpTable internal struct TcpTable
...@@ -52,7 +52,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -52,7 +52,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/> /// <see href="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct TcpRow internal struct TcpRow
...@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -72,7 +72,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/> /// <see href="http://msdn2.microsoft.com/en-us/library/aa365928.aspx"/>
/// </summary> /// </summary>
[DllImport("iphlpapi.dll", SetLastError = true)] [DllImport("iphlpapi.dll", SetLastError = true)]
internal static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int size, bool sort, int ipVersion, int tableClass, int reserved); internal static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int size, bool sort, int ipVersion, int tableClass, int reserved);
...@@ -124,7 +124,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -124,7 +124,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name & port with the given httpCmd & headers as prefix /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix
/// Usefull for websocket requests /// Usefull for websocket requests
/// </summary> /// </summary>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
......
...@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Prepare & send the http(s) request /// Prepare and send the http(s) request
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal async Task SendRequest(bool enable100ContinueBehaviour) internal async Task SendRequest(bool enable100ContinueBehaviour)
...@@ -148,7 +148,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -148,7 +148,7 @@ namespace Titanium.Web.Proxy.Http
} }
/// <summary> /// <summary>
/// Receive & parse the http response from server /// Receive and parse the http response from server
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal async Task ReceiveResponse() internal async Task ReceiveResponse()
......
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";
} }
......
...@@ -48,6 +48,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -48,6 +48,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="keyStrength">The key strength.</param> /// <param name="keyStrength">The key strength.</param>
/// <param name="signatureAlgorithm">The signature algorithm.</param> /// <param name="signatureAlgorithm">The signature algorithm.</param>
/// <param name="issuerPrivateKey">The issuer private key.</param> /// <param name="issuerPrivateKey">The issuer private key.</param>
/// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns> /// <returns>X509Certificate2 instance.</returns>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception> /// <exception cref="PemException">Malformed sequence in RSA private key</exception>
private static X509Certificate2 GenerateCertificate(string hostName, private static X509Certificate2 GenerateCertificate(string hostName,
......
...@@ -34,6 +34,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -34,6 +34,7 @@ namespace Titanium.Web.Proxy.Network
private readonly ICertificateMaker certEngine; private readonly ICertificateMaker certEngine;
private bool clearCertificates { get; set; } private bool clearCertificates { get; set; }
/// <summary> /// <summary>
/// Cache dictionary /// Cache dictionary
/// </summary> /// </summary>
...@@ -42,9 +43,10 @@ namespace Titanium.Web.Proxy.Network ...@@ -42,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,
...@@ -70,17 +72,29 @@ namespace Titanium.Web.Proxy.Network ...@@ -70,17 +72,29 @@ namespace Titanium.Web.Proxy.Network
certificateCache = new ConcurrentDictionary<string, CachedCertificate>(); certificateCache = new ConcurrentDictionary<string, CachedCertificate>();
} }
internal X509Certificate2 GetRootCertificate() private string GetRootCertificatePath()
{ {
var path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
// dynamically loaded assemblies returns string.Empty location
if (assemblyLocation == string.Empty)
{
assemblyLocation = System.Reflection.Assembly.GetEntryAssembly().Location;
}
var path = Path.GetDirectoryName(assemblyLocation);
if (null == path) throw new NullReferenceException(); if (null == path) throw new NullReferenceException();
var fileName = Path.Combine(path, "rootCert.pfx"); var fileName = Path.Combine(path, "rootCert.pfx");
return fileName;
}
internal X509Certificate2 GetRootCertificate()
{
var fileName = GetRootCertificatePath();
if (!File.Exists(fileName)) return null; if (!File.Exists(fileName)) return null;
try try
{ {
return new X509Certificate2(fileName, string.Empty, X509KeyStorageFlags.Exportable); return new X509Certificate2(fileName, string.Empty, X509KeyStorageFlags.Exportable);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -94,35 +108,32 @@ namespace Titanium.Web.Proxy.Network ...@@ -94,35 +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 path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); var fileName = GetRootCertificatePath();
if (null == path) throw new NullReferenceException(); File.WriteAllBytes(fileName, RootCertificate.Export(X509ContentType.Pkcs12));
var fileName = Path.Combine(path, "rootCert.pfx");
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>
...@@ -149,7 +160,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -149,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)
{ {
...@@ -216,7 +227,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -216,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"
...@@ -233,8 +244,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -233,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)
{ {
......
...@@ -7,7 +7,7 @@ using Titanium.Web.Proxy.Models; ...@@ -7,7 +7,7 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
/// <summary> /// <summary>
/// An object that holds TcpConnection to a particular server & port /// An object that holds TcpConnection to a particular server and port
/// </summary> /// </summary>
public class TcpConnection : IDisposable public class TcpConnection : IDisposable
{ {
......
...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -5,7 +5,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
/// <summary> /// <summary>
/// Represents a managed interface of IP Helper API TcpRow struct /// Represents a managed interface of IP Helper API TcpRow struct
/// <see cref="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/> /// <see href="http://msdn2.microsoft.com/en-us/library/aa366913.aspx"/>
/// </summary> /// </summary>
internal class TcpRow internal class TcpRow
{ {
......
...@@ -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>
......
...@@ -54,9 +54,9 @@ namespace Titanium.Web.Proxy ...@@ -54,9 +54,9 @@ namespace Titanium.Web.Proxy
var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3); var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);
//Find the request Verb //Find the request Verb
var httpVerb = httpCmdSplit[0]; var httpVerb = httpCmdSplit[0].ToUpper();
httpRemoteUri = httpVerb.ToUpper() == "CONNECT" ? httpRemoteUri = httpVerb == "CONNECT" ?
new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]); new Uri("http://" + httpCmdSplit[1]) : new Uri(httpCmdSplit[1]);
//parse the HTTP version //parse the HTTP version
...@@ -72,13 +72,22 @@ namespace Titanium.Web.Proxy ...@@ -72,13 +72,22 @@ 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;
//Client wants to create a secure tcp tunnel (its a HTTPS request) //Client wants to create a secure tcp tunnel (its a HTTPS request)
if (httpVerb.ToUpper() == "CONNECT" && !excluded && httpRemoteUri.Port != 80) if (httpVerb == "CONNECT" && !excluded && httpRemoteUri.Port != 80)
{ {
httpRemoteUri = new Uri("https://" + httpCmdSplit[1]); httpRemoteUri = new Uri("https://" + httpCmdSplit[1]);
string tmpLine; string tmpLine;
...@@ -131,7 +140,7 @@ namespace Titanium.Web.Proxy ...@@ -131,7 +140,7 @@ namespace Titanium.Web.Proxy
} }
//Sorry cannot do a HTTPS request decrypt to port 80 at this time //Sorry cannot do a HTTPS request decrypt to port 80 at this time
else if (httpVerb.ToUpper() == "CONNECT") else if (httpVerb == "CONNECT")
{ {
//Cyphen out CONNECT request headers //Cyphen out CONNECT request headers
await clientStreamReader.ReadAllLinesAsync(); await clientStreamReader.ReadAllLinesAsync();
...@@ -139,7 +148,7 @@ namespace Titanium.Web.Proxy ...@@ -139,7 +148,7 @@ namespace Titanium.Web.Proxy
await WriteConnectResponse(clientStreamWriter, version); await WriteConnectResponse(clientStreamWriter, version);
await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port, await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port,
httpCmd, version, null, null, version, null,
false, SupportedSslProtocols, false, SupportedSslProtocols,
ValidateServerCertificate, ValidateServerCertificate,
SelectClientCertificate, SelectClientCertificate,
...@@ -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