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

stable #692

Merged
merged 13 commits into from
Nov 30, 2019
Merged
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
72 changes: 66 additions & 6 deletions examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;

namespace Titanium.Web.Proxy.Examples.Basic
{
Expand All @@ -22,6 +25,9 @@ public class ProxyTestController
public ProxyTestController()
{
proxyServer = new ProxyServer();

//proxyServer.EnableHttp2 = true;

// generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false);

Expand All @@ -32,16 +38,20 @@ public ProxyTestController()
{
if (exception is ProxyHttpException phex)
{
await writeToConsole(exception.Message + ": " + phex.InnerException?.Message, true);
await writeToConsole(exception.Message + ": " + phex.InnerException?.Message, ConsoleColor.Red);
}
else
{
await writeToConsole(exception.Message, true);
await writeToConsole(exception.Message, ConsoleColor.Red);
}
};
proxyServer.ForwardToUpstreamGateway = true;
proxyServer.CertificateManager.SaveFakeCertificates = true;

// this is just to show the functionality, provided implementations use junk value
//proxyServer.GetCustomUpStreamProxyFunc = onGetCustomUpStreamProxyFunc;
//proxyServer.CustomUpStreamProxyFailureFunc = onCustomUpStreamProxyFailureFunc;

// optionally set the Certificate Engine
// Under Mono or Non-Windows runtimes only BouncyCastle will be supported
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
Expand Down Expand Up @@ -116,6 +126,18 @@ public void Stop()
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
}

private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
{
// this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false };
}

private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
{
// this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false };
}

private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
string hostname = e.HttpClient.Request.RequestUri.Host;
Expand All @@ -130,12 +152,44 @@ private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSess
}
}

private void WebSocket_DataSent(object sender, DataEventArgs e)
{
var args = (SessionEventArgs)sender;
WebSocketDataSentReceived(args, e, true);
}

private void WebSocket_DataReceived(object sender, DataEventArgs e)
{
var args = (SessionEventArgs)sender;
WebSocketDataSentReceived(args, e, false);
}

private void WebSocketDataSentReceived(SessionEventArgs args, DataEventArgs e, bool sent)
{
var color = sent ? ConsoleColor.Green : ConsoleColor.Blue;

foreach (var frame in args.WebSocketDecoder.Decode(e.Buffer, e.Offset, e.Count))
{
if (frame.OpCode == WebsocketOpCode.Binary)
{
var data = frame.Data.ToArray();
string str = string.Join(",", data.ToArray().Select(x => x.ToString("X2")));
writeToConsole(str, color).Wait();
}

if (frame.OpCode == WebsocketOpCode.Text)
{
writeToConsole(frame.GetText(), color).Wait();
}
}
}

private Task onBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{
return Task.FromResult(false);
}

// intecept & cancel redirect or update requests
// intercept & cancel redirect or update requests
private async Task onRequest(object sender, SessionEventArgs e)
{
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
Expand Down Expand Up @@ -189,6 +243,12 @@ private async Task multipartRequestPartSent(object sender, MultipartRequestPartS

private async Task onResponse(object sender, SessionEventArgs e)
{
if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket)
{
e.DataSent += WebSocket_DataSent;
e.DataReceived += WebSocket_DataReceived;
}

await writeToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);

string ext = System.IO.Path.GetExtension(e.HttpClient.Request.RequestUri.AbsolutePath);
Expand Down Expand Up @@ -261,14 +321,14 @@ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs
return Task.FromResult(0);
}

private async Task writeToConsole(string message, bool useRedColor = false)
private async Task writeToConsole(string message, ConsoleColor? consoleColor = null)
{
await @lock.WaitAsync();

if (useRedColor)
if (consoleColor.HasValue)
{
ConsoleColor existing = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Red;
Console.ForegroundColor = consoleColor.Value;
Console.WriteLine(message);
Console.ForegroundColor = existing;
}
Expand Down
2 changes: 2 additions & 0 deletions examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" />
<GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" />
<GridViewColumn Header="ClientEndPoint" DisplayMemberBinding="{Binding ClientEndPoint}" />
<GridViewColumn Header="ClientConnectionId" DisplayMemberBinding="{Binding ClientConnectionId}" />
<GridViewColumn Header="ServerConnectionId" DisplayMemberBinding="{Binding ServerConnectionId}" />
</GridView>
</ListView.View>
</ListView>
Expand Down
41 changes: 32 additions & 9 deletions examples/Titanium.Web.Proxy.Examples.Wpf/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,15 @@ await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.HttpClient, out var item))
{
item.Update();
item.Update(e);
}
});
}

