当前位置:   article > 正文

socket穿透代理代码(C++版)

socket穿透代理代码(C++版)

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


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


头文件

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

实现文件

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

proxy中用到的CBase64类

头文件

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

实现文件

  1. #include "StdAfx.h"
  2. #include "Base64.h"
  3. CBase64::CBase64(void)
  4. {
  5. }
  6. CBase64::~CBase64(void)
  7. {
  8. }
  9. string CBase64::Encode(const unsigned char* Data,int DataByte)
  10. {
  11. //编码表
  12. const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  13. //返回值
  14. string strEncode;
  15. unsigned char Tmp[4]={0};
  16. int LineLength=0;
  17. for(int i=0;i<(int)(DataByte / 3);i++)
  18. {
  19. Tmp[1] = *Data++;
  20. Tmp[2] = *Data++;
  21. Tmp[3] = *Data++;
  22. strEncode+= EncodeTable[Tmp[1] >> 2];
  23. strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
  24. strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
  25. strEncode+= EncodeTable[Tmp[3] & 0x3F];
  26. if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
  27. }
  28. //对剩余数据进行编码
  29. int Mod=DataByte % 3;
  30. if(Mod==1)
  31. {
  32. Tmp[1] = *Data++;
  33. strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
  34. strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
  35. strEncode+= "==";
  36. }
  37. else if(Mod==2)
  38. {
  39. Tmp[1] = *Data++;
  40. Tmp[2] = *Data++;
  41. strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
  42. strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
  43. strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
  44. strEncode+= "=";
  45. }
  46. return strEncode;
  47. }
  48. string CBase64::Decode(const char* Data,int DataByte,int& OutByte)
  49. {
  50. //解码表
  51. const char DecodeTable[] =
  52. {
  53. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  54. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  55. 62, // '+'
  56. 0, 0, 0,
  57. 63, // '/'
  58. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
  59. 0, 0, 0, 0, 0, 0, 0,
  60. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
  61. 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
  62. 0, 0, 0, 0, 0, 0,
  63. 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
  64. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
  65. };
  66. //返回值
  67. string strDecode;
  68. int nValue;
  69. int i= 0;
  70. while (i < DataByte)
  71. {
  72. if (*Data != '\r' && *Data!='\n')
  73. {
  74. nValue = DecodeTable[*Data++] << 18;
  75. nValue += DecodeTable[*Data++] << 12;
  76. strDecode+=(nValue & 0x00FF0000) >> 16;
  77. OutByte++;
  78. if (*Data != '=')
  79. {
  80. nValue += DecodeTable[*Data++] << 6;
  81. strDecode+=(nValue & 0x0000FF00) >> 8;
  82. OutByte++;
  83. if (*Data != '=')
  84. {
  85. nValue += DecodeTable[*Data++];
  86. strDecode+=nValue & 0x000000FF;
  87. OutByte++;
  88. }
  89. }
  90. i += 4;
  91. }
  92. else// 回车换行,跳过
  93. {
  94. Data++;
  95. i++;
  96. }
  97. }
  98. return strDecode;
  99. }


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/114452
推荐阅读
相关标签
  

闽ICP备14008679号