<转 >socket穿透代理代码(C++版)
本文转自 http://blog.csdn.net/bodybo/article/details/7274865
写代码经常会遇到socket要通过代理连接服务器的情况,代理类型通畅有三种:HTTP、SOCK4和SOCK5,通过学习和网上参考相关代码,写了个代理类来实现该功能,贴出来与大家共享
才贴出来两天,刚在百度一搜竟然发现已被一字不改的转载到好几个网站去了,连转载的字样都没有,不反对转载分享,可能否注明出处?
头文件
#pragma once #include <WinSock2.h>
#include <string>
#include <vector> using namespace std; enum ProxyStatus
{
SUCCESS,
CONNECT_PROXY_FAIL,
NOT_CONNECT_PROXY,
CONNECT_SERVER_FAIL
}; class CProxy
{
public:
CProxy(long type, string ip, u_short port, string username, string password)
:m_proxyType(type), m_proxyIp(ip), m_proxyPort(port), m_proxyUserName(username), m_proxyUserPwd(password)
{} ~CProxy(void){}; ProxyStatus ConnectProxyServer(SOCKET socket);
ProxyStatus ConnectServer(SOCKET socket, string ip, u_short port); private:
ProxyStatus ConnectByHttp(SOCKET socket, string ip, u_short port);
ProxyStatus ConnectBySock4(SOCKET socket, string ip, u_short port);
ProxyStatus ConnectBySock5(SOCKET socket, string ip, u_short port); bool Send(SOCKET socket, const char* buf, int len);
int Receive(SOCKET socket, char* buf, int bufLen); private:
long m_proxyType;
string m_proxyIp;
u_short m_proxyPort;
string m_proxyUserName;
string m_proxyUserPwd; bool m_blnProxyServerOk;
}; struct TSock4req1
{
char VN;
char CD;
unsigned short Port;
unsigned long IPAddr;
char other;
}; struct TSock4ans1
{
char VN;
char CD;
}; struct TSock5req1
{
char Ver;
char nMethods;
char Methods;
}; struct TSock5ans1
{
char Ver;
char Method;
}; struct TSock5req2
{
char Ver;
char Cmd;
char Rsv;
char Atyp;
char other;
}; struct TSock5ans2
{
char Ver;
char Rep;
char Rsv;
char Atyp;
char other;
}; struct TAuthreq
{
char Ver;
char Ulen;
char Name;
char PLen;
char Pass;
}; struct TAuthans
{
char Ver;
char Status;
};
实现文件
#include "StdAfx.h"
#include "Proxy.h"
#include "Base64.h"
#include "log.h" #include <time.h> ProxyStatus CProxy::ConnectProxyServer(SOCKET socket)
{
int ret;
struct timeval timeout ;
fd_set r;
string ip;
u_short port; ip = m_proxyIp;
port = m_proxyPort; sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
servAddr.sin_port = htons(port); //设置非阻塞方式连接
unsigned long ul = ;
ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul);
if(ret == SOCKET_ERROR)
{
return CONNECT_PROXY_FAIL;
} connect(socket, (sockaddr*)&servAddr, sizeof(sockaddr)); FD_ZERO(&r);
FD_SET(socket, &r);
timeout.tv_sec = ;
timeout.tv_usec =;
ret = select(, , &r, , &timeout); if (ret <= )
{
m_blnProxyServerOk = false;
return CONNECT_PROXY_FAIL;
}
else
{
m_blnProxyServerOk = true;
return SUCCESS;
}
} ProxyStatus CProxy::ConnectServer(SOCKET socket, string ip, u_short port)
{
int ret;
int nTimeout; if (!m_blnProxyServerOk)
{
return NOT_CONNECT_PROXY;
} nTimeout = ;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)); //设置接收超时 unsigned long ul = ;
ret = ioctlsocket(socket, FIONBIO, (unsigned long*)&ul); //设置阻塞方式连接 switch(m_proxyType)
{
case : //HTTP
return ConnectByHttp(socket, ip, port);
break;
case : //SOCK4
return ConnectBySock4(socket, ip, port);
break;
case : //SOCK5
return ConnectBySock5(socket, ip, port);
break;
default:
break;
} return CONNECT_SERVER_FAIL;
} ProxyStatus CProxy::ConnectByHttp(SOCKET socket, string ip, u_short port)
{
char buf[]; if (m_proxyUserName != "")
{
string str;
string strBase64;
str = m_proxyUserName + ":" + m_proxyUserPwd;
strBase64 = CBase64::Encode((unsigned char*)str.c_str(), str.length());
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",
ip.c_str(), port, ip.c_str(), port, strBase64.c_str(), strBase64.c_str());
}
else
{
//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);
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);
} Send(socket, buf, strlen(buf));
Receive(socket, buf, sizeof(buf)); if (strstr(buf, "HTTP/1.0 200 Connection established") != NULL)
{
return SUCCESS;
}
else
{
return CONNECT_SERVER_FAIL;
} } ProxyStatus CProxy::ConnectBySock4(SOCKET socket, string ip, u_short port)
{
char buf[]; memset(buf, , sizeof(buf));
struct TSock4req1 *proxyreq;
proxyreq = (struct TSock4req1*)buf;
proxyreq->VN = ;
proxyreq->CD = ;
proxyreq->Port = ntohs(port);
proxyreq->IPAddr = inet_addr(ip.c_str()); Send(socket, buf, ); struct TSock4ans1 *proxyans;
proxyans = (struct TSock4ans1*)buf;
memset(buf, , sizeof(buf)); Receive(socket, buf, sizeof(buf));
if(proxyans->VN == && proxyans->CD == )
{
return SUCCESS;
}
else
{
return CONNECT_SERVER_FAIL;
}
} ProxyStatus CProxy::ConnectBySock5(SOCKET socket, string ip, u_short port)
{
char buf[]; struct TSock5req1 *proxyreq1;
proxyreq1 = (struct TSock5req1 *)buf;
proxyreq1->Ver = ;
proxyreq1->nMethods = ;
proxyreq1->Methods = m_proxyUserName != "" ? : ; Send(socket, buf, ); struct TSock5ans1 *proxyans1;
proxyans1 = (struct TSock5ans1 *)buf; memset(buf, , sizeof(buf));
Receive(socket, buf, sizeof(buf));
if(proxyans1->Ver != || (proxyans1->Method != && proxyans1->Method != ))
{
return CONNECT_SERVER_FAIL;
} if(proxyans1->Method == )
{
int nUserLen = m_proxyUserName.length();
int nPassLen = m_proxyUserPwd.length();
//struct TAuthreq *authreq;
//authreq = (struct TAuthreq *)buf;
//authreq->Ver = 1;
//authreq->Ulen = nUserLen;
//strcpy(authreq->Name, m_proxyUserName.c_str());
//authreq->PLen = nPassLen;
//strcpy(authreq->Pass, m_proxyUserPwd.c_str()); buf[] = ;
buf[] = nUserLen;
memcpy(buf + , m_proxyUserName.c_str(), nUserLen);
buf[ + nUserLen] = nPassLen;
memcpy(buf + + nUserLen, m_proxyUserPwd.c_str(), nPassLen); Send(socket, buf, + nUserLen + nPassLen); struct TAuthans *authans;
authans = (struct TAuthans *)buf;
memset(buf, , sizeof(buf)); Receive(socket, buf, sizeof(buf));
if(authans->Ver != || authans->Status != )
{
return CONNECT_SERVER_FAIL;
}
} memset(buf, , sizeof(buf));
struct TSock5req2 *proxyreq2;
proxyreq2 = (struct TSock5req2 *)buf;
proxyreq2->Ver = ;
proxyreq2->Cmd = ;
proxyreq2->Rsv = ;
proxyreq2->Atyp = ;
unsigned long tmpLong = inet_addr(ip.c_str());
unsigned short port1 = ntohs(port);
memcpy((char*)&proxyreq2->other, &tmpLong, );
memcpy((char*)(&proxyreq2->other) + , &port1, ); //Send(socket, buf, sizeof(struct TSock5req2) + 5);
Send(socket, buf, );
struct TSock5ans2 *proxyans2;
memset(buf ,, sizeof(buf));
proxyans2 = (struct TSock5ans2 *)buf; Receive(socket, buf, sizeof(buf));
if(proxyans2->Ver != || proxyans2->Rep != )
{
return CONNECT_SERVER_FAIL;
} return SUCCESS;
} int CProxy::Receive(SOCKET socket, char* buf, int bufLen)
{
return recv(socket, buf, bufLen, );
} bool CProxy::Send(SOCKET socket, const char* buf, int len)
{
long ilen = len;
int sendCnt = ;
int ret; while(sendCnt < ilen)
{
if((ret = send(socket, buf + sendCnt, ilen - sendCnt, )) == SOCKET_ERROR)
{
return false;
}
else
{
sendCnt += ret;
}
} return true;
}
proxy中用到的CBase64类
头文件
#pragma once #include <string> using namespace std; class CBase64
{
private:
CBase64(void);
public:
~CBase64(void); static string Encode(const unsigned char* Data,int DataByte);
static string Decode(const char* Data,int DataByte,int& OutByte);
};
#include "StdAfx.h"
#include "Base64.h" CBase64::CBase64(void)
{
} CBase64::~CBase64(void)
{
} string CBase64::Encode(const unsigned char* Data,int DataByte)
{
//编码表
const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
string strEncode;
unsigned char Tmp[]={};
int LineLength=;
for(int i=;i<(int)(DataByte / );i++)
{
Tmp[] = *Data++;
Tmp[] = *Data++;
Tmp[] = *Data++;
strEncode+= EncodeTable[Tmp[] >> ];
strEncode+= EncodeTable[((Tmp[] << ) | (Tmp[] >> )) & 0x3F];
strEncode+= EncodeTable[((Tmp[] << ) | (Tmp[] >> )) & 0x3F];
strEncode+= EncodeTable[Tmp[] & 0x3F];
if(LineLength+=,LineLength==) {strEncode+="\r\n";LineLength=;}
}
//对剩余数据进行编码
int Mod=DataByte % ;
if(Mod==)
{
Tmp[] = *Data++;
strEncode+= EncodeTable[(Tmp[] & 0xFC) >> ];
strEncode+= EncodeTable[((Tmp[] & 0x03) << )];
strEncode+= "==";
}
else if(Mod==)
{
Tmp[] = *Data++;
Tmp[] = *Data++;
strEncode+= EncodeTable[(Tmp[] & 0xFC) >> ];
strEncode+= EncodeTable[((Tmp[] & 0x03) << ) | ((Tmp[] & 0xF0) >> )];
strEncode+= EncodeTable[((Tmp[] & 0x0F) << )];
strEncode+= "=";
} return strEncode;
} string CBase64::Decode(const char* Data,int DataByte,int& OutByte)
{
//解码表
const char DecodeTable[] =
{
, , , , , , , , , , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , , , , , ,
, // '+'
, , ,
, // '/'
, , , , , , , , , , // '0'-'9'
, , , , , , ,
, , , , , , , , , , , , ,
, , , , , , , , , , , , , // 'A'-'Z'
, , , , , ,
, , , , , , , , , , , , ,
, , , , , , , , , , , , , // 'a'-'z'
};
//返回值
string strDecode;
int nValue;
int i= ;
while (i < DataByte)
{
if (*Data != '\r' && *Data!='\n')
{
nValue = DecodeTable[*Data++] << ;
nValue += DecodeTable[*Data++] << ;
strDecode+=(nValue & 0x00FF0000) >> ;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << ;
strDecode+=(nValue & 0x0000FF00) >> ;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode+=nValue & 0x000000FF;
OutByte++;
}
}
i += ;
}
else// 回车换行,跳过
{
Data++;
i++;
}
}
return strDecode;
}
<转 >socket穿透代理代码(C++版)的更多相关文章
- Jenkins日常运维笔记-重启数据覆盖问题、迁移、基于java代码发版(maven构建)
之前在公司机房部署了一套jenkins环境,现需要迁移至IDC机房服务器上,迁移过程中记录了一些细节:1)jenkins默认的主目录放在当前用户家目录路径下的.jenkins目录中.如jenkins使 ...
- 《OOC》笔记(4)——自动化地将C#代码转化为C代码(结构版)
<OOC>笔记(4)——自动化地将C#代码转化为C代码(结构版) 我在<C表达面向对象语言的机制——C#版>中已经说明了从C#到C的转换方法.这次看<OOC>也是想 ...
- svn代码发版的脚本分享
背景:开发将其代码放到svn里面,如何将修改后存放到svn里的代码发布到线上?简单做法:写个shell脚本,用于代码发版.比如开发的代码存放svn的路径是:svn://112.168.19.120/h ...
- cglib动态代理代码示例
cglib动态代理代码示例 引用包cglib-xxx.jar 非Maven项目还需要手动引用包asm-xxx.jar 业务类(不需要定义接口) cglib代理类(实现接口MethodIntercept ...
- JDK动态代理代码示例
JDK动态代理代码示例 业务接口 实现了业务接口的业务类 实现了InvocationHandler接口的handler代理类 1.业务接口 package com.wzq.demo01; /** * ...
- python2.7用socks和socket设置代理
接下来是最近遇到的一个代理问题. 背景:一个基于python2.7的自动化测试项目 目的:因调试需求,需要通过代理连接其他公司的前端网站,来检验项目运行所在的问题. 问题:RUN>等了1分钟没有 ...
- 原生JS实现购物车结算功能代码+zepto版
html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- Linux 网络编程详解二(socket创建流程、多进程版)
netstat -na | grep " --查看TCP/IP协议连接状态 //socket编程提高版--服务器 #include <stdio.h> #include < ...
- 使用cow将socks5代理转为http代理(Windows版)
自己租vps架设shadowsocks服务器,再配合chrome的SwitchyOmega插件科学上网一直很稳定,但是windows很多软件都不支持socks5,经常也会需要配置http代理做更新上传 ...
随机推荐
- 超越IEtab、网银支付助手,无需再次登陆的Firefox的IE插件
强烈推荐! fire-ie最大亮点就是:可以传递firefox下的cookie,从而避免了再次登陆或打开支付页面的繁琐. 在线安装:https://addons.mozilla.org/zh-CN/f ...
- 关闭浏览器session就被干掉的假象的问题
当在前台取出session时,关闭浏览器后再次访问服务器,这时服务器返回了一个null,此时的返回的session并非之前的那个session而是一个新的session. -->先来看看sess ...
- opencv图像二值化的函数cvThreshold()。 cvAdaptiveThreshol
OpenCV中对图像进行二值化的关键函数——cvThreshold(). 函数功能:采用Canny方法对图像进行边缘检测 函数原型: void cvThreshold( const CvArr* sr ...
- HDU 多校1.12
- 并查集+背包 【CF741B】 Arpa's weak amphitheater and Mehrdad's valuable Hoses
Descirption 有n个人,每个人都有颜值bi与体重wi.剧场的容量为W.有m条关系,xi与yi表示xi和yi是好朋友,在一个小组. 每个小组要么全部参加舞会,要么参加人数不能超过1人. 问保证 ...
- DP 贪心【p2134】百日旅行
Background 重要的不是去哪里,而是和你在一起.--小红 对小明和小红来说,2014年7月29日是一个美好的日子.这一天是他们相识100天的纪念日. (小明:小红,感谢你2场大考时默默的支持, ...
- 13、Django实战第13天:分页列表功能
我们看课程 机构列表页是需要分页的 为了完成分页功能,我们需要用到Django的一个开源开发库django-pure-pagination workon mxonline pip install dj ...
- Linq 透明标识符 let
IEnumerable<Person> list = new List<Person> { , Id = }, , Id = }, , Id = }, , Id = }, , ...
- [P2397] yyy loves Maths VI (mode)
Link: P2397 传送门 Solution: (1)在这里记录一个小小的黑科技:摩尔投票法 (线性时间复杂度,$O(1)$的空间复杂度求众数) 从数组的第一个元素开始,假定它代表的群体的人数是最 ...
- [USACO17DEC]Greedy Gift Takers
题目描述 Farmer John's nemesis, Farmer Nhoj, has NN cows (1 \leq N \leq 10^51≤N≤105 ), conveniently numb ...