通过spi实现socks5代理(含错误代码)

pig_2000 2007-02-21 03:25:03
代理客户端开发,截获某些应用的网络通讯,对网络数据进行socks5封包,然后通过支持socks5的通用代理服务器中转。

我现在对整个流程的技术如何实现感觉很糊涂,希望有高手能指点迷津。

首先我与代理服务器进行连接、协商、验证身份及获取代理服务器上传输端口应该在哪里来实现?是在WSPConnect里吗?

如果我在WSPConnect里实现是不是就不能用connect连接服务器,必须调用下一层lpWSPConnect来连接代理服务器。
还有如果获取到代理服务器上的传输端口,如何告知WSPSendTo服务器的端口是什么,因为一次可能不止一个网络应用在运行,如何保证每个应用发送数据时都能正确的发送到指定的代理服务器端口?是否需要在内存中建个列表,针对每个应用存储对应的端口?

我调试IE发现,即使在同一IE窗口、同一网站,每次打开一个网页都有2次WSPConnect过程,一个连接域名服务器,一次连接相应的网站服务器。
如果我要实现代理,是否每次WSPConnect过程都要实现与代理服务器连接、协商、验证身份及获取代理服务器上传输端口过程?

我现在对spi和socks5有一些了解(不是很深入),但是如何把这两个技术糅合到一起感觉非常迷惑,希望有过这方面开发经验的同志,能给我些提示,如果有例子源码更好。

在此十分感谢,下边是WSPConnect里实现与代理服务器进行连接、协商、验证身份及获取代理服务器上传输端口源码,感觉应该是错误的,我也是抄别人后自己瞎改的,大家看一下。

int WSPAPI WSPConnect(
SOCKET s,
const struct sockaddr FAR * name,
int namelen,
LPWSABUF lpCallerData,
LPWSABUF lpCalleeData,
LPQOS lpSQOS,
LPQOS lpGQOS,
LPINT lpErrno
)
{
ODS(_T("XFILTER.DLL: WSPConnect ..."));

if(m_CheckAcl.CheckConnect(s, name, namelen) != XF_PASS)
{
ODS2(_T("Deny the application "), m_sProcessName);
*lpErrno = WSAECONNREFUSED;
return SOCKET_ERROR;
}

//socks5代理
SOCKET tcp;
u_short m_n_port;
char buf[1024];
tcp = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr,mAddr;
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr("159.226.26.71"); //代理服务地址(SuperProXY)
addr.sin_port= htons(8080);
if(connect(tcp,(sockaddr*)&addr,sizeof(addr))==SOCKET_ERROR)
{
closesocket(tcp);
return false;
}
memset(buf,0,1024);
buf[0]=0x05;
buf[1]=0x02;
buf[2]=0x00;
buf[3]=0x02;
send(tcp,buf,4,0);
memset(buf,0,1024);
if(recv(tcp,buf,1024,0)==SOCKET_ERROR)
{
closesocket(tcp);
return false;
}
//分析第一个接收数据
if(buf[0]==0x05 && buf[1]==0x02)
{
AfxMessageBox("需要验证密码!");
}
else if(buf[0]!=0x05 || buf[1]!=0x00)
{
closesocket(tcp);
return false;
}

//第二步操作(我的代理服务不需要验证所以直接到了下一步)
memset(buf,0,1024);
buf[0]=0x05;
buf[1]=0x03; //0x03 UDP命令
buf[2]=0x00;//保留字节
buf[3]=0x01;//地址类型 1表示 IPV4
mAddr.sin_family= AF_INET;
mAddr.sin_addr.s_addr= inet_addr("1.1.51.227"); //远程服务地址(演示需要就在本机运行的)
mAddr.sin_port= htons(8001);
*((int *)(&buf[4])) = mAddr.sin_addr.s_addr;
*((short *)(&(buf[8]))) = (short)mAddr.sin_port;
send(tcp,buf,10,0);
memset(buf,0,1024);
if(recv(tcp,buf,1024,0)==SOCKET_ERROR)
{
closesocket(tcp);
return false;
}
//回答信息:版本 | 代理的应答 | 保留1字节 | 地址类型 | 绑定的地址 | 绑定的代理端口
if(buf[0]!=0x05 || buf[1]!=0x00) //00表示成功
{
closesocket(tcp);
return false;
}
if(buf[3]==0x01) //已经执行到该步了
{
char m_sz_udp_srv[1024];
int n_ip = *((int *)&buf[4]);
memset((void *)m_sz_udp_srv,0,sizeof(m_sz_udp_srv));
in_addr in;
in.S_un.S_addr = n_ip;
strcpy(m_sz_udp_srv,inet_ntoa(in)); //得到值为1.1.51.227
m_n_port = htons(*((short *)&(buf[8]))); //端口1328
}
else
{
closesocket(tcp);
return false;
}
//发送数据了
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr("1.1.51.227"); //点分地址
addr.sin_port= htons(8001);//这个ip是服务器端的ip
buf[0] = 0x00;
buf[1] = 0x00; //RSV 保留 0000
buf[2] = 0x00; //FRAH 分段号 00表示独立
buf[3] = 0x01; //ATYP IPV4 01
buf[4]=(char)addr.sin_addr.S_un.S_un_b.s_b1;
buf[5]=(char)addr.sin_addr.S_un.S_un_b.s_b2;
buf[6]=(char)addr.sin_addr.S_un.S_un_b.s_b3;
buf[7]=(char)addr.sin_addr.S_un.S_un_b.s_b4;
*((SHORT*)(&(buf[8])))=addr.sin_port;

buf[10] = 18;
struct sockaddr_in bndaddr;
bndaddr.sin_family = AF_INET;
bndaddr.sin_addr.s_addr = inet_addr("1.1.51.227");//返回时绑定的IP
bndaddr.sin_port = htons(m_n_port);//发送请求的时返回的代理绑定的端口
int addr_len;
addr_len=sizeof(struct sockaddr);
int returndatalen=sendto(s,(char *)buf,strlen(buf),0,(struct sockaddr *)&bndaddr,addr_len);

//return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
}
...全文
1214 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
keanchen0928 2010-01-13
  • 打赏
  • 举报
