Skip to content

Commit

Permalink
Upgraded solution, updated fwk, refactored Resolve, moved ProxyDummyE…
Browse files Browse the repository at this point in the history
…cho out of the Logic file and implemented a (shy) CONNECT.
  • Loading branch information
ignacio committed Oct 22, 2014
1 parent 61cbe8c commit 93c66ec
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 94 deletions.
4 changes: 2 additions & 2 deletions Example/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public static void Main()

var Server = new TcpServer(port, bUseIPv6);

//Server.Start(TransparentProxy.CreateProxy);
Server.Start(TransparentProxy.CreateProxy);
//Server.Start(RedirectingProxy.CreateProxy);
Server.Start(RewritingProxy.CreateProxy);
//Server.Start(RewritingProxy.CreateProxy);

Server.InitListenFinished.WaitOne();
if (Server.InitListenException != null)
Expand Down
49 changes: 44 additions & 5 deletions Example/TrotiNet.Example.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
Expand All @@ -10,8 +10,29 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TrotiNetConsole</RootNamespace>
<AssemblyName>TrotiNetConsole</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -21,6 +42,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -29,11 +51,12 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\Log4Net\log4net.dll</HintPath>
<HintPath>..\packages\log4net.2.0.3\lib\net40-full\log4net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.XML" />
Expand All @@ -52,6 +75,22 @@
<Name>TrotiNet</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand All @@ -60,4 +99,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
3 changes: 3 additions & 0 deletions Example/app.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
4 changes: 4 additions & 0 deletions Example/packages.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.3" targetFramework="net45" />
</packages>
63 changes: 63 additions & 0 deletions Lib/ProxyDummyEcho.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace TrotiNet
{

/// <summary>
/// Dummy proxy that simply echoes back what it gets from the browser
/// </summary>
/// Used for TCP testing.
public class ProxyDummyEcho : AbstractProxyLogic
{
bool bPrintEchoPrefix;

/// <summary>
/// Instantiate a dummy proxy that echoes what it reads on the
/// socket back to it
/// </summary>
/// <param name="socketBP">Client socket</param>
/// <param name="PrintEchoPrefix">If true, the proxy will add an
/// "Echo" prefix for each message</param>
public ProxyDummyEcho(HttpSocket socketBP, bool PrintEchoPrefix) :
base(socketBP)
{
bPrintEchoPrefix = PrintEchoPrefix;
}

/// <summary>
/// Static constructor with <c>PrintEchoPrefix = true</c>
/// </summary>
static public AbstractProxyLogic CreateEchoProxy(HttpSocket socketBP)
{
return new ProxyDummyEcho(socketBP, true);
}

/// <summary>
/// Static constructor with <c>PrintEchoPrefix = false</c>
/// </summary>
static public AbstractProxyLogic CreateMirrorProxy(HttpSocket socketBP)
{
return new ProxyDummyEcho(socketBP, false);
}

/// <summary>
/// Dummy logic loop, for test purposes
/// </summary>
override public bool LogicLoop()
{
uint r = SocketBP.ReadBinary();
if (r == 0)
// Connection closed
return false;

string s = System.Text.ASCIIEncoding.ASCII.GetString(
SocketBP.Buffer, 0, (int)r);
if (bPrintEchoPrefix)
SocketBP.WriteBinary(System.Text.ASCIIEncoding.
ASCII.GetBytes("Echo: "));
SocketBP.WriteBinary(SocketBP.Buffer, r);

if (s.StartsWith("x"))
return false;
return true;
}
}
}
121 changes: 44 additions & 77 deletions Lib/ProxyLogic.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
using System.Text;
using log4net;

namespace TrotiNet
namespace TrotiNet
{
using System;
using System.Linq;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
using System.Text;
using log4net;
using System.Threading;

/// <summary>
/// Abstract class for all HTTP proxy logic implementations
/// </summary>
Expand Down Expand Up @@ -105,7 +107,7 @@ protected void Connect(string hostname, int port)
SocketPS = null;
}

IPAddress[] ips = Dns.GetHostAddresses(hostname);
IPAddress[] ips = Resolve(hostname);
Socket socket = null;
Exception e = null;
foreach (var ip in ips)
Expand Down Expand Up @@ -145,6 +147,12 @@ protected void Connect(string hostname, int port)
log.Debug("SocketPS connected to " + hostname + ":" + port);
}

