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

beta #621

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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