回复
楼上的,你会吗?我正要弄这个。和楼主一样的迷茫!
潮汕吴先生 2010-01-06
  • 打赏
  • 举报
回复
一看就知道是在吹,吹吧。
iisfirewall 2008-10-24
  • 打赏
  • 举报
回复
很多时候 你的问题都是自问自答 你问的问题 都从来没有给出个解答出来 然后又继续问

自私还是不晓得如何共享问题。

我也拒绝回答 即使我知道!跟你学
sosonokia 2007-03-30
  • 打赏
  • 举报
回复
up
cwhl2003 2007-03-28
  • 打赏
  • 举报
回复
请问你真的全部实现了吗,如果你的connect函数没有立即完成怎么办呢?后面的收发显然是不可能成功的?
pig_2000 2007-02-27
  • 打赏
  • 举报
回复
现在问题基本都解决了,QQ、MSN...都可以转发,除了IE

不知道上边的代码为什么无法转发IE浏览器的信息,难道IE与其他的机制不一样?
pig_2000 2007-02-25
  • 打赏
  • 举报
回复
我现在可以在WSPConnect中实现与代理服务器的连接、协商、验证身份等工作,按理说SOCKET s记录着此网络连接的句柄,我只要在WSPSend中通过此连接发送数据就可以了,可是实际测试中发现无法发送和接受数据。

这是什么原因?

难道IE每次访问网站的过程中WSPConnect和WSPSend以及WSPRecv中的s不是同一个网络连接句柄?

我是用的socks5 tcp连接不是udp连接。

