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

Commit

Permalink
issues #67 #69 #70 #71 #72
Browse files Browse the repository at this point in the history
  • Loading branch information
justcoding121 committed May 19, 2016
1 parent e4c68b0 commit 95877cd
Show file tree
Hide file tree
Showing 36 changed files with 1,119 additions and 931 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;

namespace Titanium.Web.Proxy.Test
namespace Titanium.Web.Proxy.Examples.Basic
{
public class Program
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;

namespace Titanium.Web.Proxy.Test
namespace Titanium.Web.Proxy.Examples.Basic
{
public class ProxyTestController
{
public void StartProxy()
{
ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse;
ProxyServer.RemoteCertificateValidationCallback += OnCertificateValidation;

//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
Expand All @@ -34,13 +35,14 @@ public void StartProxy()
//That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests
//In this example only google.com will work for HTTPS requests
//Other sites will receive a certificate mismatch warning on browser
//Please read about it before asking questions!
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
GenericCertificateName = "google.com"
};
ProxyServer.AddEndPoint(transparentEndPoint);

//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };

foreach (var endPoint in ProxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
Expand All @@ -63,12 +65,12 @@ public void Stop()
//Read browser URL send back to proxy by the injection script in OnResponse event
public void OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine(e.ProxySession.Request.Url);
Console.WriteLine(e.WebSession.Request.Url);

//read request headers
var requestHeaders = e.ProxySession.Request.RequestHeaders;
////read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders;

if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT"))
if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT"))
{
//Get/Set request body bytes
byte[] bodyBytes = e.GetRequestBody();
Expand All @@ -82,7 +84,7 @@ public void OnRequest(object sender, SessionEventArgs e)

//To cancel a request with a custom HTML content
//Filter URL
if (e.ProxySession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
{
e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" +
Expand All @@ -93,7 +95,7 @@ public void OnRequest(object sender, SessionEventArgs e)
"</html>");
}
//Redirect example
if (e.ProxySession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{
e.Redirect("https://www.paypal.com");
}
Expand All @@ -105,14 +107,14 @@ public void OnResponse(object sender, SessionEventArgs e)
{

//read response headers
var responseHeaders = e.ProxySession.Response.ResponseHeaders;
var responseHeaders = e.WebSession.Response.ResponseHeaders;

//if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
if (e.RequestMethod == "GET" || e.RequestMethod == "POST")
if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
{
if (e.ProxySession.Response.ResponseStatusCode == "200")
if (e.WebSession.Response.ResponseStatusCode == "200")
{
if (e.ProxySession.Response.ContentType.Trim().ToLower().Contains("text/html"))
if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
{
byte[] bodyBytes = e.GetResponseBody();
e.SetResponseBody(bodyBytes);
Expand All @@ -123,5 +125,19 @@ public void OnResponse(object sender, SessionEventArgs e)
}
}
}

/// <summary>
/// Allows overriding default certificate validation logic
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
e.IsValid = true;
else
e.Session.Ok("Cannot validate server certificate! Not safe to proceed.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<ProjectGuid>{F3B7E553-1904-4E80-BDC7-212342B5C952}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Titanium.Web.Proxy.Test</RootNamespace>
<AssemblyName>Titanium.Web.Proxy.Test</AssemblyName>
<RootNamespace>Titanium.Web.Proxy.Examples.Basic</RootNamespace>
<AssemblyName>Titanium.Web.Proxy.Examples.Basic</AssemblyName>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
Expand Down Expand Up @@ -65,7 +65,7 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj">
<ProjectReference Include="..\..\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj">
<Project>{8d73a1be-868c-42d2-9ece-f32cc1a02906}</Project>
<Name>Titanium.Web.Proxy</Name>
</ProjectReference>
Expand Down
136 changes: 84 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A light weight http(s) proxy server written in C#

Kindly report only issues/bugs here . For programming help or questions use [StackOverflow](http://stackoverflow.com/questions/tagged/titanium-web-proxy) with the tag Titanium-Web-Proxy.

![alt tag](https://raw.githubusercontent.com/titanium007/Titanium/master/Titanium.Web.Proxy.Test/Capture.PNG)
![alt tag](https://raw.githubusercontent.com/titanium007/Titanium/master/Titanium-Web-Proxy/Examples/Titanium.Web.Proxy.Examples.Basic/Capture.PNG)

Features
========
Expand All @@ -32,52 +32,69 @@ After installing nuget package mark following files to be copied to app director
Setup HTTP proxy:

```csharp
// listen to client request & server response events
ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse;

var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true){
//Exclude Https addresses you don't want to proxy/cannot be proxied
//for example exclude dropbox client which use certificate pinning
ExcludedHttpsHostNameRegex = new List<string>() { "dropbox.com" }
};

//Add an explicit endpoint where the client is aware of the proxy
//So client would send request in a proxy friendly manner
ProxyServer.AddEndPoint(explicitEndPoint);
ProxyServer.Start();

//Only explicit proxies can be set as a system proxy!
ProxyServer.SetAsSystemHttpProxy(explicitEndPoint);
ProxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
ProxyServer.BeforeRequest += OnRequest;
ProxyServer.BeforeResponse += OnResponse;
ProxyServer.RemoteCertificateValidationCallback += OnCertificateValidation;

//Exclude Https addresses you don't want to proxy
//Usefull for clients that use certificate pinning
//for example dropbox.com
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{
// ExcludedHttpsHostNameRegex = new List<string>() { "google.com", "dropbox.com" }
};

//An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner
ProxyServer.AddEndPoint(explicitEndPoint);
ProxyServer.Start();


//Transparent endpoint is usefull for reverse proxying (client is not aware of the existance of proxy)
//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)
//That means that the transparent endpoint will always provide the same Generic Certificate to all HTTPS requests
//In this example only google.com will work for HTTPS requests
//Other sites will receive a certificate mismatch warning on browser
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
GenericCertificateName = "google.com"
};
ProxyServer.AddEndPoint(transparentEndPoint);


foreach (var endPoint in ProxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
//ProxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//ProxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
foreach (var endPoint in ProxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);

//wait here (You can use something else as a wait function, I am using this as a demo)
Console.Read();
//Only explicit proxies can be set as system proxy!
ProxyServer.SetAsSystemHttpProxy(explicitEndPoint);
ProxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

//wait here (You can use something else as a wait function, I am using this as a demo)
Console.Read();

//Unsubscribe & Quit
ProxyServer.BeforeRequest -= OnRequest;
ProxyServer.BeforeResponse -= OnResponse;
ProxyServer.Stop();
//Unsubscribe & Quit
ProxyServer.BeforeRequest -= OnRequest;
ProxyServer.BeforeResponse -= OnResponse;
ProxyServer.Stop();

```
Sample request and response event handlers

```csharp

//Test On Request, intecept requests
//Read browser URL send back to proxy by the injection script in OnResponse event
public void OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine(e.ProxySession.Request.Url);
Console.WriteLine(e.WebSession.Request.Url);

//read request headers
var requestHeaders = e.ProxySession.Request.RequestHeaders;
////read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders;

if ((e.RequestMethod.ToUpper() == "POST" || e.RequestMethod.ToUpper() == "PUT"))
if ((e.WebSession.Request.Method.ToUpper() == "POST" || e.WebSession.Request.Method.ToUpper() == "PUT"))
{
//Get/Set request body bytes
byte[] bodyBytes = e.GetRequestBody();
Expand All @@ -91,43 +108,58 @@ Sample request and response event handlers

//To cancel a request with a custom HTML content
//Filter URL
if (e.ProxySession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("google.com"))
{
e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" +
"Website Blocked" +
"</h1>" +
"<p>Blocked by titanium web proxy.</p>" +
"</body>" +
"</html>");
}
//Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{
e.Ok("<!DOCTYPE html>"+
"<html><body><h1>"+
"Website Blocked"+
"</h1>"+
"<p>Blocked by titanium web proxy.</p>"+
"</body>"+
"</html>");
e.Redirect("https://www.paypal.com");
}
}

//Test script injection
//Insert script to read the Browser URL and send it back to proxy

public void OnResponse(object sender, SessionEventArgs e)
{

//read response headers
var responseHeaders = e.ProxySession.Response.ResponseHeaders;
var responseHeaders = e.WebSession.Response.ResponseHeaders;


if (e.RequestMethod == "GET" || e.RequestMethod == "POST")
//if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
{
if (e.ProxySession.Response.ResponseStatusCode == "200")
if (e.WebSession.Response.ResponseStatusCode == "200")
{
if (e.ProxySession.Response.ContentType.Trim().ToLower().Contains("text/html"))
if (e.WebSession.Response.ContentType.Trim().ToLower().Contains("text/html"))
{
byte[] bodyBytes = e.GetResponseBody();
e.SetResponseBody(bodyBytes);

string body = e.GetResponseBodyAsString();
e.SetResponseBodyString(body);
}
}
}
}

// Allows overriding default certificate validation logic
public void OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
e.IsValid = true;
else
e.Session.Ok("Cannot validate server certificate! Not safe to proceed.");
}
```
Future roadmap
============
* Add callbacks for client/server certificate validation/selection
* Support mutual authentication
* Support Server Name Indication (SNI) for transparent endpoints
* Support HTTP 2.0
Expand Down
6 changes: 0 additions & 6 deletions Titanium.Web.Proxy.Test/Titanium.Web.Proxy.Test.csproj.user

This file was deleted.

27 changes: 20 additions & 7 deletions Titanium.Web.Proxy.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Test", "Titanium.Web.Proxy.Test\Titanium.Web.Proxy.Test.csproj", "{F3B7E553-1904-4E80-BDC7-212342B5C952}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy", "Titanium.Web.Proxy\Titanium.Web.Proxy.csproj", "{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}"
EndProject
Expand All @@ -16,20 +14,35 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6FD3B8
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.Examples.Basic", "Examples\Titanium.Web.Proxy.Examples.Basic\Titanium.Web.Proxy.Examples.Basic.csproj", "{F3B7E553-1904-4E80-BDC7-212342B5C952}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{38EA62D0-D2CB-465D-AF4F-407C5B4D4A1E}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{AC9AE37A-3059-4FDB-9A5C-363AD86F2EEF}"
ProjectSection(SolutionItems) = preProject
.build\Bootstrap.ps1 = .build\Bootstrap.ps1
.build\Common.psm1 = .build\Common.psm1
.build\default.ps1 = .build\default.ps1
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.Build.0 = Release|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D73A1BE-868C-42D2-9ECE-F32CC1A02906}.Release|Any CPU.Build.0 = Release|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3B7E553-1904-4E80-BDC7-212342B5C952}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading

0 comments on commit 95877cd

Please sign in to comment.