C# TcpClient.Connect via a proxy

后端 未结 2 1560
无人共我
无人共我 2020-12-29 14:29

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,

相关标签:
2条回答
  • 2020-12-29 14:52

    I use starksoft-aspen. It's free and open-source.

    In the example below the TcpClient initialized within "CreateConnection()" method, but you can also initialize the client by yourself, as well as do it all async.

    using Starksoft.Aspen.Proxy;
    
        Socks5ProxyClient proxyClient = new Socks5ProxyClient(
            socks5Proxy.Host, socks5Proxy.Port, 
            socks5Proxy.Username, socks5Proxy.Password);
    
        TcpClient client = proxyClient.CreateConnection(destination.Host, 
            destination.Port);
        NetworkStream stream = client.GetStream();
    
    0 讨论(0)
  • 2020-12-29 14:57

    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;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题