V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
undefinedList
V2EX  ›  C

有偿求助: winsock lsp tcp 代理部分;详情见描述

  •  1
     
  •   undefinedList · 2018-05-30 19:16:52 +08:00 · 696 次点击
    这是一个创建于 2403 天前的主题,其中的信息可能已经有所发展或是发生改变。

    使用 lsp->socks5 来做游戏代理,主要是自用的 步骤如下: 1:拦截 wspSocket,创建相同参数的 socket ① 2:拦截 asyncSelect 和 eventSelect。wspIoctl 并记录参数 3:connect 时用①来代替原来的 socket,如果被修改过阻塞类型那么将类型修改为阻塞;和 socks5 代理协商并发送需要代理的数据;重新设置 async,event,wspIoctl 三种事件 结果:LOL 登陆是成功的,但开始游戏后聊天室连接不上(这个没啥,还凑合);倒计时结束开始加载对战界面的时候会提示连接服务器失败 求助:我该如何做

    connect 部分代码如下:

    #include "stdafx.h"
    
    // an ip address is local address ; such as 127.0.0.1 169 192.168
    bool isLocalAddr(const struct sockaddr *lpTo) {
    	
    }
    
    //检查进程是否走代理
    bool isProxy() {
    	
    }
    
    bool SetSocketNonblock(SOCK_INFO *s, u_long nonblock)
    {
    	WSATHREADID id;
    	id.ThreadHandle = GetCurrentThread();
    	id.Reserved = NULL;
    	INT err;
    	DWORD pvout, pvlen = sizeof(DWORD);
    	return s->Provider->NextProcTable.lpWSPIoctl(s->ProviderSocket, FIONBIO, &nonblock, sizeof(u_long), &pvout,	sizeof(DWORD), &pvlen, NULL, NULL, &id, &err) == 0;
    }
    
    int changeBlocking(SOCK_INFO *s, bool isReset = false) {
    	int err = 0, ret = 0, nonBlock;
    
    	if (isReset) {
    		if (s->blockingType == BLOCKING_EVENT) {
    			ret = s->Provider->NextProcTable.lpWSPEventSelect(s->ProviderSocket, s->eventSelectInfo.hEventObject, s->eventSelectInfo.lNetworkEvents, &err);
    		}
    		else if(s->blockingType == BLOCKING_ASYNC){
    			ret = s->Provider->NextProcTable.lpWSPAsyncSelect(s->ProviderSocket, s->asyncSelectInfo.hWnd, s->asyncSelectInfo.wMsg, s->asyncSelectInfo.lEvent,  &err);
    		}
    		if (ret == SOCKET_ERROR) {
    			dbgprint("Error: reset socket %d failed: %d",s->ProviderSocket,err);
    			goto cleanup;
    		}
    	}
    	else {
    		nonBlock = 0;
    		if (s->blockingType == BLOCKING_EVENT) {
    			ret = s->Provider->NextProcTable.lpWSPEventSelect(s->ProviderSocket, 0, NULL, &err);
    		}
    		else if (s->blockingType == BLOCKING_ASYNC) {
    			ret = s->Provider->NextProcTable.lpWSPAsyncSelect(s->ProviderSocket, s->asyncSelectInfo.hWnd, 0, 0, &err);
    		}
    		if (ret == SOCKET_ERROR) {
    			dbgprint("Error: clean socket %d event failed: %d", s->ProviderSocket, err);
    			goto cleanup;
    		}
    		SetSocketNonblock(s, FALSE);
    	}
    
    cleanup:
    
    	return ret;
    }
    
    int ProxyConnect(SOCK_INFO *SocketContext, const struct sockaddr FAR * name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno) {
    	if (!isProxy() || isLocalAddr(name)) {
    		return  SocketContext->Provider->NextProcTable.lpWSPConnect(SocketContext->ProviderSocket, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
    	}
    	dbgprint("Info: socket using lsp connect");
    	int err = 0, ret = 0;
    	DWORD byteLen = 0;
    	ULONG nonBlock;
    	//SetBlockingProvider(SocketContext->Provider);
    	ret = changeBlocking(SocketContext, false);
    	if (ret != 0) {
    		dbgprint("Error: connect socket %d change type failed %d", SocketContext->ProviderSocket, ret);
    		goto cleanup;
    	}
    	nonBlock = 0;
    	sockaddr_in serveraddr;
    	memset(&serveraddr, 0, sizeof(serveraddr));
    	serveraddr.sin_family = AF_INET;
    	serveraddr.sin_addr.S_un.S_addr = inet_addr(proxyHost); //代理服务器地址
    	serveraddr.sin_port = htons(proxyPort); // 端口号
    	WSABUF DataBuf;
    	char buffer[4];
    	memset(buffer, 0, sizeof(buffer));
    	DataBuf.len = 4;
    	DataBuf.buf = buffer;
    	err = 0;
    	ret = SocketContext->Provider->NextProcTable.lpWSPConnect(SocketContext->ProviderSocket, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr), &DataBuf, lpCalleeData, lpSQOS, lpGQOS, &err);
    	if (ret == SOCKET_ERROR)
    	{
    		dbgprint("Error: lpError is : %d;socket is %d", err, SocketContext->ProviderSocket);
    		goto cleanup;
    	}
    	dbgprint("Info: connection to proxy %d,%s", SocketContext->ProviderSocket, callerFileNameFull);
    	// 发送请求来协商版本和认证方法
    	//VER   NMETHODS    METHODS  
    	//1     1           1 to 255  
    	char verstring[257];
    	verstring[0] = 0x05;    //VER (1 Byte)  
    	verstring[1] = 0x01;    //NMETHODS (1 Byte)  
    	verstring[2] = 0x00;    //METHODS (allow 1 - 255 bytes, current 1 byte) 
    	WSABUF infoBuf;
    	infoBuf.len = 257;
    	infoBuf.buf = verstring;
    	err = 0;
    	ret = SocketContext->Provider->NextProcTable.lpWSPSend(SocketContext->ProviderSocket, &infoBuf, 1, &byteLen, 0, NULL, NULL, NULL, &err);
    	//rc = send(SocketContext->ProviderSocket, verstring, 257, 0);
    	if (ret == SOCKET_ERROR)
    	{
    		dbgprint("Error: consult send version data to proxy failed: %d; sokcet is: %d", WSAGetLastError(), SocketContext->ProviderSocket);
    		goto cleanup;
    	}
    	dbgprint("Info: socket send to server consult data success %d", SocketContext->ProviderSocket);
    	/*
    	* 接收代理服务器返回信息
    	*/
    	//rc = SocketContext->Provider->NextProcTable.lpWSPRecv(SocketContext->ProviderSocket, &infoBuf, 1, &byteLen, 0, NULL, NULL, NULL, &err);
    	ret = recv(SocketContext->ProviderSocket, verstring, 257, 0);
    	if (ret == SOCKET_ERROR)
    	{
    		dbgprint("Error: consult recv data from proxy failed :%d", WSAGetLastError());
    		goto cleanup;
    	}
    	struct sockaddr_in sin;
    	sin = *(const struct sockaddr_in *)name;
    	char buf[10];
    	buf[0] = 0x05; // 版本 SOCKS5
    	buf[1] = 0x01; // 连接请求  
    	buf[2] = 0x00; // 保留字段  
    	buf[3] = 0x01; // IPV4  
    	memcpy(&buf[4], &sin.sin_addr.S_un.S_addr, 4);
    	memcpy(&buf[8], &sin.sin_port, 2);
    	//发送  
    	WSABUF infoBufData;
    	infoBufData.len = sizeof(buf);
    	infoBufData.buf = buf;
    	byteLen = 0;
    	//rc = SocketContext->Provider->NextProcTable.lpWSPSend(SocketContext->ProviderSocket, &infoBufData, 1, &byteLen, 0, NULL, NULL, NULL, &err);
    	ret = send(SocketContext->ProviderSocket, buf, 10, 0);
    	if (ret == SOCKET_ERROR)
    	{
    		dbgprint("Error: send proxy data to server failed: %d", err);
    		goto cleanup;
    	}
    	//rc = SocketContext->Provider->NextProcTable.lpWSPRecv(SocketContext->ProviderSocket, &infoBufData, 1, &byteLen, 0, NULL, NULL, NULL, &err);
    	ret = recv(SocketContext->ProviderSocket, buf, 10, 0);
    	if (ret == SOCKET_ERROR)
    	{
    		dbgprint("Error: recv proxy server return failed :%d", WSAGetLastError());
    		ret = ECONNREFUSED;
    		goto cleanup;
    	}
    	SetSocketNonblock(SocketContext, SocketContext->Nonblock);
    	ret = changeBlocking(SocketContext, true);
    	if (ret != 0) {
    		dbgprint("Error: connect socket %d reset type failed %d", SocketContext->ProviderSocket, ret);
    		goto cleanup;
    	}
    	
    	ret = NO_ERROR;
    	dbgprint("Info: socket connected %d", SocketContext->ProviderSocket);
    
    cleanup:
    
    	return ret;
    }
    
    第 1 条附言  ·  2018-05-31 11:01:08 +08:00
    补充下:
    sendto 和 recvFrom 有写,也都是走了代理的
    6 条回复    2018-05-31 18:39:41 +08:00
    undefinedList
        1
    undefinedList  
    OP
       2018-05-30 23:52:06 +08:00
    自顶。。求助
    db520
        2
    db520  
       2018-05-31 06:48:23 +08:00 via iPhone
    可能登录后用的是 udp,因此你的 sock5 还需要代理 udp
    undefinedList
        3
    undefinedList  
    OP
       2018-05-31 09:56:41 +08:00
    感谢大佬,udp 是 ok 的,从抓包看,没有产生 udp 包,@db520 大神起真早
    undefinedList
        4
    undefinedList  
    OP
       2018-05-31 10:41:53 +08:00
    RMB500 求助,来大佬教我
    undefinedList
        5
    undefinedList  
    OP
       2018-05-31 16:37:37 +08:00
    tcp 部分的解决了,原因:源 socket 1 ; lsp socket2
    1 使用了 ioctl 来控制阻塞状态,2 未处理,正常情况下返回的应该是:return: SOCKET_ERROR; *lpErrno: 10035; 由于未处理,返回了:0 ; 0 ; 1 的程序就出错了

    后续: 特么 lol 还是读秒后连不上,继续求助
    undefinedList
        6
    undefinedList  
    OP
       2018-05-31 18:39:41 +08:00
    解决了, 结帖
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   928 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:26 · PVG 05:26 · LAX 13:26 · JFK 16:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.