private static IPAddress[] Resolve(string hostname)
{
IPAddress[] ips = Dns.GetHostAddresses(hostname);
return ips;
}

/// <summary>
/// Extract the host and port to use from either the HTTP request
/// line, or the HTTP headers; update the request line to remove
Expand Down Expand Up @@ -542,21 +550,18 @@ protected virtual void ReadRequest()

RequestHeaders = new HttpHeaders(SocketBP);

if (RequestLine.Method.Equals("CONNECT"))
{
log.Debug("Method CONNECT not implemented");
SocketBP.Send501();
AbortRequest();
return;
}

log.Info("Got request " + RequestLine.RequestLine);

// We call OnReceiveRequest now because Connect() will
// modify the request URI.
State.NextStep = SendRequest;
OnReceiveRequest();

if (RequestLine.Method.Equals("CONNECT"))
{
HandleConnect();
}

// Now we parse the request to:
// 1) find out where we should connect
// 2) find out whether there is a message body in the request
Expand Down Expand Up @@ -630,6 +635,27 @@ protected virtual void ReadRequest()

}

/// <summary>
/// A specific case for the CONNECT command,
/// connect both ends blindly (will work for HTTPS, SSH and others)
/// </summary>
virtual protected void HandleConnect()
{
int NewDestinationPort;
string NewDestinationHost = ParseDestinationHostAndPort(
RequestLine, RequestHeaders, out NewDestinationPort);
Connect(NewDestinationHost, NewDestinationPort);
this.State.NextStep = null;
this.SocketBP.WriteAsciiLine(string.Format("HTTP/{0} 200 Connection established", RequestLine.ProtocolVersion));
this.SocketBP.WriteAsciiLine(string.Empty);
var socketsToConnect = new[] { this.SocketBP, this.SocketPS };

socketsToConnect
.Zip(socketsToConnect.Reverse(), (from, to) => new { from,to })
.AsParallel()
.ForAll(team => team.from.TunnelDataTo(team.to));
}

/// <summary>
/// Pipeline step: tunnel the request from the client to the remove
/// server, and schedule the next step to be <c>ReadResponse</c>
Expand Down Expand Up @@ -1072,63 +1098,4 @@ public byte[] EncodeStringResponse(string s, Encoding encoding)
}
}

/// <summary>
/// Dummy proxy that simply echoes back what it gets from the browser
/// </summary>
/// Used for TCP testing.
public class ProxyDummyEcho : AbstractProxyLogic
{
bool bPrintEchoPrefix;

/// <summary>
/// Instantiate a dummy proxy that echoes what it reads on the
/// socket back to it
/// </summary>
/// <param name="socketBP">Client socket</param>
/// <param name="PrintEchoPrefix">If true, the proxy will add an
/// "Echo" prefix for each message</param>
public ProxyDummyEcho(HttpSocket socketBP, bool PrintEchoPrefix):
base(socketBP)
{
bPrintEchoPrefix = PrintEchoPrefix;
}

/// <summary>
/// Static constructor with <c>PrintEchoPrefix = true</c>
/// </summary>
static public AbstractProxyLogic CreateEchoProxy(HttpSocket socketBP)
{
return new ProxyDummyEcho(socketBP, true);
}

/// <summary>
/// Static constructor with <c>PrintEchoPrefix = false</c>
/// </summary>
static public AbstractProxyLogic CreateMirrorProxy(HttpSocket socketBP)
{
return new ProxyDummyEcho(socketBP, false);
}

/// <summary>
/// Dummy logic loop, for test purposes
/// </summary>
override public bool LogicLoop()
{
uint r = SocketBP.ReadBinary();
if (r == 0)
// Connection closed
return false;

string s = System.Text.ASCIIEncoding.ASCII.GetString(
SocketBP.Buffer, 0, (int)r);
if (bPrintEchoPrefix)
SocketBP.WriteBinary(System.Text.ASCIIEncoding.
ASCII.GetBytes("Echo: "));
SocketBP.WriteBinary(SocketBP.Buffer, r);

if (s.StartsWith("x"))
return false;
return true;
}
}
}
Loading

0 comments on commit 93c66ec

Please sign in to comment.