Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# TcpClient.Connect via a proxy

I've searched high and low trying to figure this out, but everything I've seen so far, people are just telling me to use other methods.

With that out of the way, my issue is that I'm trying to connect to a server through a TcpClient using a socks 5 proxy

My current setup is:

        Client = new TcpClient();
        Client.Connect(EndPoint);
        NetworkStream = Client.GetStream();
        Stream = new new BufferedStream(NetworkStream);
        Stream.Write...//Write Packet information etc

I'm not sure if I've missed any information out so if I have I'll happily update this.

like image 252
André Avatar asked Aug 17 '13 13:08

André


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C full form?

Full form of C is “COMPILE”.

What is C language basics?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

I don't really think .Net comes equipped with Socks5 support, or proxied TCP.

There are a couple of third-party implementations (google knows more), of course, but it's also pretty easy to implement (part of) RFC 1928 yourself.

Here is an example Socks5 client I just hacked together. You will really want to clean it up :p. Just does the auth negotiation, connection setup and finally a simple http request.

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace tcpsocks5
{
  static class Program
  {
    static void ReadAll(this NetworkStream stream, byte[] buffer, int offset, int size)
    {
      while (size != 0) {
        var read = stream.Read(buffer, offset, size);
        if (read < 0) {
          throw new IOException("Premature end");
        }
        size -= read;
        offset += read;
      }
    }
    static void Main(string[] args)
    {
      using (var client = new TcpClient()) {
        client.Connect(ip, port); // Provide IP, Port yourself
        using (var stream = client.GetStream()) {
          // Auth
          var buf = new byte[300];
          buf[0] = 0x05; // Version
          buf[1] = 0x01; // NMETHODS
          buf[2] = 0x00; // No auth-method
          stream.Write(buf, 0, 3);

          stream.ReadAll(buf, 0, 2);
          if (buf[0] != 0x05) {
            throw new IOException("Invalid Socks Version");
          }
          if (buf[1] == 0xff) {
            throw new IOException("Socks Server does not support no-auth");
          }
          if (buf[1] != 0x00) {
            throw new Exception("Socks Server did choose bogus auth");
          }

          // Request
          buf[0] = 0x05; // Version
          buf[1] = 0x01; // Connect (TCP)
          buf[2] = 0x00; // Reserved
          buf[3] = 0x03; // Dest.Addr: Domain name
          var domain = Encoding.ASCII.GetBytes("google.com");
          buf[4] = (byte)domain.Length; // Domain name length (octet)
          Array.Copy(domain, 0, buf, 5, domain.Length);
          var port = BitConverter.GetBytes(
            IPAddress.HostToNetworkOrder((short)80));
          buf[5 + domain.Length] = port[0];
          buf[6 + domain.Length] = port[1];
          stream.Write(buf, 0, domain.Length + 7);

          // Reply
          stream.ReadAll(buf, 0, 4);
          if (buf[0] != 0x05) {
            throw new IOException("Invalid Socks Version");
          }
          if (buf[1] != 0x00) {
            throw new IOException(string.Format("Socks Error {0:X}", buf[1]));
          }
          var rdest = string.Empty;
          switch (buf[3]) {
            case 0x01: // IPv4
              stream.ReadAll(buf, 0, 4);
              var v4 = BitConverter.ToUInt32(buf, 0);
              rdest = new IPAddress(v4).ToString();
              break;
            case 0x03: // Domain name
              stream.ReadAll(buf, 0, 1);
              if (buf[0] == 0xff) {
                throw new IOException("Invalid Domain Name");
              }
              stream.ReadAll(buf, 1, buf[0]);
              rdest = Encoding.ASCII.GetString(buf, 1, buf[0]);
              break;
            case 0x04: // IPv6
              var octets = new byte[16];
              stream.ReadAll(octets, 0, 16);
              rdest = new IPAddress(octets).ToString();
              break;
            default:
              throw new IOException("Invalid Address type");
          }
          stream.ReadAll(buf, 0, 2);
          var rport = (ushort)IPAddress.NetworkToHostOrder((short)BitConverter.ToUInt16(buf, 0));
          Console.WriteLine("Connected via {0}:{1}", rdest, rport);

          // Make an HTTP request, aka. "do stuff ..."
          using (var writer = new StreamWriter(stream)) {
            writer.Write("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n");
            writer.Flush();
            using (var reader = new StreamReader(stream)) {
              while (true) {
                var line = reader.ReadLine();
                if (string.IsNullOrEmpty(line)) {
                  break;
                }
              }
            }
          }
        }
      }
    }
  }
}
like image 82
nmaier Avatar answered Sep 19 '22 16:09

nmaier