最近幫一個朋友實現sockscap的socks V5代理功能,sockscap貌似是通過API HOOK實現,一開始我便嘗試這種方式,遇到各種麻煩的問題,還是用SPI的LSP來試試吧。
SPI的出現其實就是微軟為了方便程序員對網絡API的各種HOOK,從而省去一些麻煩,然而相對的也會增加不少問題。對於SPI中的LSP這種分層的結構,可以很好的使用強盜手法將自己當作老大放在最上層,但是,如果有其他程序也使用同樣的手法,那么就會產生沖突了。
好吧進入正題。。。
一、LSP的安裝,先拋開socks代理不說
1、構造自己的LSP,並安裝之;
2、遍歷已有 服務提供者,找到剛安裝的LSP入口ID;
3、構造自己的協議鏈,並安裝之;
4、對所有協議鏈進行排序,並將我們的協議鏈放到最上面。
二、LSP的編寫
主要操作都在WSPStartup中,其他WSP函數就是對原函數的HOOK,詳情看下面代碼。
MSDN有完整LSP代碼的下載:
ftp://ftp.microsoft.com/bussys/WinSock/winsock2/layered.zip
同時,網上也有一些源代碼,與MSDN代碼相比,基本一樣,只是在LSP安裝的第一步有所不同,MSDN代碼是手工構造LSP,而網上許多代碼都是通過拷貝系統已有LSP進行對自己的LSP構造。
下面代碼來自網上:
INST_LSP.Cpp
#define UNICODE #define _UNICODE #include <Ws2spi.h> #include <Sporder.h> // 定義了WSCWriteProviderOrder函數 #include <windows.h> #include <stdio.h> #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "Rpcrt4.lib") // 實現了UuidCreate函數 // 要安裝的LSP的硬編碼,在移除的時候還要使用它 GUID ProviderGuid = {0xd3c21122, 0x85e1, 0x48f3, {0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef} }; LPWSAPROTOCOL_INFOW GetProvider(LPINT lpnTotalProtocols) { DWORD dwSize = 0; int nError; LPWSAPROTOCOL_INFOW pProtoInfo = NULL; // 取得需要的長度 if (::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError) == SOCKET_ERROR) { if (nError != WSAENOBUFS) return NULL; } pProtoInfo = (LPWSAPROTOCOL_INFOW)::GlobalAlloc(GPTR, dwSize); *lpnTotalProtocols = ::WSCEnumProtocols(NULL, pProtoInfo, &dwSize, &nError); return pProtoInfo; } void FreeProvider(LPWSAPROTOCOL_INFOW pProtoInfo) { ::GlobalFree(pProtoInfo); } BOOL InstallProvider(WCHAR *pwszPathName) { WCHAR wszLSPName[] = L"ZetsinLSP"; LPWSAPROTOCOL_INFOW pProtoInfo; int nProtocols; WSAPROTOCOL_INFOW OriginalProtocolInfo[3]; DWORD dwOrigCatalogId[3]; int nArrayCount = 0; DWORD dwLayeredCatalogId; // 我們分層協議的目錄ID號 int nError; // 找到我們的下層協議,將信息放入數組中 // 枚舉所有服務程序提供者 pProtoInfo = GetProvider(&nProtocols); BOOL bFindUdp = FALSE; BOOL bFindTcp = FALSE; BOOL bFindRaw = FALSE; for (int i=0; i<nProtocols; i++) { if (pProtoInfo[i].iAddressFamily == AF_INET) { if (!bFindUdp && pProtoInfo[i].iProtocol == IPPROTO_UDP) { memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW)); OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId; bFindUdp = TRUE; } if (!bFindTcp && pProtoInfo[i].iProtocol == IPPROTO_TCP) { memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW)); OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId; bFindTcp = TRUE; } if (!bFindRaw && pProtoInfo[i].iProtocol == IPPROTO_IP) { memcpy(&OriginalProtocolInfo[nArrayCount], &pProtoInfo[i], sizeof(WSAPROTOCOL_INFOW)); OriginalProtocolInfo[nArrayCount].dwServiceFlags1 = OriginalProtocolInfo[nArrayCount].dwServiceFlags1 & (~XP1_IFS_HANDLES); dwOrigCatalogId[nArrayCount++] = pProtoInfo[i].dwCatalogEntryId; bFindRaw = TRUE; } } } // 安裝我們的分層協議,獲取一個dwLayeredCatalogId // 隨便找一個下層協議的結構復制過來即可 WSAPROTOCOL_INFOW LayeredProtocolInfo; memcpy(&LayeredProtocolInfo, &OriginalProtocolInfo[0], sizeof(WSAPROTOCOL_INFOW)); // 修改協議名稱,類型,設置PFL_HIDDEN標志 wcscpy_s(LayeredProtocolInfo.szProtocol, wszLSPName); LayeredProtocolInfo.ProtocolChain.ChainLen = LAYERED_PROTOCOL; // 0; LayeredProtocolInfo.dwProviderFlags |= PFL_HIDDEN; // 安裝 if (::WSCInstallProvider(&ProviderGuid, pwszPathName, &LayeredProtocolInfo, 1, &nError) == SOCKET_ERROR) { printf("%d", nError); return FALSE; } // 重新枚舉協議,獲取分層協議的目錄ID號 FreeProvider(pProtoInfo); pProtoInfo = GetProvider(&nProtocols); for (int i=0; i<nProtocols; i++) { if (memcmp(&pProtoInfo[i].ProviderId, &ProviderGuid, sizeof(ProviderGuid)) == 0) { dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId; break; } } // 安裝協議鏈 // 修改協議名稱,類型 WCHAR wszChainName[WSAPROTOCOL_LEN + 1]; for (int i=0; i<nArrayCount; i++) { swprintf(wszChainName, L"%ws over %ws", wszLSPName, OriginalProtocolInfo[i].szProtocol); wcscpy_s(OriginalProtocolInfo[i].szProtocol, wszChainName); if (OriginalProtocolInfo[i].ProtocolChain.ChainLen == 1) { OriginalProtocolInfo[i].ProtocolChain.ChainEntries[1] = dwOrigCatalogId[i]; } else { for (int j = OriginalProtocolInfo[i].ProtocolChain.ChainLen; j>0; j--) { OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j] = OriginalProtocolInfo[i].ProtocolChain.ChainEntries[j-1]; } } OriginalProtocolInfo[i].ProtocolChain.ChainLen ++; OriginalProtocolInfo[i].ProtocolChain.ChainEntries[0] = dwLayeredCatalogId; } // 獲取一個Guid,安裝之 GUID ProviderChainGuid; if (::UuidCreate(&ProviderChainGuid) == RPC_S_OK) { if (::WSCInstallProvider(&ProviderChainGuid, pwszPathName, OriginalProtocolInfo, nArrayCount, &nError) == SOCKET_ERROR) { return FALSE; } } else return FALSE; // 重新排序Winsock目錄,將我們的協議鏈提前 // 重新枚舉安裝的協議 FreeProvider(pProtoInfo); pProtoInfo = GetProvider(&nProtocols); PDWORD dwIds = (PDWORD)malloc(sizeof(DWORD) * nProtocols); int nIndex = 0; // 添加我們的協議鏈 for (int i=0; i<nProtocols; i++) { if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) && (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId)) dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId; } // 添加其它協議 for (int i=0; i<nProtocols; i++) { if ((pProtoInfo[i].ProtocolChain.ChainLen <= 1) || (pProtoInfo[i].ProtocolChain.ChainEntries[0] != dwLayeredCatalogId)) dwIds[nIndex++] = pProtoInfo[i].dwCatalogEntryId; } // 重新排序Winsock目錄 if ((nError = ::WSCWriteProviderOrder(dwIds, nIndex)) != ERROR_SUCCESS) { return FALSE; } FreeProvider(pProtoInfo); return TRUE; } BOOL RemoveProvider() { LPWSAPROTOCOL_INFOW pProtoInfo; int nProtocols; DWORD dwLayeredCatalogId; // 根據Guid取得分層協議的目錄ID號 pProtoInfo = GetProvider(&nProtocols); int nError; int i; for (i=0; i<nProtocols; i++) { if (memcmp(&ProviderGuid, &pProtoInfo[i].ProviderId, sizeof(ProviderGuid)) == 0) { dwLayeredCatalogId = pProtoInfo[i].dwCatalogEntryId; break; } } if (i < nProtocols) { // 移除協議鏈 for (i=0; i<nProtocols; i++) { if ((pProtoInfo[i].ProtocolChain.ChainLen > 1) && (pProtoInfo[i].ProtocolChain.ChainEntries[0] == dwLayeredCatalogId)) { ::WSCDeinstallProvider(&pProtoInfo[i].ProviderId, &nError); } } // 移除分層協議 ::WSCDeinstallProvider(&ProviderGuid, &nError); } else return FALSE; return TRUE; } void main(int argc, char *argv[]) { char *ptr; //if(argc==2) { ptr = argv[1]; while (*ptr) *ptr++ = tolower(*ptr); int test; scanf("%d", &test); if (test == 1) //if(strcmp(argv[1], "-install")==0) { TCHAR szPathName[256]; TCHAR* p; if (::GetFullPathName(L"LSP.dll", 256, szPathName, &p) != 0) { if (InstallProvider(szPathName)) { printf(" Install successully. /n"); return; } } printf(" Install failed. /n"); return; } else //else if(strcmp(argv[1],"-remove")==0) { if (RemoveProvider()) printf(" Deinstall successully. /n"); else printf(" Deinstall failed. /n"); return; } } printf(" Usage: Instlsp [ -install │ -remove ] /n"); }
LSP.Cpp
#define UNICODE #define _UNICODE #include <ws2spi.h> #include <errno.h> #include <fstream> #pragma comment(lib,"Ws2_32.lib") GUID filterguid = {0xd3c21122, 0x85e1, 0x48f3, {0x9a,0xb6,0x23,0xd9,0x0c,0x73,0x07,0xef} }; LPWSAPROTOCOL_INFOW ProtoInfo=NULL; WSPPROC_TABLE NextProcTable; DWORD ProtoInfoSize=0; int TotalProtos=0; // 輸出函數 int PutDbgStr(LPCTSTR lpFmt, ...) { TCHAR Msg[1024]; int len=wvsprintf(Msg,lpFmt,va_list(1+&lpFmt)); OutputDebugString(Msg); return len; } // 獲取各種值 BOOL GetLSP() { int errorcode; ProtoInfo=NULL; ProtoInfoSize=0; TotalProtos=0; if (WSCEnumProtocols(NULL,ProtoInfo,&ProtoInfoSize,&errorcode)==SOCKET_ERROR) { if (errorcode!=WSAENOBUFS) { PutDbgStr(L"First WSCEnumProtocols Error!"); return FALSE; } } if ((ProtoInfo=(LPWSAPROTOCOL_INFOW)GlobalAlloc(GPTR,ProtoInfoSize))==NULL) { PutDbgStr(L"GlobalAlloc Error!"); return FALSE; } if ((TotalProtos=WSCEnumProtocols(NULL,ProtoInfo,&ProtoInfoSize,&errorcode))==SOCKET_ERROR) { PutDbgStr(L"Second WSCEnumProtocols Error!"); return FALSE; } return TRUE; } // 釋放內存 void FreeLSP() { GlobalFree(ProtoInfo); } // DLL入口函數 BOOL WINAPI DllMain(HINSTANCE hmodule, DWORD reason, LPVOID lpreserved) { TCHAR processname[MAX_PATH]; if (reason==DLL_PROCESS_ATTACH) { GetModuleFileName(NULL,processname,MAX_PATH); PutDbgStr(L"%s Loading IPFilter ...", processname); } return TRUE; } /********************************* 改寫WSP函數,只有WSPConnect被改寫成調用socksProxy函數,其它的直接調用下層WSP函數 ****************************************/ //WSPConnect int WSPAPI WSPConnect( SOCKET s, const struct sockaddr *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno) { return NextProcTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno); } } //WSPSocket SOCKET WINAPI WSPSocket( __in int af, __in int type, __in int protocol, __in LPWSAPROTOCOL_INFO lpProtocolInfo, __in GROUP g, DWORD dwFlags, __out LPINT lpErrno ) { PutDbgStr(L"WSPSocket"); return NextProcTable.lpWSPSocket(af, type, protocol, lpProtocolInfo, g, dwFlags, lpErrno); } //WSPBind int WINAPI WSPBind( __in SOCKET s, __in const struct sockaddr *name, __in int namelen, __out LPINT lpErrno ) { PutDbgStr(L"WSPBind"); return NextProcTable.lpWSPBind(s, name, namelen, lpErrno); } //WSPSend int WINAPI WSPSend( __in SOCKET s, __in LPWSABUF lpBuffers, __in DWORD dwBufferCount, __out LPDWORD lpNumberOfBytesSent, __in DWORD dwFlags, __in LPWSAOVERLAPPED lpOverlapped, __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, __in LPWSATHREADID lpThreadId, __out LPINT lpErrno ) { PutDbgStr(L"WSPSend"); return NextProcTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); } //WSPSendTo int WINAPI WSPSendTo( __in SOCKET s, __in LPWSABUF lpBuffers, __in DWORD dwBufferCount, __out LPDWORD lpNumberOfBytesSent, __in DWORD dwFlags, __in const struct sockaddr *lpTo, __in int iTolen, __in LPWSAOVERLAPPED lpOverlapped, __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, __in LPWSATHREADID lpThreadId, __out LPINT lpErrno ) { PutDbgStr(L"WSPSendTo"); return NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); } //WSPRecv int WINAPI WSPRecv( __in SOCKET s, __inout LPWSABUF lpBuffers, __in DWORD dwBufferCount, __out LPDWORD lpNumberOfBytesRecvd, __inout LPDWORD lpFlags, __in LPWSAOVERLAPPED lpOverlapped, __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, __in LPWSATHREADID lpThreadId, __out LPINT lpErrno ) { PutDbgStr(L"WSPRecv"); return NextProcTable.lpWSPRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); } //WSPRecvFrom int WINAPI WSPRecvFrom( __in SOCKET s, __inout LPWSABUF lpBuffers, __in DWORD dwBufferCount, __out LPDWORD lpNumberOfBytesRecvd, __inout LPDWORD lpFlags, __out struct sockaddr *lpFrom, __inout LPINT lpFromlen, __in LPWSAOVERLAPPED lpOverlapped, __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, __in LPWSATHREADID lpThreadId, __inout LPINT lpErrno ) { PutDbgStr(L"WSPRecvFrom"); return NextProcTable.lpWSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); } //WSPStartup int WSPAPI WSPStartup( WORD wversionrequested, LPWSPDATA lpwspdata, LPWSAPROTOCOL_INFOW lpProtoInfo, WSPUPCALLTABLE upcalltable, LPWSPPROC_TABLE lpproctable ) { PutDbgStr(L"IPFilter WSPStartup ..."); int i; int errorcode; int filterpathlen; DWORD layerid=0; DWORD nextlayerid=0; TCHAR *filterpath; HINSTANCE hfilter; LPWSPSTARTUP wspstartupfunc=NULL; if (lpProtoInfo->ProtocolChain.ChainLen<=1) { PutDbgStr(L"ChainLen<=1"); return FALSE; } GetLSP(); for (i=0;i<TotalProtos;i++) { if (memcmp(&ProtoInfo[i].ProviderId,&filterguid,sizeof(GUID))==0) { layerid=ProtoInfo[i].dwCatalogEntryId; break; } } for (i=0;i<lpProtoInfo->ProtocolChain.ChainLen;i++) { if (lpProtoInfo->ProtocolChain.ChainEntries[i]==layerid) { nextlayerid=lpProtoInfo->ProtocolChain.ChainEntries[i+1]; break; } } filterpathlen=MAX_PATH; filterpath=(TCHAR*)GlobalAlloc(GPTR,filterpathlen); for (i=0;i<TotalProtos;i++) { if (nextlayerid==ProtoInfo[i].dwCatalogEntryId) { if (WSCGetProviderPath(&ProtoInfo[i].ProviderId,filterpath,&filterpathlen,&errorcode)==SOCKET_ERROR) { PutDbgStr(L"WSCGetProviderPath Error!"); return WSAEPROVIDERFAILEDINIT; } break; } } if (!ExpandEnvironmentStrings(filterpath,filterpath,MAX_PATH)) { PutDbgStr(L"ExpandEnvironmentStrings Error!"); return WSAEPROVIDERFAILEDINIT; } if ((hfilter=LoadLibrary(filterpath))==NULL) { PutDbgStr(L"LoadLibrary Error!"); return WSAEPROVIDERFAILEDINIT; } if ((wspstartupfunc=(LPWSPSTARTUP)GetProcAddress(hfilter,"WSPStartup"))==NULL) { PutDbgStr(L"GetProcessAddress Error!"); return WSAEPROVIDERFAILEDINIT; } if ((errorcode=wspstartupfunc(wversionrequested,lpwspdata,lpProtoInfo,upcalltable,lpproctable))!=ERROR_SUCCESS) { PutDbgStr(L"wspstartupfunc Error!"); return errorcode; } NextProcTable=*lpproctable;// 保存原來的入口函數表 //改寫函數 lpproctable->lpWSPSendTo = WSPSendTo; lpproctable->lpWSPSend = WSPSend; lpproctable->lpWSPBind = WSPBind; lpproctable->lpWSPConnect = WSPConnect; lpproctable->lpWSPRecv = WSPRecv; lpproctable->lpWSPRecvFrom = WSPRecvFrom; lpproctable->lpWSPSocket = WSPSocket; FreeLSP(); return 0; }
關於SOCKS V5代理,下回修改文章再貼上。
zetsin@gmail.com
2011-04-30 20:57:02
要說SOCKS V5代理,其實非常簡單,細讀一遍RFC1928文檔就OK了,文檔地址如下:
http://www.ietf.org/rfc/rfc1928.txt
如果需要遠程解析域名,則將上述文檔中第四點的 ATYP 置為 /X03
最后將前面所寫的LSP與SOCKS V5代理結合,TCP的話只要攔截WSPCONNECT函數,UDP因為不是面向連接的所以只要攔截WSPSENDTO即可,具體代碼如下:
// 連接socks5代理
int socksProxy(SOCKET s, const struct sockaddr *name, int namelen) { int rc = 0; // 這里應該先保存下socket的阻塞/非阻塞類型,在最后面跟據這里的值將它還原,但是不知道怎樣獲取此類型 // 修改socket為阻塞類型 if (rc = WSAEventSelect(s, 0, NULL))//這一個可以不用執行 { PutDbgStr(L"Error %d : WSAEventSelect Failure!", WSAGetLastError()); } else { PutDbgStr(L"Message : WSAEventSelect successfully!"); } 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("76.120.160.122"); //代理服務器地址,從無憂代理網獲取的,質量還行,不過只能用幾天,發現連不上的話重新獲取吧 serveraddr.sin_port = htons(27977); // 端口號 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' 沒有可以接受的方法*/ if ((rc = recv(s, verstring, 257, 0)) < 0) { PutDbgStr(L"Error %d : attempting to receive SOCKS method negotiation reply!", WSAGetLastError()); return rc; } else { PutDbgStr(L"Message : receive SOCKS method negotiation reply successfully!"); } if (rc < 2)//返回2字節 { PutDbgStr(L"Error : Short reply from SOCKS server!"); rc = ECONNREFUSED; return rc; } else { PutDbgStr(L"Message : reply from SOCKS server larger than 2"); } // 代理服務器選擇方法 // 判斷我們的方法是否可行 if (verstring[1] == '/xff') { PutDbgStr(L"Error : SOCKS server refused authentication methods!"); rc = ECONNREFUSED; return rc; } else if (verstring[1] == '/x02')// 方法2 : 用戶名/密碼 { //另外處理 PutDbgStr(L"Error : SOCKS server need username/password!"); } else if (verstring[1] == '/x00')// 方法0: 不需要認證 { //發送SOCKS請求 //VER CMD RSV ATYP DST.ADDR DST.PROT //1 1 X'00' 1 Variable 2 /* VER 協議版本: X'05' · CMD · CONNECT:X'01' · BIND:X'02' · UDP ASSOCIATE:X'03' · RSV 保留 · ATYP 后面的地址類型 · IPV4:X'01' · 域名:X'03' · IPV6:X'04'' · DST.ADDR 目的地址 · DST.PORT 以網絡字節順序出現的端口號 SOCKS服務器會根據源地址和目的地址來分析請求,然后根據請求類型返回一個或多個應答。*/ 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!"); } //應答 //VER REP RSV ATYP BND.ADDR BND.PORT //1 1 X'00' 1 Variable 2 /*VER 協議版本: X'05' · REP 應答字段: · X'00' 成功 · X'01' 普通的SOCKS服務器請求失敗 · X'02' 現有的規則不允許的連接 · X'03' 網絡不可達 · X'04' 主機不可達 · X'05' 連接被拒 · X'06' TTL超時 · X'07' 不支持的命令 · X'08' 不支持的地址類型 · X'09' - X'FF' 未定義 · RSV 保留 · ATYP 后面的地址類型 · IPV4:X'01' · 域名:X'03' · IPV6:X'04' · BND.ADDR 服務器綁定的地址 · BND.PORT 以網絡字節順序表示的服務器綁定的段口 標識為RSV的字段必須設為X'00'。*/ 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; } //WSPConnect int WSPAPI WSPConnect( SOCKET s, const struct sockaddr *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno) { PutDbgStr(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); } return socksProxy(s, name, namelen); } //WSPSendTo int WINAPI WSPSendTo( __in SOCKET s, __in LPWSABUF lpBuffers, __in DWORD dwBufferCount, __out LPDWORD lpNumberOfBytesSent, __in DWORD dwFlags, __in const struct sockaddr *lpTo, __in int iTolen, __in LPWSAOVERLAPPED lpOverlapped, __in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, __in LPWSATHREADID lpThreadId, __out LPINT lpErrno ) { PutDbgStr(L"WSPSendTo"); struct sockaddr_in sin; sin=*(const struct sockaddr_in *)name; if (strcmp(inet_ntoa(sin.sin_addr), "127.0.0.1") == 0) { return NextProcTable.lpWSPSendTo(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo, iTolen, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno); } return socksProxy(s, lpTo, iTolen); }
zetsin@gmail.com
2011-05-02 18:25:39