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

Commit

Permalink
Merge pull request #625 from justcoding121/beta
Browse files Browse the repository at this point in the history
Stable
  • Loading branch information
honfika authored Aug 30, 2019
2 parents 0737791 + 53ba585 commit 4a7ccfa
Show file tree
Hide file tree
Showing 29 changed files with 350 additions and 552 deletions.
142 changes: 70 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
## Titanium Web Proxy

### Note: This Project is no longer maintained. Any pull requests for fixes are welcome.

A lightweight HTTP(S) proxy server written in C#.

<a href="https://ci.appveyor.com/project/justcoding121/titanium-web-proxy">![Build Status](https://ci.appveyor.com/api/projects/status/p5vvtbpx9yp250ol?svg=true)</a> [![Join the chat at https://gitter.im/Titanium-Web-Proxy/Lobby](https://badges.gitter.im/Titanium-Web-Proxy/Lobby.svg)](https://gitter.im/Titanium-Web-Proxy/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Expand Down Expand Up @@ -32,7 +30,7 @@ For stable releases on [stable branch](https://github.com/justcoding121/Titanium
Supports

* .Net Standard 2.0 or above
* .Net Framework 4.5 or above
* .Net Framework 4.6.1 or above

### Development environment

Expand All @@ -57,11 +55,11 @@ Setup HTTP proxy:
```csharp
var proxyServer = new ProxyServer();

//locally trust root certificate used by this proxy
// locally trust root certificate used by this proxy
proxyServer.CertificateManager.TrustRootCertificate = true;

//optionally set the Certificate Engine
//Under Mono only BouncyCastle will be supported
// optionally set the Certificate Engine
// Under Mono only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
proxyServer.BeforeRequest += OnRequest;
Expand All @@ -72,28 +70,28 @@ proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;

var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{
//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")
// 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")
};

//Fired when a CONNECT request is received
// 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
// 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);
proxyServer.Start();

//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 or DNS
//to send data to this endPoint
// 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 or DNS
// to send data to this endPoint
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
//Generic Certificate hostname to use
//when SNI is disabled by client
GenericCertificateName = "google.com"
// Generic Certificate hostname to use
// when SNI is disabled by client
GenericCertificateName = "google.com"
};

proxyServer.AddEndPoint(transparentEndPoint);
Expand All @@ -105,36 +103,36 @@ 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);

//Only explicit proxies can be set as system proxy!
// 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)
// wait here (You can use something else as a wait function, I am using this as a demo)
Console.Read();

//Unsubscribe & Quit
// Unsubscribe & Quit
explicitEndPoint.BeforeTunnelConnect -= OnBeforeTunnelConnect;
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;

proxyServer.Stop();
```
Sample request and response event handlers

```csharp
```csharp

private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.HttpClient.Request.RequestUri.Host;

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
// Exclude Https addresses you don't want to proxy
// Useful for clients that use certificate pinning
// for example dropbox.com
e.DecryptSsl = false;
}
}
Expand All @@ -143,88 +141,88 @@ public async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine(e.HttpClient.Request.Url);

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

var method = e.HttpClient.Request.Method.ToUpper();
if ((method == "POST" || method == "PUT" || method == "PATCH"))
{
//Get/Set request body bytes
byte[] bodyBytes = await e.GetRequestBody();
await e.SetRequestBody(bodyBytes);

//Get/Set request body as string
string bodyString = await e.GetRequestBodyAsString();
await e.SetRequestBodyString(bodyString);
//store request
//so that you can find it from response handler
e.UserData = e.HttpClient.Request;
// Get/Set request body bytes
byte[] bodyBytes = await e.GetRequestBody();
await e.SetRequestBody(bodyBytes);

// Get/Set request body as string
string bodyString = await e.GetRequestBodyAsString();
await e.SetRequestBodyString(bodyString);
// store request
// so that you can find it from response handler
e.UserData = e.HttpClient.Request;
}

//To cancel a request with a custom HTML content
//Filter URL
// To cancel a request with a custom HTML content
// Filter URL
if (e.HttpClient.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>");
e.Ok("<!DOCTYPE html>" +
"<html><body><h1>" +
"Website Blocked" +
"</h1>" +
"<p>Blocked by titanium web proxy.</p>" +
"</body>" +
"</html>");
}
//Redirect example

// Redirect example
if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{
e.Redirect("https://www.paypal.com");
e.Redirect("https://www.paypal.com");
}
}

//Modify response
// Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
//read response headers
// read response headers
var responseHeaders = e.HttpClient.Response.ResponseHeaders;

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

string body = await e.GetResponseBodyAsString();
await e.SetResponseBodyString(body);
}
}
if (e.HttpClient.Response.ResponseStatusCode == "200")
{
if (e.HttpClient.Response.ContentType!=null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
{
byte[] bodyBytes = await e.GetResponseBody();
await e.SetResponseBody(bodyBytes);

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

if(e.UserData!=null)
if (e.UserData!=null)
{
//access request from UserData property where we stored it in RequestHandler
var request = (Request)e.UserData;
// access request from UserData property where we stored it in RequestHandler
var request = (Request)e.UserData;
}

}

/// Allows overriding default certificate validation logic
// Allows overriding default certificate validation logic
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
// set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
e.IsValid = true;
e.IsValid = true;

return Task.FromResult(0);
}

/// Allows overriding default client certificate selection logic during mutual authentication
// Allows overriding default client certificate selection logic during mutual authentication
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
//set e.clientCertificate to override
// set e.clientCertificate to override
return Task.FromResult(0);
}
```
Expand Down
Loading

0 comments on commit 4a7ccfa

Please sign in to comment.