Skip to content

Commit

Permalink
[Tools] Added network capture tool
Browse files Browse the repository at this point in the history
  • Loading branch information
leandromonaco committed Mar 2, 2022
1 parent e870662 commit 5815c59
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Tools/Tools.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OctopusCertificateReference
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiraReporting", "src\JiraReporting\JiraReporting.csproj", "{EB5D47D5-6702-4EC0-A1E3-CD48A16C1ECE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{16F9BA96-0BC1-4D3F-91AF-0D096BDCD174}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetworkCapture", "src\NetworkCapture\NetworkCapture.csproj", "{9F260947-AAD2-443E-851E-B7CE5305F7C2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -47,6 +51,10 @@ Global
{EB5D47D5-6702-4EC0-A1E3-CD48A16C1ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB5D47D5-6702-4EC0-A1E3-CD48A16C1ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB5D47D5-6702-4EC0-A1E3-CD48A16C1ECE}.Release|Any CPU.Build.0 = Release|Any CPU
{9F260947-AAD2-443E-851E-B7CE5305F7C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F260947-AAD2-443E-851E-B7CE5305F7C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F260947-AAD2-443E-851E-B7CE5305F7C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F260947-AAD2-443E-851E-B7CE5305F7C2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
12 changes: 12 additions & 0 deletions Tools/src/NetworkCapture/NetworkCapture.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Titanium.Web.Proxy" Version="3.1.1397" />
</ItemGroup>

</Project>
189 changes: 189 additions & 0 deletions Tools/src/NetworkCapture/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
using System;
using System.Net;
using System.Threading.Tasks;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;

namespace NetworkCapture
{
class Program
{
static void Main(string[] args)
{
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();

}

private static 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 static async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine($"Request: {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 static 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);
Console.WriteLine($"Response: {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 static 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 static Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
// set e.clientCertificate to override
return Task.CompletedTask;
}

}
}

0 comments on commit 5815c59

Please sign in to comment.