int WSPAPI WSPConnect(
SOCKET s,
const struct sockaddr FAR * name,
int namelen,
LPWSABUF lpCallerData,
LPWSABUF lpCalleeData,
LPQOS lpSQOS,
LPQOS lpGQOS,
LPINT lpErrno
)
{
ODS(_T("XFILTER.DLL: WSPConnect ..."));

if(m_CheckAcl.CheckConnect(s, name, namelen) != XF_PASS)
{
ODS2(_T("Deny the application "), m_sProcessName);
*lpErrno = WSAECONNREFUSED;
return SOCKET_ERROR;
}


/////////////////////////////////////////////////////////////////
//socks5代理
int nRet = 0;
u_short m_n_port;
char buf[1024];
s = socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr,mAddr;
addr.sin_family= AF_INET;
addr.sin_addr.s_addr= inet_addr("159.226.26.71"); //代理服务地址(SuperProXY)
addr.sin_port= htons(8080);

nRet = NextProcTable.lpWSPConnect(s, (SOCKADDR*)&addr, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);

memset(buf,0,1024);
buf[0]=0x05;
buf[1]=0x02;
buf[2]=0x00;
buf[3]=0x02;

send(s,buf,4,0);
memset(buf,0,1024);

if(recv(s,buf,1024,0)==SOCKET_ERROR)
{
closesocket(s);
return false;
}
//分析第一个接收数据
if(buf[0]==0x05 && buf[1]==0x02)
{
//需要验证密码
memset(buf,0,1024);
buf[0]=0x01;
buf[1]=0x04;
buf[2]='t';
buf[3]='e';
buf[4]='s';
buf[5]='t';
buf[6]=0x04;
buf[7]='t';
buf[8]='e';
buf[9]='s';
buf[10]='t';
send(s,buf,11,0);
memset(buf,0,1024);

if(recv(s,buf,1024,0)==SOCKET_ERROR)
{
closesocket(s);
return false;
}

if(buf[1] != 0x00)
{
//用户名密码错误
closesocket(s);
return false;
}
}
else if(buf[0]!=0x05 || buf[1]!=0x00)
{
closesocket(s);
return false;
}

memcpy((SOCKADDR*)&mAddr, name, sizeof(SOCKADDR));
memset(buf,0,1024);
buf[0]=0x05;
buf[1]=0x01; //0x01 tcp connect命令
buf[2]=0x00;//保留字节
buf[3]=0x01;//地址类型 1表示 IPV4
*((int *)(&buf[4])) = mAddr.sin_addr.s_addr;
*((short *)(&(buf[8]))) = (short)mAddr.sin_port;
send(s,buf,10,0);
memset(buf,0,1024);
if(recv(s,buf,1024,0)==SOCKET_ERROR)
{
closesocket(s);
return false;
}
//回答信息:版本 | 代理的应答 | 保留1字节 | 地址类型 | 绑定的地址 | 绑定的代理端口
if(buf[0]!=0x05 || buf[1]!=0x00) //00表示成功
{
closesocket(s);
return false;
}
if(buf[3]==0x01) //已经执行到该步了
{
char m_sz_udp_srv[1024];
int n_ip = *((int *)&buf[4]);
memset((void *)m_sz_udp_srv,0,sizeof(m_sz_udp_srv));
in_addr in;
in.S_un.S_addr = n_ip;
strcpy(m_sz_udp_srv,inet_ntoa(in));
m_n_port = htons(*((short *)&(buf[8])));
}
else
{
closesocket(s);
return false;
}

return s;
}


int WSPAPI WSPSend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno
)
{
ODS(_T("XFILTER.DLL: WSPSend ..."));

if (m_CheckAcl.CheckSend(s, lpBuffers[0].buf, lpBuffers[0].len, lpNumberOfBytesSent) != XF_PASS)
{
XfShutdown(s);
*lpErrno = WSAECONNABORTED;
return SOCKET_ERROR;
}

return NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped
, lpCompletionRoutine, lpThreadId, lpErrno);

}
Juchiyufei 2007-02-22
  • 打赏
  • 举报
回复
免费给你UP一下。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