private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
{
//if (e.HttpClient.Request.HttpVersion.Major != 2) return;

SessionListItem item = null;
await Dispatcher.InvokeAsync(() => { item = addSession(e); });

Expand All @@ -175,7 +177,7 @@ await Dispatcher.InvokeAsync(() =>
{
if (sessionDictionary.TryGetValue(e.HttpClient, out item))
{
item.Update();
item.Update(e);
}
});

Expand All @@ -190,7 +192,7 @@ await Dispatcher.InvokeAsync(() =>
e.HttpClient.Response.KeepBody = true;
await e.GetResponseBody();

await Dispatcher.InvokeAsync(() => { item.Update(); });
await Dispatcher.InvokeAsync(() => { item.Update(e); });
if (item == SelectedSession)
{
await Dispatcher.InvokeAsync(selectedSessionChanged);
Expand Down Expand Up @@ -225,6 +227,8 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var item = new SessionListItem
{
Number = lastSessionNumber,
ClientConnectionId = e.ClientConnectionId,
ServerConnectionId = e.ServerConnectionId,
HttpClient = e.HttpClient,
ClientEndPoint = e.ClientEndPoint,
IsTunnelConnect = isTunnelConnect
Expand All @@ -236,14 +240,16 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
var connectRequest = session.HttpClient.ConnectRequest;
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}

li.ReceivedDataCount += args.Count;

//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_received",
args.Buffer, args.Offset, args.Count);
}
Expand All @@ -254,15 +260,17 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
var connectRequest = session.HttpClient.ConnectRequest;
var tunnelType = connectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}

li.SentDataCount += args.Count;

AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
//if (tunnelType == TunnelType.Http2)
AppendTransferLog( session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
args.Buffer, args.Offset, args.Count);
}
};
Expand All @@ -272,18 +280,22 @@ private SessionListItem createSessionListItem(SessionEventArgsBase e)
te.DecryptedDataReceived += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + "_decrypted_received", args.Buffer, args.Offset,
args.Count);
};

te.DecryptedDataSent += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
//var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
//if (tunnelType == TunnelType.Http2)
AppendTransferLog(session.GetHashCode() + "_decrypted_sent", args.Buffer, args.Offset, args.Count);
};
}

item.Update();
item.Update(e);
return item;
}

Expand Down Expand Up @@ -362,9 +374,15 @@ private void selectedSessionChanged()

//string hexStr = string.Join(" ", data.Select(x => x.ToString("X2")));
var sb = new StringBuilder();
sb.AppendLine("URI: " + request.RequestUri);
sb.Append(request.HeaderText);
sb.Append(request.Encoding.GetString(data));
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
if (truncated)
{
sb.AppendLine();
sb.Append($"Data is truncated after {truncateLimit} bytes");
}

sb.Append((request as ConnectRequest)?.ClientHelloInfo);
TextBoxRequest.Text = sb.ToString();

Expand All @@ -381,7 +399,12 @@ private void selectedSessionChanged()
sb = new StringBuilder();
sb.Append(response.HeaderText);
sb.Append(response.Encoding.GetString(data));
sb.Append(truncated ? Environment.NewLine + $"Data is truncated after {truncateLimit} bytes" : null);
if (truncated)
{
sb.AppendLine();
sb.Append($"Data is truncated after {truncateLimit} bytes");
}

sb.Append((response as ConnectResponse)?.ServerHelloInfo);
if (SelectedSession.Exception != null)
{
Expand Down
19 changes: 18 additions & 1 deletion examples/Titanium.Web.Proxy.Examples.Wpf/SessionListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.ComponentModel;
using System.Net;
using System.Runtime.CompilerServices;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Examples.Wpf.Annotations;
using Titanium.Web.Proxy.Http;

Expand All @@ -18,9 +19,23 @@ public class SessionListItem : INotifyPropertyChanged
private long sentDataCount;
private string statusCode;
private string url;
private Guid clientConnectionId;
private Guid serverConnectionId;

public int Number { get; set; }

public Guid ClientConnectionId
{
get => clientConnectionId;
set => SetField(ref clientConnectionId, value);
}

public Guid ServerConnectionId
{
get => serverConnectionId;
set => SetField(ref serverConnectionId, value);
}

public HttpWebClient HttpClient { get; set; }

public IPEndPoint ClientEndPoint { get; set; }
Expand Down Expand Up @@ -123,13 +138,15 @@ protected virtual void OnPropertyChanged([CallerMemberName] string propertyName
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void Update()
public void Update(SessionEventArgsBase args)
{
var request = HttpClient.Request;
var response = HttpClient.Response;
int statusCode = response?.StatusCode ?? 0;
StatusCode = statusCode == 0 ? "-" : statusCode.ToString();
Protocol = request.RequestUri.Scheme;
ClientConnectionId = args.ClientConnectionId;
ServerConnectionId = args.ServerConnectionId;

if (IsTunnelConnect)
{
Expand Down
1 change: 1 addition & 0 deletions src/Titanium.Web.Proxy.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=Titanium_002EWeb_002EProxy_002EExamples_002EWpf_002EAnnotations/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/CodeInspection/GeneratedCode/GeneratedFileMasks/=docfx_002Ejson/@EntryIndexedValue">docfx.json</s:String>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_EXISTING_EMBEDDED_ARRANGEMENT/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_ACCESSORHOLDER_ATTRIBUTE_ON_SAME_LINE_EX/@EntryValue">NEVER</s:String>
Expand Down
Loading