• C# 连接 Socks5 代理


    public class Socks5ProxyHelp
    {
    private Socks5ProxyHelp() { }

        public static string[] errorMsgs = {
         "Operation completed successfully.",//操作成功完成
         "General SOCKS server failure.",//常规服务器失败
         "Connection not allowed by ruleset.",//连接不被允许
         "Network unreachable.",//网络不能到达
         "Host unreachable.",//主机不能到达
         "Connection refused.",//连接被拒绝
         "TTL expired.",//TTL期满
         "Command not supported.",//不支持的命令
         "Address type not supported.",//不被支持的地址类型
         "Unknown error."//未名的错误
        };
    
       
    
        // <summary>
        // 连接到socks5代理
        // </summary>
        // <param name="proxyAdress">代理服务期地址</param>
        // <param name="proxyPort">代理服务器端口</param>
        // <param name="destAddress">目标地址  Destination: 目的地,UDP命令时是本机的地址</param>
        // <param name="destPort">目标端口,UDP命令时是本机的UDP端口</param>
        // <param name="userName">用户名</param>
        // <param name="password">密码</param>
        // <returns>用于TCP连接的SOCKET</returns>
        public static void ConnectToSocks5Proxy(string proxyAdress, int proxyPort, string userName, string password, out string ErrorMsg)
        {
            ErrorMsg = "";
            IPAddress proxyIP = null;
            byte[] request = new byte[257]; //请求
            byte[] response = new byte[257];//应答
            ushort nIndex;
            try
            {
                proxyIP = IPAddress.Parse(proxyAdress);
            }
            catch (FormatException)
            {
                proxyIP = Dns.GetHostEntry(proxyAdress).AddressList[0];
            }
            // 解析 destAddress (要求是类似 "212.116.65.112" 的string),否则是类似 "www.microsoft.com"的地址
    
            IPEndPoint proxyEndPoint = new IPEndPoint(proxyIP, proxyPort);
            Socket s = null;
            try
            {
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(proxyEndPoint);//客户端连到服务器后,然后就发送请求来协商版本和认证方法: 
    
                nIndex = 0;
                request[nIndex++] = 0x05; // V 5.              [版本]
                request[nIndex++] = 0x02; // 2种验证方式    [方法的数目]
                request[nIndex++] = 0x00; // X'00'  不需要认证 [方法1]
                request[nIndex++] = 0x02; // X'02'  用户名/密码[方法2]
                s.Send(request, nIndex, SocketFlags.None);
                // 收到2个字节的应答,填充到response中,如果不是两个字节,则抛出异常
                int nGot = s.Receive(response, 2, SocketFlags.None);
                if (nGot != 2) throw new Exception("从 proxy server 返回错误的应答.");
    
                // 当前定义的方法有:
                // X'00'  不需要认证
                // X'01'     GSSAPI
                // X'02'     用户名/密码
                // X'03' -- X'7F'   由IANA分配
                // X'80' -- X'FE'  为私人方法所保留的
                // X'FF'      没有可以接受的方法
                switch (response[1])
                {
                    case 0xFF:
                        没有可以接受的方法(s);
                        break;
                    case 0x02:
                        用户名密码验证(s, userName, password);
                        break;
                }
            }
            catch (Exception ex)
            {
                ErrorMsg = ex.Message;
            }
            finally
            {
                if (s != null)
                {
                    s.Close();
                    s.Dispose();
                    s = null;
                }
            }
            //SendUDP.UDP命令(s);
        }
        static void 没有可以接受的方法(Socket s)
        {
            // 客户端没有一中验证方式能被服务器接受,则关闭该socket.
            s.Close();
            throw new Exception("客户端没有一中验证方式能被代理服务器接受.");
        }
        static bool 用户名密码验证(Socket s, string userName, string password)
        {
            byte[] request = new byte[257]; //请求
            byte[] response = new byte[257];//应答
            ushort nIndex;
            byte[] rawBytes;
            nIndex = 0;
    
            request[nIndex++] = 0x05; // Version 5.   不清楚为什么报文的首字节是0x01(按照惯例应当是0x05)
    
            // 加入 user name
            request[nIndex++] = (byte)userName.Length;  //一个字节,放UserName的长度
            rawBytes = Encoding.Default.GetBytes(userName);
            rawBytes.CopyTo(request, nIndex);          //将userName 加入
            nIndex += (ushort)rawBytes.Length;
    
            // 加入 password
            request[nIndex++] = (byte)password.Length;  //一个字节,放PassWord的长度
            rawBytes = Encoding.Default.GetBytes(password);
            rawBytes.CopyTo(request, nIndex);
            nIndex += (ushort)rawBytes.Length;
    
            // 发送 Username/Password 请求
            s.Send(request, nIndex, SocketFlags.None);
            int nGot = s.Receive(response, 2, SocketFlags.None);
            if (nGot != 2)
            {
                throw new Exception("从 proxy server 返回错误的应答.");
            }
            if (response[1] != 0x00) //返回如下的报文字节序列映像为:0x01 | 验证结果标志-->0x00 验证通过,其余均表示有故障
            {
                throw new Exception("账号或密码错误!");
            }
            Console.WriteLine("okpass");
            return true;
        }
    }
  • 相关阅读:
    [转]zxing二维码的生成和解码 j2se
    [转]Android的网络与通信
    (转)Firefox:浏览器内置数据库之路
    dom Framework oop模块
    我的框架 别名机制
    获取屏幕的PDI值
    mass Framework lang模块
    王云飞 《绿色生活》(附译文)
    dom Framework query模块
    dom Framework核心模块发布!(更新)
  • 原文地址:https://www.cnblogs.com/mayblog/p/11007595.html
Copyright © 2020-2023  润新知