zoukankan      html  css  js  c++  java
  • socket穿透代理代码(C++版)

    写代码经常会遇到socket要通过代理连接服务器的情况,代理类型通畅有三种:HTTP、SOCK4和SOCK5,通过学习和网上参考相关代码,写了个代理类来实现该功能,贴出来与大家共享


    才贴出来两天,刚在百度一搜竟然发现已被一字不改的转载到好几个网站去了,连转载的字样都没有,不反对转载分享,可能否注明出处?


    头文件

    1. #pragma once  
    2.   
    3. #include <WinSock2.h>  
    4. #include <string>  
    5. #include <vector>  
    6.   
    7. using namespace std;  
    8.   
    9. enum ProxyStatus  
    10. {  
    11.     SUCCESS,  
    12.     CONNECT_PROXY_FAIL,  
    13.     NOT_CONNECT_PROXY,  
    14.     CONNECT_SERVER_FAIL  
    15. };  
    16.   
    17. class CProxy  
    18. {  
    19. public:  
    20.     CProxy(long type, string ip, u_short port, string username, string password)  
    21.         :m_proxyType(type), m_proxyIp(ip), m_proxyPort(port), m_proxyUserName(username), m_proxyUserPwd(password)  
    22.     {}  
    23.   
    24.     ~CProxy(void){};  
    25.   
    26.     ProxyStatus ConnectProxyServer(SOCKET socket);  
    27.     ProxyStatus ConnectServer(SOCKET socket, string ip, u_short port);  
    28.   
    29. private:  
    30.     ProxyStatus ConnectByHttp(SOCKET socket, string ip, u_short port);  
    31.     ProxyStatus ConnectBySock4(SOCKET socket, string ip, u_short port);  
    32.     ProxyStatus ConnectBySock5(SOCKET socket, string ip, u_short port);  
    33.   
    34.     bool Send(SOCKET socket, const char* buf, int len);  
    35.     int Receive(SOCKET socket, char* buf, int bufLen);  
    36.   
    37. private:  
    38.     long m_proxyType;  
    39.     string m_proxyIp;  
    40.     u_short m_proxyPort;  
    41.     string m_proxyUserName;  
    42.     string m_proxyUserPwd;  
    43.   
    44.     bool m_blnProxyServerOk;  
    45. };  
    46.   
    47. struct TSock4req1   
    48. {   
    49.     char VN;   
    50.     char CD;   
    51.     unsigned short Port;   
    52.     unsigned long IPAddr;   
    53.     char other;   
    54. };   
    55.   
    56. struct TSock4ans1   
    57. {   
    58.     char VN;   
    59.     char CD;   
    60. };  
    61.   
    62. struct TSock5req1   
    63. {   
    64.     char Ver;   
    65.     char nMethods;   
    66.     char Methods;   
    67. };   
    68.   
    69. struct TSock5ans1   
    70. {   
    71.     char Ver;   
    72.     char Method;   
    73. };   
    74.   
    75. struct TSock5req2   
    76. {   
    77.     char Ver;   
    78.     char Cmd;   
    79.     char Rsv;   
    80.     char Atyp;   
    81.     char other;   
    82. };   
    83.   
    84. struct TSock5ans2   
    85. {   
    86.     char Ver;   
    87.     char Rep;   
    88.     char Rsv;   
    89.     char Atyp;   
    90.     char other;   
    91. };   
    92.   
    93. struct TAuthreq   
    94. {   
    95.     char Ver;   
    96.     char Ulen;   
    97.     char Name;   
    98.     char PLen;   
    99.     char Pass;   
    100. };   
    101.   
    102. struct TAuthans   
    103. {   
    104.     char Ver;   
    105.     char Status;   
    106. };   

    实现文件

    1. #include "StdAfx.h"  
    2. #include "Proxy.h"  
    3. #include "Base64.h"  
    4. #include "log.h"  
    5.   
    6. #include <time.h>  
    7.   
    8.   
    9. ProxyStatus CProxy::ConnectProxyServer(SOCKET socket)  
    10. {  
    11.     int ret;  
    12.     struct timeval timeout ;  
    13.     fd_set r;  
    14.     string ip;  
    15.     u_short port;  
    16.   
    17.     ip = m_proxyIp;  
    18.     port = m_proxyPort;  
    19.   
    20.     sockaddr_in servAddr;  
    21.     servAddr.sin_family = AF_INET;  
    22.     servAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());  
    23.     servAddr.sin_port = htons(port);  
    24.   
    25.     //设置非阻塞方式连接  
    26.     unsigned long ul = 1;  
    27.     ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);  
    28.     if(ret == SOCKET_ERROR)   
    29.     {  
    30.         return CONNECT_PROXY_FAIL;  
    31.     }  
    32.   
    33.     connect(socket, (sockaddr*)&servAddr, sizeof(sockaddr));  
    34.   
    35.     FD_ZERO(&r);  
    36.     FD_SET(socket, &r);  
    37.     timeout.tv_sec = 5;   
    38.     timeout.tv_usec =0;  
    39.     ret = select(0, 0, &r, 0, &timeout);  
    40.   
    41.     if (ret <= 0)  
    42.     {  
    43.         m_blnProxyServerOk = false;  
    44.         return CONNECT_PROXY_FAIL;  
    45.     }  
    46.     else  
    47.     {  
    48.         m_blnProxyServerOk = true;  
    49.         return SUCCESS;  
    50.     }  
    51. }  
    52.   
    53. ProxyStatus CProxy::ConnectServer(SOCKET socket, string ip, u_short port)  
    54. {  
    55.     int ret;  
    56.     int nTimeout;  
    57.   
    58.     if (!m_blnProxyServerOk)  
    59.     {  
    60.         return NOT_CONNECT_PROXY;  
    61.     }  
    62.   
    63.     nTimeout = 5000;  
    64.     setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int));    //设置接收超时  
    65.   
    66.     unsigned long ul = 0;  
    67.     ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);    //设置阻塞方式连接  
    68.   
    69.     switch(m_proxyType)  
    70.     {  
    71.     case 0: //HTTP  
    72.         return ConnectByHttp(socket, ip, port);  
    73.         break;  
    74.     case 1: //SOCK4  
    75.         return ConnectBySock4(socket, ip, port);  
    76.         break;  
    77.     case 2: //SOCK5  
    78.         return ConnectBySock5(socket, ip, port);  
    79.         break;  
    80.     default:  
    81.         break;  
    82.     }  
    83.   
    84.     return CONNECT_SERVER_FAIL;  
    85. }  
    86.   
    87. ProxyStatus CProxy::ConnectByHttp(SOCKET socket, string ip, u_short port)  
    88. {  
    89.     char buf[512];  
    90.   
    91.     if (m_proxyUserName != "")  
    92.     {  
    93.         string str;  
    94.         string strBase64;  
    95.         str = m_proxyUserName + ":" + m_proxyUserPwd;  
    96.         strBase64 = CBase64::Encode((unsigned char*)str.c_str(), str.length());  
    97.         sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1 Host: %s:%d Authorization: Basic %s Proxy-Authorization: Basic %s ",   
    98.             ip.c_str(), port, ip.c_str(), port, strBase64.c_str(), strBase64.c_str());  
    99.     }  
    100.     else  
    101.     {  
    102.         //sprintf_s(buf, 512, "CONNECT %s:%d HTTP/1.1 Host: %s:%d ", ip.c_str(), port, ip.c_str(), port);  
    103.         sprintf_s(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.1 User-Agent: MyApp/0.1 ", ip.c_str(), port);  
    104.     }  
    105.   
    106.     Send(socket, buf, strlen(buf));  
    107.     Receive(socket, buf, sizeof(buf));  
    108.   
    109.     if (strstr(buf, "HTTP/1.0 200 Connection established") != NULL)  
    110.     {  
    111.         return SUCCESS;  
    112.     }  
    113.     else  
    114.     {  
    115.         return CONNECT_SERVER_FAIL;  
    116.     }  
    117.   
    118. }  
    119.   
    120. ProxyStatus CProxy::ConnectBySock4(SOCKET socket, string ip, u_short port)  
    121. {  
    122.     char buf[512];  
    123.   
    124.     memset(buf, 0, sizeof(buf));   
    125.     struct TSock4req1 *proxyreq;  
    126.     proxyreq = (struct TSock4req1*)buf;   
    127.     proxyreq->VN = 4;   
    128.     proxyreq->CD = 1;   
    129.     proxyreq->Port = ntohs(port);   
    130.     proxyreq->IPAddr = inet_addr(ip.c_str());   
    131.   
    132.     Send(socket, buf, 9);  
    133.   
    134.     struct TSock4ans1 *proxyans;   
    135.     proxyans = (struct TSock4ans1*)buf;   
    136.     memset(buf, 0, sizeof(buf));   
    137.   
    138.     Receive(socket, buf, sizeof(buf));  
    139.     if(proxyans->VN == 0 && proxyans->CD == 90)   
    140.     {   
    141.         return SUCCESS;   
    142.     }   
    143.     else  
    144.     {  
    145.         return CONNECT_SERVER_FAIL;  
    146.     }  
    147. }  
    148.   
    149. ProxyStatus CProxy::ConnectBySock5(SOCKET socket, string ip, u_short port)  
    150. {  
    151.     char buf[512];  
    152.   
    153.     struct TSock5req1 *proxyreq1;   
    154.     proxyreq1 = (struct TSock5req1 *)buf;   
    155.     proxyreq1->Ver = 5;   
    156.     proxyreq1->nMethods = 1;   
    157.     proxyreq1->Methods = m_proxyUserName != "" ? 2 : 0;  
    158.   
    159.     Send(socket, buf, 3);   
    160.       
    161.     struct TSock5ans1 *proxyans1;   
    162.     proxyans1 = (struct TSock5ans1 *)buf;   
    163.   
    164.     memset(buf, 0, sizeof(buf));  
    165.     Receive(socket, buf, sizeof(buf));  
    166.     if(proxyans1->Ver != 5 || (proxyans1->Method != 0 && proxyans1->Method != 2))   
    167.     {   
    168.         return CONNECT_SERVER_FAIL;   
    169.     }  
    170.   
    171.     if(proxyans1->Method == 2)   
    172.     {   
    173.         int nUserLen = m_proxyUserName.length();  
    174.         int nPassLen = m_proxyUserPwd.length();  
    175.         //struct TAuthreq *authreq;   
    176.         //authreq = (struct TAuthreq *)buf;   
    177.         //authreq->Ver = 1;   
    178.         //authreq->Ulen = nUserLen;   
    179.         //strcpy(authreq->Name, m_proxyUserName.c_str());   
    180.         //authreq->PLen = nPassLen;   
    181.         //strcpy(authreq->Pass, m_proxyUserPwd.c_str());   
    182.   
    183.         buf[0] = 1;  
    184.         buf[1] = nUserLen;  
    185.         memcpy(buf + 2, m_proxyUserName.c_str(), nUserLen);  
    186.         buf[2 + nUserLen] = nPassLen;  
    187.         memcpy(buf + 3 + nUserLen, m_proxyUserPwd.c_str(), nPassLen);  
    188.   
    189.         Send(socket, buf, 3 + nUserLen + nPassLen);  
    190.   
    191.         struct TAuthans *authans;   
    192.         authans = (struct TAuthans *)buf;   
    193.         memset(buf, 0, sizeof(buf));   
    194.   
    195.         Receive(socket, buf, sizeof(buf));  
    196.         if(authans->Ver != 1 || authans->Status != 0)   
    197.         {   
    198.             return CONNECT_SERVER_FAIL;  
    199.         }   
    200.     }  
    201.   
    202.     memset(buf, 0, sizeof(buf));  
    203.     struct TSock5req2 *proxyreq2;   
    204.     proxyreq2 = (struct TSock5req2 *)buf;   
    205.     proxyreq2->Ver = 5;   
    206.     proxyreq2->Cmd = 1;   
    207.     proxyreq2->Rsv = 0;   
    208.     proxyreq2->Atyp = 1;   
    209.     unsigned long tmpLong = inet_addr(ip.c_str());   
    210.     unsigned short port1 = ntohs(port);   
    211.     memcpy((char*)&proxyreq2->other, &tmpLong, 4);   
    212.     memcpy((char*)(&proxyreq2->other) + 4, &port1, 2);   
    213.   
    214.     //Send(socket, buf, sizeof(struct TSock5req2) + 5);   
    215.     Send(socket, buf, 10);   
    216.     struct TSock5ans2 *proxyans2;   
    217.     memset(buf ,0, sizeof(buf));   
    218.     proxyans2 = (struct TSock5ans2 *)buf;   
    219.       
    220.     Receive(socket, buf, sizeof(buf));  
    221.     if(proxyans2->Ver != 5 || proxyans2->Rep != 0)   
    222.     {   
    223.         return CONNECT_SERVER_FAIL;   
    224.     }  
    225.   
    226.     return SUCCESS;  
    227. }  
    228.   
    229. int CProxy::Receive(SOCKET socket, char* buf, int bufLen)  
    230. {  
    231.     return recv(socket, buf, bufLen, 0);  
    232. }  
    233.   
    234. bool CProxy::Send(SOCKET socket, const char* buf, int len)  
    235. {  
    236.     long ilen = len;  
    237.     int sendCnt = 0;  
    238.     int ret;  
    239.   
    240.     while(sendCnt < ilen)  
    241.     {  
    242.         if((ret = send(socket, buf + sendCnt, ilen - sendCnt, 0)) == SOCKET_ERROR)  
    243.         {  
    244.             return false;  
    245.         }  
    246.         else  
    247.         {  
    248.             sendCnt += ret;  
    249.         }  
    250.     }  
    251.   
    252.     return true;  
    253. }  

    proxy中用到的CBase64类

    头文件

    1. #pragma once  
    2.   
    3. #include <string>  
    4.   
    5. using namespace std;  
    6.   
    7. class CBase64  
    8. {  
    9. private:  
    10.     CBase64(void);  
    11. public:  
    12.     ~CBase64(void);  
    13.   
    14.     static string Encode(const unsigned char* Data,int DataByte);  
    15.     static string Decode(const char* Data,int DataByte,int& OutByte);  
    16. };  

    实现文件

    1. #include "StdAfx.h"  
    2. #include "Base64.h"  
    3.   
    4. CBase64::CBase64(void)  
    5. {  
    6. }  
    7.   
    8. CBase64::~CBase64(void)  
    9. {  
    10. }  
    11.   
    12. string CBase64::Encode(const unsigned char* Data,int DataByte)  
    13. {  
    14.     //编码表  
    15.     const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
    16.     //返回值  
    17.     string strEncode;  
    18.     unsigned char Tmp[4]={0};  
    19.     int LineLength=0;  
    20.     for(int i=0;i<(int)(DataByte / 3);i++)  
    21.     {  
    22.         Tmp[1] = *Data++;  
    23.         Tmp[2] = *Data++;  
    24.         Tmp[3] = *Data++;  
    25.         strEncode+= EncodeTable[Tmp[1] >> 2];  
    26.         strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];  
    27.         strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];  
    28.         strEncode+= EncodeTable[Tmp[3] & 0x3F];  
    29.         if(LineLength+=4,LineLength==76) {strEncode+=" ";LineLength=0;}  
    30.     }  
    31.     //对剩余数据进行编码  
    32.     int Mod=DataByte % 3;  
    33.     if(Mod==1)  
    34.     {  
    35.         Tmp[1] = *Data++;  
    36.         strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
    37.         strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];  
    38.         strEncode+= "==";  
    39.     }  
    40.     else if(Mod==2)  
    41.     {  
    42.         Tmp[1] = *Data++;  
    43.         Tmp[2] = *Data++;  
    44.         strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];  
    45.         strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];  
    46.         strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];  
    47.         strEncode+= "=";  
    48.     }  
    49.   
    50.     return strEncode;  
    51. }  
    52.   
    53. string CBase64::Decode(const char* Data,int DataByte,int& OutByte)  
    54. {  
    55.     //解码表  
    56.     const char DecodeTable[] =  
    57.     {  
    58.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
    59.         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
    60.         62, // '+'  
    61.         0, 0, 0,  
    62.         63, // '/'  
    63.         52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'  
    64.         0, 0, 0, 0, 0, 0, 0,  
    65.         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,  
    66.         13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'  
    67.         0, 0, 0, 0, 0, 0,  
    68.         26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  
    69.         39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'  
    70.     };  
    71.     //返回值  
    72.     string strDecode;  
    73.     int nValue;  
    74.     int i= 0;  
    75.     while (i < DataByte)  
    76.     {  
    77.         if (*Data != ' ' && *Data!=' ')  
    78.         {  
    79.             nValue = DecodeTable[*Data++] << 18;  
    80.             nValue += DecodeTable[*Data++] << 12;  
    81.             strDecode+=(nValue & 0x00FF0000) >> 16;  
    82.             OutByte++;  
    83.             if (*Data != '=')  
    84.             {  
    85.                 nValue += DecodeTable[*Data++] << 6;  
    86.                 strDecode+=(nValue & 0x0000FF00) >> 8;  
    87.                 OutByte++;  
    88.                 if (*Data != '=')  
    89.                 {  
    90.                     nValue += DecodeTable[*Data++];  
    91.                     strDecode+=nValue & 0x000000FF;  
    92.                     OutByte++;  
    93.                 }  
    94.             }  
    95.             i += 4;  
    96.         }  
    97.         else// 回车换行,跳过  
    98.         {  
    99.             Data++;  
    100.             i++;  
    101.         }  
    102.     }  
    103.     return strDecode;  
    104. }  
  • 相关阅读:
    The new powerful SQL executing schedule monthly or weekly in DB Query Analyzer 7.01
    热烈庆祝自已厉精13年开发的 DB查询分析器 7.01(最新版本) 在中关村在线本月获得近6000次的下载量
    CentOS7下安装GitLab
    DB查询分析器7.01新增的周、月SQL执行计划功能
    Ubuntu环境下Anaconda安装TensorFlow并配置Jupyter远程访问
    Docker学习笔记4: Docker-Compose—简化复杂容器应用的利器
    Docker学习笔记3:CentOS7下安装Docker-Compose
    CentOS7下安装python-pip
    [Flutter] 音频播放插件 audioplayers 的一个路径坑
    解放双手之自动拉取与推送
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318505.html
Copyright © 2011-2022 走看看