Commit 44d042ae authored by justcoding121's avatar justcoding121

Add request Id; refactor process id as Lazy<int>

parent 1acc1ad8
...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
var responseHeaders = e.WebSession.Response.ResponseHeaders; var responseHeaders = e.WebSession.Response.ResponseHeaders;
// print out process id of current session // print out process id of current session
Console.WriteLine($"PID: {e.WebSession.ProcessId}"); Console.WriteLine($"PID: {e.WebSession.ProcessId.Value}");
//if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return; //if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST") if (e.WebSession.Request.Method == "GET" || e.WebSession.Request.Method == "POST")
......
...@@ -60,9 +60,10 @@ namespace Titanium.Web.Proxy ...@@ -60,9 +60,10 @@ namespace Titanium.Web.Proxy
/// Call back to select client certificate used for mutual authentication /// Call back to select client certificate used for mutual authentication
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="certificate"></param> /// <param name="targetHost"></param>
/// <param name="chain"></param> /// <param name="localCertificates"></param>
/// <param name="sslPolicyErrors"></param> /// <param name="remoteCertificate"></param>
/// <param name="acceptableIssuers"></param>
/// <returns></returns> /// <returns></returns>
internal X509Certificate SelectClientCertificate( internal X509Certificate SelectClientCertificate(
object sender, object sender,
...@@ -101,11 +102,11 @@ namespace Titanium.Web.Proxy ...@@ -101,11 +102,11 @@ namespace Titanium.Web.Proxy
{ {
var args = new CertificateSelectionEventArgs(); var args = new CertificateSelectionEventArgs();
args.targetHost = targetHost; args.TargetHost = targetHost;
args.localCertificates = localCertificates; args.LocalCertificates = localCertificates;
args.remoteCertificate = remoteCertificate; args.RemoteCertificate = remoteCertificate;
args.acceptableIssuers = acceptableIssuers; args.AcceptableIssuers = acceptableIssuers;
args.clientCertificate = clientCertificate; args.ClientCertificate = clientCertificate;
Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList(); Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length]; Task[] handlerTasks = new Task[invocationList.Length];
...@@ -117,7 +118,7 @@ namespace Titanium.Web.Proxy ...@@ -117,7 +118,7 @@ namespace Titanium.Web.Proxy
Task.WhenAll(handlerTasks).Wait(); Task.WhenAll(handlerTasks).Wait();
return args.clientCertificate; return args.ClientCertificate;
} }
return clientCertificate; return clientCertificate;
......
...@@ -6,19 +6,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -6,19 +6,15 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// An argument passed on to user for client certificate selection during mutual SSL authentication /// An argument passed on to user for client certificate selection during mutual SSL authentication
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs, IDisposable public class CertificateSelectionEventArgs : EventArgs
{ {
public object sender { get; internal set; } public object Sender { get; internal set; }
public string targetHost { get; internal set; } public string TargetHost { get; internal set; }
public X509CertificateCollection localCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; internal set; }
public X509Certificate remoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; internal set; }
public string[] acceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; internal set; }
public X509Certificate clientCertificate { get; set; } public X509Certificate ClientCertificate { get; set; }
public void Dispose()
{
throw new NotImplementedException();
}
} }
} }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Helpers
{
internal class NetworkHelper
{
private static int FindProcessIdFromLocalPort(int port, IpVersion ipVersion)
{
var tcpRow = TcpHelper.GetExtendedTcpTable(ipVersion).FirstOrDefault(
row => row.LocalEndPoint.Port == port);
return tcpRow?.ProcessId ?? 0;
}
internal static int GetProcessIdFromPort(int port, bool ipV6Enabled)
{
var processId = FindProcessIdFromLocalPort(port, IpVersion.Ipv4);
if (processId > 0 && !ipV6Enabled)
{
return processId;
}
return FindProcessIdFromLocalPort(port, IpVersion.Ipv6);
}
/// <summary>
/// Adapated from below link
/// http://stackoverflow.com/questions/11834091/how-to-check-if-localhost
/// </summary>
/// <param name="address></param>
/// <returns></returns>
internal static bool IsLocalIpAddress(IPAddress address)
{
try
{
// get local IP addresses
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
// test if any host IP equals to any local IP or to localhost
// is localhost
if (IPAddress.IsLoopback(address)) return true;
// is local address
foreach (IPAddress localIP in localIPs)
{
if (address.Equals(localIP)) return true;
}
}
catch { }
return false;
}
}
}
...@@ -14,28 +14,39 @@ namespace Titanium.Web.Proxy.Http ...@@ -14,28 +14,39 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class HttpWebClient public class HttpWebClient
{ {
private int processId;
/// <summary> /// <summary>
/// Connection to server /// Connection to server
/// </summary> /// </summary>
internal TcpConnection ServerConnection { get; set; } internal TcpConnection ServerConnection { get; set; }
public Guid RequestId { get; private set; }
public List<HttpHeader> ConnectHeaders { get; set; } public List<HttpHeader> ConnectHeaders { get; set; }
public Request Request { get; set; } public Request Request { get; set; }
public Response Response { get; set; } public Response Response { get; set; }
/// <summary> /// <summary>
/// PID of the process that is created the current session /// PID of the process that is created the current session when client is running in this machine
/// If client is remote then this will return
/// </summary> /// </summary>
public int ProcessId { get; internal set; } public Lazy<int> ProcessId { get; internal set; }
/// <summary> /// <summary>
/// Is Https? /// Is Https?
/// </summary> /// </summary>
public bool IsHttps => this.Request.RequestUri.Scheme == Uri.UriSchemeHttps; public bool IsHttps => this.Request.RequestUri.Scheme == Uri.UriSchemeHttps;
internal HttpWebClient()
{
this.RequestId = Guid.NewGuid();
this.Request = new Request();
this.Response = new Response();
}
/// <summary> /// <summary>
/// Set the tcp connection to server used by this webclient /// Set the tcp connection to server used by this webclient
/// </summary> /// </summary>
...@@ -46,11 +57,6 @@ namespace Titanium.Web.Proxy.Http ...@@ -46,11 +57,6 @@ namespace Titanium.Web.Proxy.Http
ServerConnection = connection; ServerConnection = connection;
} }
internal HttpWebClient()
{
this.Request = new Request();
this.Response = new Response();
}
/// <summary> /// <summary>
/// Prepare & send the http(s) request /// Prepare & send the http(s) request
......
...@@ -25,31 +25,12 @@ namespace Titanium.Web.Proxy ...@@ -25,31 +25,12 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
partial class ProxyServer partial class ProxyServer
{ {
private int FindProcessIdFromLocalPort(int port, IpVersion ipVersion)
{
var tcpRow = TcpHelper.GetExtendedTcpTable(ipVersion).FirstOrDefault(
row => row.LocalEndPoint.Port == port);
return tcpRow?.ProcessId ?? 0;
}
private int GetProcessIdFromPort(int port, bool ipV6Enabled)
{
var processId = FindProcessIdFromLocalPort(port, IpVersion.Ipv4);
if (processId > 0 && !ipV6Enabled)
{
return processId;
}
return FindProcessIdFromLocalPort(port, IpVersion.Ipv6);
}
//This is called when client is aware of proxy //This is called when client is aware of proxy
//So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy //So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient)
{ {
var processId = GetProcessIdFromPort(((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port, endPoint.IpV6Enabled);
Stream clientStream = tcpClient.GetStream(); Stream clientStream = tcpClient.GetStream();
...@@ -177,10 +158,10 @@ namespace Titanium.Web.Proxy ...@@ -177,10 +158,10 @@ namespace Titanium.Web.Proxy
return; return;
} }
//Now create the request //Now create the request
await HandleHttpSessionRequest(tcpClient, processId, httpCmd, clientStream, clientStreamReader, clientStreamWriter, await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.Host : null, connectRequestHeaders, null, null); httpRemoteUri.Scheme == Uri.UriSchemeHttps ? httpRemoteUri.Host : null, endPoint, connectRequestHeaders, null, null);
} }
catch (Exception ex) catch (Exception)
{ {
Dispose(clientStream, clientStreamReader, clientStreamWriter, null); Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
} }
...@@ -190,7 +171,6 @@ namespace Titanium.Web.Proxy ...@@ -190,7 +171,6 @@ namespace Titanium.Web.Proxy
//So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client //So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
{ {
var processId = GetProcessIdFromPort(((IPEndPoint)tcpClient.Client.RemoteEndPoint).Port, endPoint.IpV6Enabled);
Stream clientStream = tcpClient.GetStream(); Stream clientStream = tcpClient.GetStream();
...@@ -238,8 +218,8 @@ namespace Titanium.Web.Proxy ...@@ -238,8 +218,8 @@ namespace Titanium.Web.Proxy
var httpCmd = await clientStreamReader.ReadLineAsync(); var httpCmd = await clientStreamReader.ReadLineAsync();
//Now create the request //Now create the request
await HandleHttpSessionRequest(tcpClient, processId, httpCmd, clientStream, clientStreamReader, clientStreamWriter, await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
endPoint.EnableSsl ? endPoint.GenericCertificateName : null, null); endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null);
} }
private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, ExternalProxy customUpStreamHttpProxy, ExternalProxy customUpStreamHttpsProxy, bool CloseConnection) private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, ExternalProxy customUpStreamHttpProxy, ExternalProxy customUpStreamHttpsProxy, bool CloseConnection)
...@@ -371,15 +351,14 @@ namespace Titanium.Web.Proxy ...@@ -371,15 +351,14 @@ namespace Titanium.Web.Proxy
/// This is the core request handler method for a particular connection from client /// This is the core request handler method for a particular connection from client
/// </summary> /// </summary>
/// <param name="client"></param> /// <param name="client"></param>
/// <param name="processId"></param>
/// <param name="httpCmd"></param> /// <param name="httpCmd"></param>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="clientStreamReader"></param> /// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param> /// <param name="clientStreamWriter"></param>
/// <param name="httpsHostName"></param> /// <param name="httpsHostName"></param>
/// <returns></returns> /// <returns></returns>
private async Task HandleHttpSessionRequest(TcpClient client, int processId, string httpCmd, Stream clientStream, private async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, List<HttpHeader> connectHeaders, ExternalProxy customUpStreamHttpProxy = null, ExternalProxy customUpStreamHttpsProxy = null) CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, ProxyEndPoint endPoint, List<HttpHeader> connectHeaders, ExternalProxy customUpStreamHttpProxy = null, ExternalProxy customUpStreamHttpsProxy = null)
{ {
TcpConnection connection = null; TcpConnection connection = null;
...@@ -396,8 +375,21 @@ namespace Titanium.Web.Proxy ...@@ -396,8 +375,21 @@ namespace Titanium.Web.Proxy
var args = new SessionEventArgs(BUFFER_SIZE, HandleHttpSessionResponse); var args = new SessionEventArgs(BUFFER_SIZE, HandleHttpSessionResponse);
args.ProxyClient.TcpClient = client; args.ProxyClient.TcpClient = client;
args.WebSession.ConnectHeaders = connectHeaders; args.WebSession.ConnectHeaders = connectHeaders;
args.WebSession.ProcessId = processId;
args.WebSession.ProcessId = new Lazy<int>(() =>
{
var remoteEndPoint = (IPEndPoint)args.ProxyClient.TcpClient.Client.RemoteEndPoint;
//If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
return NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled);
}
//can't access process Id of remote request from remote machine
return -1;
});
try try
{ {
//break up the line into three components (method, remote URL & Http Version) //break up the line into three components (method, remote URL & Http Version)
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
<Compile Include="EventArguments\CertificateSelectionEventArgs.cs" /> <Compile Include="EventArguments\CertificateSelectionEventArgs.cs" />
<Compile Include="EventArguments\CertificateValidationEventArgs.cs" /> <Compile Include="EventArguments\CertificateValidationEventArgs.cs" />
<Compile Include="Extensions\ByteArrayExtensions.cs" /> <Compile Include="Extensions\ByteArrayExtensions.cs" />
<Compile Include="Helpers\Network.cs" />
<Compile Include="Network\CachedCertificate.cs" /> <Compile Include="Network\CachedCertificate.cs" />
<Compile Include="Network\CertificateMaker.cs" /> <Compile Include="Network\CertificateMaker.cs" />
<Compile Include="Network\ProxyClient.cs" /> <Compile Include="Network\ProxyClient.cs" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment