Search code examples
c#tcpmonotunnel

C# TCP Tunnel sends lots of nulls


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();
        }
    }
}

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); }