Unobtanium.Web.Proxy
0.1.1
See the version list below for details.
dotnet add package Unobtanium.Web.Proxy --version 0.1.1
NuGet\Install-Package Unobtanium.Web.Proxy -Version 0.1.1
<PackageReference Include="Unobtanium.Web.Proxy" Version="0.1.1" />
paket add Unobtanium.Web.Proxy --version 0.1.1
#r "nuget: Unobtanium.Web.Proxy, 0.1.1"
// Install Unobtanium.Web.Proxy as a Cake Addin #addin nuget:?package=Unobtanium.Web.Proxy&version=0.1.1 // Install Unobtanium.Web.Proxy as a Cake Tool #tool nuget:?package=Unobtanium.Web.Proxy&version=0.1.1
Unobtanium Web Proxy
A lightweight HTTP(S) proxy server written in C# NET8.0
.
Report bugs or raise issues here.
Project reboot
This project is a reboot of the original Titanium-Web-Proxy project. The original project was last updated two years ago, has been archived by the author on July 9th 2023 and has been inactive since then. This project aims to continue the development of the original project and provide a stable and reliable proxy server library for .NET developers.
Announcement Reboot discussion Issues
Reboot focus
net8.0
only (no support for older versions of .NET!)- Support for
ILogger
See #4 - Support for diagnostic events using
ActivitySource
andActivity
See #3 - Using the latest .NET features like
Span<T>
andMemory<T>
to improve performance - Update dependencies to the latest versions
TLS 1.2
andTLS 1.3
only support- Event-handlers with
HttpRequestMessage
andHttpResponseMessage
, to greatly improve the portability of the library See #6 HttpClient
as the default client, and using the IHttpClientFactory to handle pooling of the clients- Testing, testing, testing!
Features
API DocumentationWiki & Contribution guidelines- Multithreaded and asynchronous proxy employing server connection pooling, certificate cache, and buffer pooling
- View, modify, redirect and block requests or responses
- Supports mutual SSL authentication, proxy authentication & automatic upstream proxy detection
- Supports kerberos, NTLM authentication over HTTP protocols on windows domain controlled networks
- SOCKS4/5 Proxy support
Installation
Package on NuGet, Unobtanium.Web.Proxy
will be a partial drop-in replacement for Titanium.Web.Proxy
, if you're on NET8.0 or higher
.
dotnet add package Unobtanium.Web.Proxy
Supports
.NET 8.0
and above
As stated above, this project is a reboot of the original project. Expect things to change, everything marked as obsolete
in the original project will be removed in this project. And until this is v1.0.0
, expect breaking changes.
Collaborators
The owner of this project, justcoding121, is considered to be inactive from this project due to his busy work schedule. See project reboot for more information.
Previous contributors:
- justcoding121 owner
- honfika
Current contributors:
You contributions are more then welcome! Let's make this project great again!
Development environment
Since this is a dotnet
project I would suggest to use Visual Studio 2022
or Visual Studio Code
as your development environment. The project is set up to use the dotnet
CLI, so you can also use that to build and run the project.
Usage
Refer the Unobtanium.Web.Proxy
in your project and check one of the example projects.
Setup HTTP proxy:
using Titanium.Web.Proxy;
...
var proxyServer = new ProxyServer();
// locally trust root certificate used by this proxy
proxyServer.CertificateManager.TrustRootCertificate(true);
// optionally set the Certificate Engine
// Under Mono only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
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")
};
// Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
// 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
var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
// Generic Certificate hostname to use
// when SNI is disabled by client
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} ",
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
// 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
explicitEndPoint.BeforeTunnelConnectRequest -= OnBeforeTunnelConnectRequest;
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
proxyServer.Stop();
Sample request and response event handlers
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
e.DecryptSsl = false;
}
}
public async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine(e.HttpClient.Request.Url);
// read request headers
var requestHeaders = e.HttpClient.Request.Headers;
var method = e.HttpClient.Request.Method.ToUpper();
if ((method == "POST" || method == "PUT" || method == "PATCH"))
{
// Get/Set request body bytes
byte[] bodyBytes = await e.GetRequestBody();
e.SetRequestBody(bodyBytes);
// Get/Set request body as string
string bodyString = await e.GetRequestBodyAsString();
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
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>");
}
// Redirect example
if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{
e.Redirect("https://www.paypal.com");
}
}
// Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
// read response headers
var responseHeaders = e.HttpClient.Response.Headers;
//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.StatusCode == 200)
{
if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
{
byte[] bodyBytes = await e.GetResponseBody();
e.SetResponseBody(bodyBytes);
string body = await e.GetResponseBodyAsString();
e.SetResponseBodyString(body);
}
}
}
if (e.UserData != null)
{
// access request from UserData property where we stored it in RequestHandler
var request = (Request)e.UserData;
}
}
// Allows overriding default certificate validation logic
public Task 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;
return Task.CompletedTask;
}
// Allows overriding default client certificate selection logic during mutual authentication
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
// set e.clientCertificate to override
return Task.CompletedTask;
}
Console example application screenshot
GUI example application screenshot
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- BouncyCastle.Cryptography (>= 2.4.0)
- BrotliSharpLib (>= 0.3.3)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.1)
- System.Runtime.CompilerServices.Unsafe (>= 6.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Unobtanium.Web.Proxy:
Repository | Stars |
---|---|
microsoft/dev-proxy
Dev Proxy is an API simulator that helps you effortlessly test your app beyond the happy path.
|