如何通过Stacksoft.net的袜子5连接到tor?

时间:2012-09-25 10:27:27

标签: c# socks tor

我正在尝试使用带有Stacksoft.net库的socks 5协议来获取页面:

ProxyClientFactory cf = new ProxyClientFactory();
var p = cf.CreateProxyClient(ProxyType.Socks5, "127.0.0.1", 9051, "", "");
var c = p.CreateConnection("www.google.com",80);

当我运行此操作时,我遇到以下异常:

Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.
Inner exception:An established connection was aborted by the software in your host machine

当程序尝试从google.com stream.Read(response, 0, response.Length);读取响应时抛出异常:

    private void SendCommand(byte command, string destinationHost, int destinationPort)
    {
        NetworkStream stream = _tcpClient.GetStream();

        byte addressType = GetDestAddressType(destinationHost);
        byte[] destAddr = GetDestAddressBytes(addressType, destinationHost);
        byte[] destPort = GetDestPortBytes(destinationPort);

        //  The connection request is made up of 6 bytes plus the
        //  length of the variable address byte array
        //
        //  +----+-----+-------+------+----------+----------+
        //  |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
        //  +----+-----+-------+------+----------+----------+
        //  | 1  |  1  | X'00' |  1   | Variable |    2     |
        //  +----+-----+-------+------+----------+----------+
        //
        // * VER protocol version: X'05'
        // * CMD
        //   * CONNECT X'01'
        //   * BIND X'02'
        //   * UDP ASSOCIATE X'03'
        // * RSV RESERVED
        // * ATYP address itemType of following address
        //   * IP V4 address: X'01'
        //   * DOMAINNAME: X'03'
        //   * IP V6 address: X'04'
        // * DST.ADDR desired destination address
        // * DST.PORT desired destination port in network octet order            

        byte[] request = new byte[4 + destAddr.Length + 2];
        request[0] = SOCKS5_VERSION_NUMBER;
        request[1] = command;
        request[2] = SOCKS5_RESERVED;
        request[3] = addressType;
        destAddr.CopyTo(request, 4);
        destPort.CopyTo(request, 4 + destAddr.Length);

        // send connect request.
        stream.Write(request, 0, request.Length);

        //  PROXY SERVER RESPONSE
        //  +----+-----+-------+------+----------+----------+
        //  |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
        //  +----+-----+-------+------+----------+----------+
        //  | 1  |  1  | X'00' |  1   | Variable |    2     |
        //  +----+-----+-------+------+----------+----------+
        //
        // * VER protocol version: X'05'
        // * REP Reply field:
        //   * X'00' succeeded
        //   * X'01' general SOCKS server failure
        //   * X'02' connection not allowed by ruleset
        //   * X'03' Network unreachable
        //   * X'04' Host unreachable
        //   * X'05' Connection refused
        //   * X'06' TTL expired
        //   * X'07' Command not supported
        //   * X'08' Address itemType not supported
        //   * X'09' to X'FF' unassigned
        //* RSV RESERVED
        //* ATYP address itemType of following address

        byte[] response = new byte[255];

        // read proxy server response
        stream.Read(response, 0, response.Length);

我做错了什么?

1 个答案:

答案 0 :(得分:2)

抱歉延迟回复,我已经找到了这个小型的“库”,它基本上暴露了一个单例Tor类和一个socks类;这是一个大项目的一部分,我不想拖延我的答案。我希望我的方法为你提供一些方向。

我只想注意,我在测试时遇到的唯一问题是我似乎没有获得完整的http返回有效负载,这意味着代理类似乎只从Web服务器捕获一部分html代码。我相信这是由于Tor网络所涉及的大延迟。我试图增加缓冲阵列的大小,但没有帮助。如果你想出一个解决方案,我将非常感激

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;

using Starksoft.Net.Proxy;

using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Web;

using System.Threading;

namespace networking
{
    namespace client
    {

        internal class proxy
        {
            public struct conn
            {
                internal TcpClient http;
                internal IProxyClient Proxy;
                public ProxyType proxy_type;

                public string proxy_host;
                public int proxy_port;
                public string target_host;
                public int target_port;
                public string recv_packet;

                public void proxy_config(string target_host, int target_port, string proxy_host, int proxy_port, ProxyType type)
                {
                    this.target_host = target_host; this.target_port = target_port;
                    this.proxy_host = proxy_host; this.proxy_port = proxy_port;
                    this.proxy_type = type;
                }
            }
            public conn proxy_conn;
            internal proxy(string target_host, int target_port, string proxy_host, int proxy_port, ProxyType type)
            {
                Console.WriteLine("Socket allocated.");
                this.proxy_conn = new proxy.conn();
                this.proxy_conn.proxy_config(target_host, target_port, proxy_host, proxy_port, type);
                ProxyClientFactory factory = new ProxyClientFactory();
                this.proxy_conn.Proxy = factory.CreateProxyClient(type, proxy_host, proxy_port);
                this.proxy_conn.Proxy.CreateConnectionAsyncCompleted += new EventHandler<CreateConnectionAsyncCompletedEventArgs>(proxy_connected);

                //this.Proxy.CreateConnectionAsync(obj.target_host, obj.target_port);
            }
            internal void connect()
            {
                this.proxy_conn.Proxy.CreateConnectionAsync(this.proxy_conn.target_host, this.proxy_conn.target_port);
            }
            private void proxy_connected(object sender, CreateConnectionAsyncCompletedEventArgs e)
            {
                if (e.Error != null)
                {
                    Console.WriteLine("Connection Error!");
                    Console.WriteLine(e.Error.Message);
                    return;
                }
                else if (e.Error == null)
                {
                    // get a reference to the open proxy connection
                    Console.WriteLine("Connected to Tor!");
                    this.proxy_conn.http = e.ProxyConnection;
                    Console.WriteLine("Proxy referenced.");
                }
            }
            public void send(string data)
            {
                this.proxy_conn.http.Client.Send(ASCIIEncoding.ASCII.GetBytes(data));
            }
            public string recv()
            {
                byte[] rcvBuffer = new byte[1024]; //1024
                int bytes = this.proxy_conn.http.Client.Receive(rcvBuffer, 1024, SocketFlags.None);
                this.proxy_conn.recv_packet += ASCIIEncoding.ASCII.GetString(rcvBuffer, 0, bytes);
                return this.proxy_conn.recv_packet;
            }

        }

        internal class Tor
        {
            private static Tor instance;

            private Process tor;
            //private conn obj_conn;
            private Tor(){}
            internal static Tor Instance
            {
                get
                {
                    if (instance == null)
                    {
                        instance = new Tor();
                    }
                    return instance;
                }
            }
            internal void tor_start()
            {
                if (this.tor == null)
                {
                    Console.WriteLine("Tor init...");
                    this.tor = new Process();
                    this.tor.StartInfo.FileName = "tor.exe";
                    this.tor.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
                    Console.WriteLine(Directory.GetCurrentDirectory());
                    this.tor.StartInfo.CreateNoWindow = false;
                    this.tor.StartInfo.UseShellExecute = false;
                    this.tor.StartInfo.RedirectStandardOutput = true;
                    this.tor.StartInfo.RedirectStandardInput = true;
                    this.tor.StartInfo.RedirectStandardError = true;
                    this.tor.OutputDataReceived += new DataReceivedEventHandler((sender, args) => { stdout__tor(sender, args); });
                    this.tor.ErrorDataReceived += new DataReceivedEventHandler((sender, args) => { stderr__tor(sender, args); });

                    this.tor.Start();
                    Console.WriteLine("Strapping input...");
                    this.tor.BeginOutputReadLine();
                    this.tor.BeginErrorReadLine();
                }
                else
                {
                    Console.WriteLine("A Tor process already exists.");
                }

            }
            internal void tor_stop()
            {
                this.tor.StandardOutput.Close();
                this.tor.StandardInput.Close();
                this.tor.StandardError.Close();
                this.tor.Kill();
                this.tor.Dispose();
                this.tor = null;
            }
            internal void tor_restart()
            {
                tor_stop();
                tor_start();
            }
            private void stdout__tor(object sender, DataReceivedEventArgs pipe)
            {
                if (pipe.Data.Contains("Bootstrapped 100%: Done."))
                {
                    Console.WriteLine("Tor has been initialized.");
                    //this.obj_conn.Proxy.CreateConnectionAsync(obj_conn.target_host, obj_conn.target_port);
                }
                Console.WriteLine(pipe.Data);
            }
            private void stderr__tor(object sender, DataReceivedEventArgs pipe)
            {
                Console.WriteLine("[ERROR]: " + pipe.Data);
            }
        }


    }


    public class socket
    {
        internal static client.Tor Tor_obj;
        internal static List<client.proxy> proxy_socks;

        public socket()
        {
            if (Tor_obj == null || proxy_socks == null)
            {
                if (Tor_obj == null)
                {
                    Tor_obj = client.Tor.Instance;
                    Tor_obj.tor_start();
                }
                if (proxy_socks == null)
                {
                    proxy_socks = new List<client.proxy>();
                }
            }
        }
        public int add(string type, string host, int port)
        {
            int index = -1;
            if (type == "proxy")
            {
                proxy_socks.Add(new client.proxy(host, port, "127.0.0.1", 9050, ProxyType.Socks4a));
                index = proxy_socks.Count() - 1;
                proxy_socks[index].connect();
                return index;
            }
            return index;

            }
    }
}

namespace myprog
{
    class Program
    {
        static void Main(string[] args)
        {

            networking.socket connections = new networking.socket();
            Thread.Sleep(20000);
            int conn_index = connections.add("proxy", "checkmyip.com", 80);
            Thread.Sleep(10000);
            networking.socket.proxy_socks[conn_index].send("GET / HTTP/1.1\r\nHost: checkmyip.com\r\n\r\n");
            Console.WriteLine(WebUtility.HtmlDecode(networking.socket.proxy_socks[conn_index].recv()));
            Thread.Sleep(50000);
        }
    }
}

我调用thread.sleep()以确保Tor进程已完全连接,然后建立与Tor的代理连接,并在此时发出请求。