Question

I'm trying to write a simple TCP network tunnel in C# (with MonoDevelop, not VS). Currently, it works up to the point at which I make a connection. After connecting with netcat localhost <portnum>, I get packets filled with nulls sent at me constantly. My code is:

Tunnel.cs

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

public class Tunnel {
    public TcpListener listener;
    public NetworkStream local, remote;
    private Thread threadControl, threadLocalSide, threadRemoteSide;
    public Tunnel(int localPort, String remoteServer, int remotePort) {
        this.listener = new TcpListener(new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), localPort));
        this.remote = new TcpClient(remoteServer, remotePort).GetStream();
        this.threadControl = new Thread(new ThreadStart(this.thread));
        this.threadControl.Start();
    }
    public void thread() {
        this.listener.Start();
        Console.WriteLine("Awaiting connection...");
        this.local = this.listener.AcceptTcpClient().GetStream();
        Console.WriteLine("Tunnel connected!");
        Console.WriteLine("Starting threads...");
        this.threadLocalSide = new Thread(new ThreadStart(this.localSide));
        this.threadLocalSide.Start();
        this.threadRemoteSide = new Thread(new ThreadStart(this.remoteSide));
        this.threadRemoteSide.Start();
    }
    public void localSide() {
        byte[] buffer = new byte[2048];
        try {
            while(true) {
                while(!this.local.DataAvailable);
                this.local.Read(buffer, 0, buffer.Length);
                this.remote.Write(buffer, 0, buffer.Length);
            }
        } catch {
            this.threadRemoteSide.Abort();
        }
    }
    public void remoteSide() {
        byte[] buffer = new byte[2048];
        try {
            while(true) {
                while(!this.remote.DataAvailable);
                this.remote.Read(buffer, 0, buffer.Length);
                this.local.Write(buffer, 0, buffer.Length);
            }
        } catch {
            this.threadLocalSide.Abort();
        }
    }
}
Was it helpful?

Solution

Stream.Read() method returns number of bytes actually received, but you are always sending the whole buffer.

Try to copy data from one stream to another this way:

static void CopyStream(Stream from, Stream to)
{
    var buffer = new byte[2048];
    while(true)
    {
        int bytesRead = from.Read(buffer, 0, buffer.Length);
        if(bytesRead == 0) break; // 0 means end of stream
        to.Write(buffer, 0, bytesRead);
    }
}

localSide() { CopyStream(local, remote); }
remoteSide() { CopyStream(remote, local); }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top