Wednesday, August 13, 2014

A simple TCP proxy forwarder in .NET

Here's a way of doing a super simple TCP proxy in C#.

Warning: this should only be used for testing purposes, as it will leak threads.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class Program
{
    static void ProxyStream(string stream1name, NetworkStream stream1, string stream2name, NetworkStream stream2)
    {
        var buffer = new byte[65536];

        try
        {
            while (true)
            {
                var len = stream1.Read(buffer, 0, 65536);
                stream2.Write(buffer, 0, len);
            }
        }
        catch (Exception)
        {
            Console.WriteLine("Stream from " + stream1name + " to " + stream2name + " closed");
        }
    }

    static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            Console.WriteLine("Usage: program.exe localport remoteServerHost remoteServerPort");
            Console.WriteLine("Example: program.exe 13389 10.1.2.3 3389");
            return;
        }

        var localPort = int.Parse(args[0]);
        var remoteServerHost = args[1];
        var remoteServerPort = int.Parse(args[2]);

        var l = new TcpListener(IPAddress.Any, localPort);
        l.Start();
        while (true)
        {
            var client1 = l.AcceptTcpClient();
            var remoteAddress = (client1.Client.RemoteEndPoint as IPEndPoint).Address.ToString();
            Console.WriteLine("Accepted session from " + remoteAddress);
            var client2 = new TcpClient(remoteServerHost, remoteServerPort);
            Console.WriteLine("Created connection to " + remoteServerHost + ":" + remoteServerPort);

            new Thread(() => { ProxyStream(remoteAddress, client1.GetStream(), remoteServerHost, client2.GetStream()); }).Start();
            new Thread(() => { ProxyStream(remoteServerHost, client2.GetStream(), remoteAddress, client1.GetStream()); }).Start();
        }
    }
}

Or, if you need this from PowerShell, I would suggest wrapping it (as threads in PowerShell are painful):
$source = '
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class Program
{
    static void ProxyStream(string stream1name, NetworkStream stream1, string stream2name, NetworkStream stream2)
    {
        var buffer = new byte[65536];

        try
        {
            while (true)
            {
                var len = stream1.Read(buffer, 0, 65536);
                stream2.Write(buffer, 0, len);
            }
        }
        catch (Exception)
        {
            Console.WriteLine("Stream from " + stream1name + " to " + stream2name + " closed");
        }
    }

    static void Main(string[] args)
    {
        if (args.Length != 3)
        {
            Console.WriteLine("Usage: program.exe localport remoteServerHost remoteServerPort");
            Console.WriteLine("Example: program.exe 13389 10.1.2.3 3389");
            return;
        }

        var localPort = int.Parse(args[0]);
        var remoteServerHost = args[1];
        var remoteServerPort = int.Parse(args[2]);

        var l = new TcpListener(IPAddress.Any, localPort);
        l.Start();
        while (true)
        {
            var client1 = l.AcceptTcpClient();
            var remoteAddress = (client1.Client.RemoteEndPoint as IPEndPoint).Address.ToString();
            Console.WriteLine("Accepted session from " + remoteAddress);
            var client2 = new TcpClient(remoteServerHost, remoteServerPort);
            Console.WriteLine("Created connection to " + remoteServerHost + ":" + remoteServerPort);

            new Thread(() => { ProxyStream(remoteAddress, client1.GetStream(), remoteServerHost, client2.GetStream()); }).Start();
            new Thread(() => { ProxyStream(remoteServerHost, client2.GetStream(), remoteAddress, client1.GetStream()); }).Start();
        }
    }
}

'
Add-Type `
    -TypeDefinition $source `
    -Language CSharp `
    -OutputAssembly 'c:\windows\temp\tcpproxy.exe' `
    -OutputType 'ConsoleApplication'

Tuesday, August 05, 2014

Command prompt running as NT AUTHORITY\Network Service

Here's a convenient way to get a command prompt running as Network Service. This is useful for troubleshooting authentication issues for services running as Network Service.

Get Psexec from http://live.sysinternals.com/psexec.exe.

Run:

psexec -u "NT AUTHORITY\Network Service" -i cmd

Or, if you prefer PowerShell:

psexec -u "NT AUTHORITY\Network Service" -i powershell

Or, if you prefer PowerShell, and a bigger than standard window with some distinguishable color:

psexec -u "NT AUTHORITY\Network Service" -i powershell -noexit "cd c:\ ; mode con:cols=170 lines=60 ; (Get-Host).UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size(170,3000) ; (Get-Host).UI.RawUI.BackgroundColor='DarkCyan' ; clear"



WCF net.tcp test client in PowerShell

Here's a convenient way of creating a WCF net.tcp client for a quick test. It uses PowerShell to compile C# code to an exe on the fly. Note that the interface can be partial (only containing the method you want to call).
$source = '
    using System;
    using System.ServiceModel;

    [ServiceContract(Namespace = "http://example.com/SomeSchema")]
    public interface ISomeService
    {
        [OperationContract]
        bool SomeMethod();
    }

    public class Wcftest
    {
        public static void Main(string[] args)
        {
            var binding = new NetTcpBinding();
            var address = new EndpointAddress("net.tcp://" + args[0] + ":808/SomeService");

            var factory = new ChannelFactory<ISomeService>(binding, address);
            var proxy = factory.CreateChannel();

            Console.WriteLine(proxy.SomeMethod());
        }
    }
'
Add-Type `
    -ReferencedAssemblies 'System.ServiceModel.dll' `
    -TypeDefinition $source `
    -Language CSharp `
    -OutputAssembly 'c:\windows\temp\wcftest.exe' `
    -OutputType 'ConsoleApplication'

c:\windows\temp\wcftest.exe "example.com"
del c:\windows\temp\wcftest.*