LSP 拦截 TCP 使用SOCKS5 实现单进程 单IP 长连接失败

it2024-02-01  64

LSP 拦截 TCP 使用SOCKS5 实现单进程 单IP 长连接失败 https://bbs.pediy.com/thread-203313.htm

小弟,刚开始接触这方面,而且编程基础薄弱,网上找到些代码,自己改了下,实现了LSP 的安装和卸载,而且,上网也正常,LSP dll 里面 根据进程名来判断是否使用SOCKS5 代理,浏览器,访问都没问题。但是一旦建立TCP 长连接,连接成功后,立刻断掉。找不到原因,求大神看看 ```cpp / 连接socks5代理 int socksProxyEx(SOCKET s, const struct sockaddr *name, int namelen) { char ip[] = "**.**.**.**"; int host = 40136; char user[] = "jxqy8671%#**"; char password[] = "43***"; int rc = 0; if(rc = WSAEventSelect(s, 0, NULL))//这一个可以不用执行 { PutDbgStr(L"Error %d : WSAEventSelect Failure!", WSAGetLastError()); } else { PutDbgStr(L"Message : WSAEventSelect successfully!"); } //这里应该先保存下socket的阻塞/非阻塞类型,在最后面跟据这里的值将它还原,但是不知道怎样获取此类型 // 修改socket为阻塞类型 unsigned long nonBlock = 0; if(rc = ioctlsocket(s, FIONBIO, &nonBlock))// 这个真正修改为阻塞类型 { PutDbgStr(L"Error %d : Set Blocking Failure!", WSAGetLastError()); } else { PutDbgStr(L"Message : Set Blocking successfully!"); } //连接代理服务器 sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.S_un.S_addr = inet_addr(ip); serveraddr.sin_port = htons(host); // 端口号 WSABUF DataBuf; char buffer[4]; memset(buffer, 0, sizeof(buffer)); DataBuf.len = 4; DataBuf.buf = buffer; int err = 0; if((rc = NextProcTable.lpWSPConnect(s, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr), &DataBuf, NULL, NULL, NULL, &err)) != 0) { PutDbgStr(L"Error %d : attempting to connect to SOCKS server!", err); return rc; } else { PutDbgStr(L"Message : Connect to SOCKS server successfully!"); } //发送请求来协商版本和认证方法 //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) if((rc = send(s, verstring, 3, 0)) < 0) { PutDbgStr(L"Error %d : attempting to send SOCKS method negotiation!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : send SOCKS method negotiation successfully!"); } //接收代理服务器返回信息 //VER METHOD //1 1 /*当前定义的方法有: · X’00’ 不需要认证 · X’01’ GSSAPI · X’02’ 用户名/密码 · X’03’ -- X’7F’ 由IANA分配 · X’80’ -- X’FE’ 为私人方法所保留的 · X’FF’ 没有可以接受的方法*/ char ver[2]; if(recv(s, ver, 2, 0) < 0) { return ECONNABORTED; } char xxxx = ver[1]; TCHAR Msg[155]; wsprintf(Msg,L"...................socks5 返回判断标示 %c...................",xxxx); OutputDebugString(Msg); // 代理服务器选择方法 // 判断我们的方法是否可行 if(ver[1] == 0xff) { PutDbgStr(L"Error : SOCKS server refused authentication methods!"); rc = ECONNREFUSED; return rc; } else if(ver[1] == 0x02)// 方法2 : 用户名/密码 { //另外处理 char Buffer[50]; *(int*)(Buffer+0)=(int)1; int ui=strlen(user); memcpy(Buffer+1,(char*)&ui,1); memcpy(Buffer+2,user,ui); int pi=strlen(password); memcpy(Buffer+2+ui,(char*)&pi,1); memcpy(Buffer+2+ui+1,password,pi); if((rc = send(s, Buffer, 3+ui+pi, 0)) < 0) { return rc; } if((rc = recv(s, Buffer, 2, 0)) < 0) { OutputDebugString(L"用户名密码验证IP测试失败1"); return ECONNREFUSED; } if(Buffer[1]!= 0x00){ OutputDebugString(L"用户名密码验证IP测试失败2"); return ECONNREFUSED; } OutputDebugString(L"用户名密码验证IP测试通过"); } else if(ver[1] == 0x00)// 方法0: 不需要认证 { struct sockaddr_in sin; sin = *(const struct sockaddr_in *)name; char buf[10]; buf[0] = '/x05'; // 版本 SOCKS5 buf[1] = '/x01'; // 连接请求 buf[2] = '/x00'; // 保留字段 buf[3] = '/x01'; // IPV4 memcpy(&buf[4], &sin.sin_addr.S_un.S_addr, 4); memcpy(&buf[8], &sin.sin_port, 2); //发送 if((rc = send(s, buf, 10, 0)) < 0) { PutDbgStr(L"Error %d : attempting to send SOCKS connect command!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : send SOCKS connect command successfully!"); } if((rc = recv(s, buf, 10, 0)) < 0) // 用了天翼的网络之后,这里就接收不到返回信息了,不解 { PutDbgStr(L"Error %d : attempting to receive SOCKS connection reply!", WSAGetLastError()); rc = ECONNREFUSED; return rc; } else { PutDbgStr(L"Message : receive SOCKS connection reply successfully!"); } if(rc < 10) { PutDbgStr(L"Message : Short reply from SOCKS server!"); return rc; } else { PutDbgStr(L"Message : reply from SOCKS larger than 10!"); } //连接不成功 if(buf[0] != '/x05') { PutDbgStr(L"Message : Socks V5 not supported!"); return ECONNABORTED; } else { PutDbgStr(L"Message : Socks V5 is supported!"); } if(buf[1] != '/x00') { PutDbgStr(L"Message : SOCKS connect failed!"); switch((int)buf[1]) { case 1: PutDbgStr(L"General SOCKS server failure!"); return ECONNABORTED; case 2: PutDbgStr(L"Connection denied by rule!"); return ECONNABORTED; case 3: PutDbgStr(L"Network unreachable!"); return ENETUNREACH; case 4: PutDbgStr(L"Host unreachable!"); return EHOSTUNREACH; case 5: PutDbgStr(L"Connection refused!"); return ECONNREFUSED; case 6: PutDbgStr(L"TTL Expired!"); return ETIMEDOUT; case 7: PutDbgStr(L"Command not supported!"); return ECONNABORTED; case 8: PutDbgStr(L"Address type not supported!"); return ECONNABORTED; default: PutDbgStr(L"Unknown error!"); return ECONNABORTED; } } else { PutDbgStr(L"Message : SOCKS connect Success!"); } } else { PutDbgStr(L"Error : Method not supported!"); } //修改socket为非阻塞类型 nonBlock = 1; if(rc = ioctlsocket(s, FIONBIO, &nonBlock)) { PutDbgStr(L"Error %d : Set Non-Blocking Failure!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : Set Non-Blocking Successful!"); } PutDbgStr(L"Message : Success!"); return 0; }

这是自己写的Socks5 代理调用函数

// 连接socks5代理 int socksProxyEx(SOCKET s, const struct sockaddr name, int namelen) { char ip[] = “...”; int host = 40136; char user[] = "jxqy8671%#"; char password[] = "43"; int rc = 0; if(rc = WSAEventSelect(s, 0, NULL))//这一个可以不用执行 { PutDbgStr(L"Error %d : WSAEventSelect Failure!", WSAGetLastError()); } else { PutDbgStr(L"Message : WSAEventSelect successfully!"); } //这里应该先保存下socket的阻塞/非阻塞类型,在最后面跟据这里的值将它还原,但是不知道怎样获取此类型 // 修改socket为阻塞类型 unsigned long nonBlock = 0; if(rc = ioctlsocket(s, FIONBIO, &nonBlock))// 这个真正修改为阻塞类型 { PutDbgStr(L"Error %d : Set Blocking Failure!", WSAGetLastError()); } else { PutDbgStr(L"Message : Set Blocking successfully!"); } //连接代理服务器 sockaddr_in serveraddr; memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.S_un.S_addr = inet_addr(ip); serveraddr.sin_port = htons(host); // 端口号 WSABUF DataBuf; char buffer[4]; memset(buffer, 0, sizeof(buffer)); DataBuf.len = 4; DataBuf.buf = buffer; int err = 0; if((rc = NextProcTable.lpWSPConnect(s, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr), &DataBuf, NULL, NULL, NULL, &err)) != 0) { PutDbgStr(L"Error %d : attempting to connect to SOCKS server!", err); return rc; } else { PutDbgStr(L"Message : Connect to SOCKS server successfully!"); }

//发送请求来协商版本和认证方法 //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) if((rc = send(s, verstring, 3, 0)) < 0) { PutDbgStr(L"Error %d : attempting to send SOCKS method negotiation!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : send SOCKS method negotiation successfully!"); } //接收代理服务器返回信息 //VER METHOD //1 1 /*当前定义的方法有: · X’00’ 不需要认证 · X’01’ GSSAPI · X’02’ 用户名/密码 · X’03’ -- X’7F’ 由IANA分配 · X’80’ -- X’FE’ 为私人方法所保留的 · X’FF’ 没有可以接受的方法*/ char ver[2]; if(recv(s, ver, 2, 0) < 0) { return ECONNABORTED; } char xxxx = ver[1]; TCHAR Msg[155]; wsprintf(Msg,L"...................socks5 返回判断标示 %c...................",xxxx); OutputDebugString(Msg); // 代理服务器选择方法 // 判断我们的方法是否可行 if(ver[1] == 0xff) { PutDbgStr(L"Error : SOCKS server refused authentication methods!"); rc = ECONNREFUSED; return rc; } else if(ver[1] == 0x02)// 方法2 : 用户名/密码 { //另外处理 char Buffer[50]; *(int*)(Buffer+0)=(int)1; int ui=strlen(user); memcpy(Buffer+1,(char*)&ui,1); memcpy(Buffer+2,user,ui); int pi=strlen(password); memcpy(Buffer+2+ui,(char*)&pi,1); memcpy(Buffer+2+ui+1,password,pi); if((rc = send(s, Buffer, 3+ui+pi, 0)) < 0) { return rc; } if((rc = recv(s, Buffer, 2, 0)) < 0) { OutputDebugString(L"用户名密码验证IP测试失败1"); return ECONNREFUSED; } if(Buffer[1]!= 0x00){ OutputDebugString(L"用户名密码验证IP测试失败2"); return ECONNREFUSED; } OutputDebugString(L"用户名密码验证IP测试通过"); } else if(ver[1] == 0x00)// 方法0: 不需要认证 { struct sockaddr_in sin; sin = *(const struct sockaddr_in *)name; char buf[10]; buf[0] = '/x05'; // 版本 SOCKS5 buf[1] = '/x01'; // 连接请求 buf[2] = '/x00'; // 保留字段 buf[3] = '/x01'; // IPV4 memcpy(&buf[4], &sin.sin_addr.S_un.S_addr, 4); memcpy(&buf[8], &sin.sin_port, 2); //发送 if((rc = send(s, buf, 10, 0)) < 0) { PutDbgStr(L"Error %d : attempting to send SOCKS connect command!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : send SOCKS connect command successfully!"); } if((rc = recv(s, buf, 10, 0)) < 0) // 用了天翼的网络之后,这里就接收不到返回信息了,不解 { PutDbgStr(L"Error %d : attempting to receive SOCKS connection reply!", WSAGetLastError()); rc = ECONNREFUSED; return rc; } else { PutDbgStr(L"Message : receive SOCKS connection reply successfully!"); } if(rc < 10) { PutDbgStr(L"Message : Short reply from SOCKS server!"); return rc; } else { PutDbgStr(L"Message : reply from SOCKS larger than 10!"); } //连接不成功 if(buf[0] != '/x05') { PutDbgStr(L"Message : Socks V5 not supported!"); return ECONNABORTED; } else { PutDbgStr(L"Message : Socks V5 is supported!"); } if(buf[1] != '/x00') { PutDbgStr(L"Message : SOCKS connect failed!"); switch((int)buf[1]) { case 1: PutDbgStr(L"General SOCKS server failure!"); return ECONNABORTED; case 2: PutDbgStr(L"Connection denied by rule!"); return ECONNABORTED; case 3: PutDbgStr(L"Network unreachable!"); return ENETUNREACH; case 4: PutDbgStr(L"Host unreachable!"); return EHOSTUNREACH; case 5: PutDbgStr(L"Connection refused!"); return ECONNREFUSED; case 6: PutDbgStr(L"TTL Expired!"); return ETIMEDOUT; case 7: PutDbgStr(L"Command not supported!"); return ECONNABORTED; case 8: PutDbgStr(L"Address type not supported!"); return ECONNABORTED; default: PutDbgStr(L"Unknown error!"); return ECONNABORTED; } } else { PutDbgStr(L"Message : SOCKS connect Success!"); } } else { PutDbgStr(L"Error : Method not supported!"); } //修改socket为非阻塞类型 nonBlock = 1; if(rc = ioctlsocket(s, FIONBIO, &nonBlock)) { PutDbgStr(L"Error %d : Set Non-Blocking Failure!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : Set Non-Blocking Successful!"); } PutDbgStr(L"Message : Success!"); return 0;

}

重写了 并导出 WSPStartup 函数 网上说TCP 的话,只需要 处理WSPConnect 就可以实现TCP 的代理 下面是代码

int WSPAPI WSPConnect( SOCKET s, const struct sockaddr name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno) { OutputDebugString(L"WSPConnect"); struct sockaddr_in sin; sin=(const struct sockaddr_in *)name; if(strcmp(inet_ntoa(sin.sin_addr), “127.0.0.1”) == 0) { return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno); } if (isSocks5())//是否需要代理 { TCHAR Msg[255]; wsprintf(Msg,L"…进程 %s 使用代理…",processname); OutputDebugString(Msg); return socksProxyEx(s, name, namelen); } else { TCHAR Msg[255]; wsprintf(Msg,L"进程 %s 走正常路线",processname); OutputDebugString(Msg); return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno); }

}

TCHAR sourceProcess[255] = L"TestIP.exe";//使用代理的进程名 //TCHAR sourceProcess[255] = L"ClinetTest.exe";//使用代理的进程名 TCHAR processname[255]; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if(ul_reason_for_call==DLL_PROCESS_ATTACH) { DWORD _processId = GetCurrentProcessId(); TCHAR Msg[1024]; GetModuleFileNameW(NULL,processname,500); wsprintf(Msg,L"进程ID:%d path %s",_processId,processname); OutputDebugString(Msg); }

return TRUE; }

//是否需要Socks5代理 bool isSocks5() { //判断processname 是否包含SourceProcess wstring _processname = processname; wstring _sourceProcess = sourceProcess;

size_t found = _processname.find(_sourceProcess); if (found!= wstring::npos) { return true; }else { return false; } }

每次建立长连接,连接服务器时,连接上立刻就断开了,很是不解,google 了很久,没找到答案,求大神们解惑啊

最新回复(0)