//**********************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winsock.h>
#define BufferSize 1024*8 // 8k Buffer
#define SOCKS4_GRANT 90
#define SOCKS4_REJECT 91 #pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"wsock32.lib") // Some Structures To Define
typedef struct
{
SOCKET ClientSocket;
}TSocks4Info; typedef struct
{
BYTE VN; // Version Number
BYTE CD; // Code Of Command
WORD wPort; // Remote Port
DWORD dwIP; // Remote IP
}Socks4Info;
// End Of Structure static CRITICAL_SECTION cs; // Function ProtoType Declaration
//------------------------------------------------------------------------------------------------------
DWORD GetRemoteAddressAndPort(char *HTTPBuffer, WORD *wPort);
BOOL SendSock4ID(SOCKET sSocket, BYTE Socks4RequestID);
DWORD WINAPI Socks4Thread(TSocks4Info *Sock4Info);
BOOL StartSocks4Proxy(unsigned int Sock4Port);
BOOL Init();
BOOL IsDigits(const char *String);
//------------------------------------------------------------------------------------------------------
// End Of Fucntion ProtoType Declaration // Main Function
int main(int argc,char *argv[])
{
unsigned int Sock4Port; // Define Sock4 Listening Port
if (argc != 2) // Require Two Arguments
{
printf("Usage: %s Port\n",argv[0]); // Display Usage
return -1; // Quit The Program
} if (!IsDigits(argv[1])) // Invalid Port Number
{
printf("Invalid Port\n"); // Display Error Message
return -1; // Quit The Program
} Sock4Port = atoi(argv[1]); // Convert String Into Unsigned Int Format,And Store Into Sock4Port
if (Sock4Port <= 0 || Sock4Port > 65535) // The Port Out Of Bound
{
printf("The Port Out Of Bound\n"); // Display Error Message
return -1; // Quit The Program
} if (!Init()) // Socket StartUP Fails
{
printf("Fail To StartUp\n"); // Display Error Message
return -1; // Quit The Program
} StartSocks4Proxy(Sock4Port); // Start The Proxy
WSACleanup(); // Clean UP
DeleteCriticalSection(&cs); // Delete Critical Section
return 0; // Quit The Program
}// End Of Main Method //------------------------------------------------------------------------------------
// Purpose: To Get The Remote IP And Port From The Buffer
// Return Type: DWORD
// Parameters:
// In: char *HTTPBuffer --> The HTTP Buffer Containing Remote IP And Port
// Out: DWORD *wPort --> Store The Remote Port And Returen To The Caller
//------------------------------------------------------------------------------------
DWORD GetRemoteAddressAndPort(char *HTTPBuffer, WORD *wPort)
{
// All Variable Stuff
DWORD dwIP, Socks4InfoSize = sizeof(Socks4Info);
struct hostent* pHostEnt;
DWORD dwIndex = 0;
char ServerAddress[BufferSize] = {0};
Socks4Info Socks4Request; memcpy(&Socks4Request, HTTPBuffer, Socks4InfoSize); // Get The Sock4 Structure
if ((Socks4Request.VN != 4) || (Socks4Request.CD != 1)) // Invalid Sock4 Request
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Invalid Socks 4 Request\n"); // Display Error Message
LeaveCriticalSection(&cs); // Leave Critical Section
return INADDR_NONE; // Return NULL Address
} *wPort = ntohs(Socks4Request.wPort); // Get The Remote Port
if ((Socks4Request.dwIP >> 8) == 0) // Some Shift Operation
{
strcpy(ServerAddress, &HTTPBuffer[Socks4InfoSize + strlen(&HTTPBuffer[Socks4InfoSize]) + 1]); // Get The Remote Address
dwIP = inet_addr(ServerAddress); // Is In Dot Form
if (dwIP == INADDR_NONE) // The Remote Address Is Not In Dot Form
{
pHostEnt = gethostbyname(ServerAddress); // Get The Dot Form
if (pHostEnt == NULL) // Fail To Get The IP
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Fail To Get Host By Name\n"); // Display Errory Message
LeaveCriticalSection(&cs); // Leave Critical Section
return INADDR_NONE; // Return NULL Address
}
dwIP = *((unsigned long *)pHostEnt->h_addr); // Get The Remote IP
}
return dwIP; // Return The Remote IP
}
return Socks4Request.dwIP; // We Already Get The Remote IP In The Sock4 Structure,Return It Then
}// End Of GetRemoteAddressAndPort() Method //------------------------------------------------------------------------------------
// Purpose: To Send The Sock4 Request
// Return Type: Boolean
// Parameters:
// 1.SOCKET sSocket --> The Socket That That ID Will Send To
// 2.BYTE SocketsRequestID --> Either Grand Or Reject
//------------------------------------------------------------------------------------
BOOL SendSock4ID(SOCKET sSocket, BYTE Socks4RequestID)
{
Socks4Info Socks4Request; // Define Variable
memset(&Socks4Request, 0, sizeof(Socks4Info)); // Reset Variable
Socks4Request.CD = Socks4RequestID;
return (send(sSocket, (char *)&Socks4Request, sizeof(Socks4Info), 0) != SOCKET_ERROR); // Return Send Success Or Failure
}// End Of SendSock4ID() Method //------------------------------------------------------------------------------------
// Purpose: To Handle All Sock4 Traffic
// Return Type: DWORD
// Parameters:
// 1.TSocks4Info *Sock4Info --> Sock4 Info
//------------------------------------------------------------------------------------
DWORD WINAPI Socks4Thread(TSocks4Info *Sock4Info)
{
// Variables Define And Reset
int iRet;
struct sockaddr_in SockAddrIn;
SOCKET MySocket, ClientSocket = Sock4Info->ClientSocket;
BOOL ClientFlag = FALSE, ServerFlag = FALSE;
int iClientLen = 0, iServerLen = 0;
BYTE byClientBuf[BufferSize], byServerBuf[BufferSize];
fd_set readfds;
DWORD dwRemoteIP;
WORD wRemotePort;
memset(byClientBuf, 0, BufferSize); iRet = recv(Sock4Info->ClientSocket, (char *)byClientBuf, BufferSize, 0); // Receive Data
if ((iRet == SOCKET_ERROR) || (iRet == 0)) // Fail To Receive Data
{
closesocket(Sock4Info->ClientSocket); // Close Socket
free(Sock4Info); // Free The Allocated Ram
return 1; // Return To The Caller
} byClientBuf[iRet] = 0;
if ((dwRemoteIP = GetRemoteAddressAndPort((char *)byClientBuf, &wRemotePort)) == INADDR_NONE) // Fail To Get Remote IP And Port
{
SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send The Reject ID
closesocket(Sock4Info->ClientSocket); // Close Socket
free(Sock4Info); // Free The Allocated Ram
return 1; // Return To The Caller
} MySocket = socket(AF_INET, SOCK_STREAM, 0); // Create A New Socket
if (MySocket == INVALID_SOCKET) // Fail To Create A New Socket
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Fail To Create Socket\n"); // Display Error Message
LeaveCriticalSection(&cs); // Leave Critical Section
SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send The Reject ID
closesocket(Sock4Info->ClientSocket); // Close Socket
free(Sock4Info); // Free The Allowed Ram
return 1; // Return To The Caller
} BOOL Val = 1;
if (setsockopt(MySocket, SOL_SOCKET, SO_KEEPALIVE, (char *)(&Val), sizeof(BOOL)) != 0) // Set Socket Option(KeepAlive) Fail
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Fail To Set Socket Option\n"); // Display Error Message
LeaveCriticalSection(&cs); // Leave Critical Section
SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send Reject ID
closesocket(Sock4Info->ClientSocket); // Close Socket
closesocket(MySocket); // Close Socket
free(Sock4Info); // Free Allocated Ram
return 1; // Return To The Caller
} // All Socket Stuff
SockAddrIn.sin_family = AF_INET;
SockAddrIn.sin_port = htons(wRemotePort);
SockAddrIn.sin_addr.s_addr = dwRemoteIP; iRet = connect(MySocket, (struct sockaddr *) &SockAddrIn, sizeof(SockAddrIn)); // Connect To The Remote IP
if (iRet == SOCKET_ERROR) // Fail To Connect
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Fail To Connect To %s\n",inet_ntoa(SockAddrIn.sin_addr)); // Display Error Message
LeaveCriticalSection(&cs); // Leave Critical Section
SendSock4ID(ClientSocket, SOCKS4_REJECT); // Send Reject ID
closesocket(ClientSocket); // Close Socket
closesocket(MySocket); // Close Socket
free(Sock4Info); // Free Allocated Ram
return 1; // Return To The Caller
} if (!SendSock4ID(ClientSocket, SOCKS4_GRANT)) // We Fail To Send The Grant ID
{
EnterCriticalSection(&cs); // Enter Critical Section
printf("Fail To Send Grant ID\n"); // Display Error Message
LeaveCriticalSection(&cs); // Leave Critical Section
closesocket(Sock4Info->ClientSocket); // Close Socket
closesocket(MySocket); // Close Socket
free(Sock4Info); // Free Allocated Ram
return 1; // Return To The Caller
} EnterCriticalSection(&cs); // Enter Critical Section
printf("Connected to: %s:%d ThreadID:%X\n",inet_ntoa(SockAddrIn.sin_addr), wRemotePort, GetCurrentThreadId()); // Display Successful Message
LeaveCriticalSection(&cs); // Leave Critical Section while(TRUE) // Sock4 Traffic Starts
{
FD_ZERO(&readfds); // Reset The Readable Socket Flag
FD_SET(MySocket, &readfds); // Set MySocket As Readable
FD_SET(ClientSocket, &readfds); //Send ClientSocket As Readable
iRet = select(0, &readfds, NULL, NULL, NULL); // Select Any Readable Socket
if (iRet == SOCKET_ERROR) // We Fail To Get Any Readable Socket
{
break; // Leave The Loop
}
// Below Are All About Send And Receive Stuff,Pretty Tedious To Explain.Read It YouSelf
if (iClientLen < BufferSize)
{
if ((FD_ISSET(ClientSocket, &readfds)) && (!ClientFlag))
{
iRet = recv(ClientSocket, (char *)&byClientBuf[iClientLen], BufferSize-iClientLen, 0);
if (iRet == 0 || iRet == SOCKET_ERROR)
{
break;
}
ClientFlag = TRUE;
iClientLen += iRet;
}
}
if (ClientFlag)
{
iRet = send(MySocket, (char *)byClientBuf, iClientLen, 0);
if (iRet == SOCKET_ERROR)
{
break;
}
ClientFlag = FALSE;
iClientLen = 0;
}
if (iServerLen < BufferSize)
{
if ((FD_ISSET(MySocket, &readfds)) && (!ServerFlag))
{
iRet = recv(MySocket, (char *)&byServerBuf[iServerLen], BufferSize-iServerLen, 0);
if (iRet == 0 || iRet == SOCKET_ERROR)
{
break;
}
ServerFlag = TRUE;
iServerLen += iRet;
}
}
if (ServerFlag)
{
iRet = send(ClientSocket, (char *)byServerBuf, iServerLen, 0);
if (iRet == SOCKET_ERROR)
{
break;
}
ServerFlag = FALSE;
iServerLen = 0;
}
}
closesocket(MySocket); // Close Socket
closesocket(ClientSocket); // Close Socket
free(Sock4Info); // Free Allocated Ram
return 0; // Return To The Caller
}// End Of Socks4Thread() Method //------------------------------------------------------------------------------------
// Purpose: To Start The Socks4 Proxy
// Return Type: Boolean
// Parameters:
// 1.unsigned int Sock4Port --> The Port Listening On
//------------------------------------------------------------------------------------
BOOL StartSocks4Proxy(unsigned int Sock4Port)
{
// All Variables Define
SOCKADDR_IN saServer;
int iRet;
SOCKET ListenSocket; // socket to listen
SOCKET ClientSocket; // Client socket
DWORD dwThreadID;
TSocks4Info *Sock4Info; saServer.sin_family = AF_INET; // Address Family(Internet)
saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock Assign Address
saServer.sin_port = htons(Sock4Port); // Port Number ListenSocket = socket( AF_INET, SOCK_STREAM,IPPROTO_TCP); // Create A New Socket
if (ListenSocket == INVALID_SOCKET) // Fail To Create A New Socket
{
printf("Fail To Create Listening Socket\n"); // Display Error Message
return FALSE; // Return False
} iRet = bind(ListenSocket, (LPSOCKADDR)&saServer, sizeof(struct sockaddr)); // Bind The Socket
if (iRet == SOCKET_ERROR) // Fail To Bind
{
printf("Fail To Bind Socket\n"); // Display Error Message
closesocket(ListenSocket); // Close Socket
return FALSE; // Return False
} iRet = listen(ListenSocket, SOMAXCONN); // Listen On The Socket
if (iRet == SOCKET_ERROR) // Fail To Listen
{
printf("Fail To Listen On The Socket\n"); // Display ErrorMessage
closesocket(ListenSocket); // Close Socket
return FALSE; // Return False
} printf("Socks 4 Server Started On Port %d\n",Sock4Port); // The Sock4 Proxy Is Started Successfully while(TRUE)
{
ClientSocket = accept(ListenSocket, NULL, NULL); // Accept Incoming Connection
if (ClientSocket == SOCKET_ERROR) // Fail To Accept Connection
{
break; // Leave The Loop
} BOOL Val = 1;
if (setsockopt(ClientSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)(&Val), sizeof(BOOL)) != 0) // Set The Socket As Keepalive Fail
{
closesocket(ClientSocket); // Close The Socket
continue; // Begin A New Loop
} if ((Sock4Info = (TSocks4Info *)malloc(sizeof(TSocks4Info))) == NULL) // Allocate Ram Fail
{
closesocket(ClientSocket); // Close Socket
closesocket(ListenSocket); // Close Socket
return FALSE; // Return False
} Sock4Info->ClientSocket = ClientSocket; // Get The Socket
if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Socks4Thread, (LPVOID)Sock4Info, 0, &dwThreadID) == NULL) // Fail To Create A New Thread
{
closesocket(ClientSocket); // Close Socket
continue; // Begin A New Loop
}
} closesocket(ListenSocket); // Close Socket
return TRUE; // Return To The Caller
}// End Of StartSocks4Proxy() Method //-------------------------------------------------------------------------
// Purpose: To Initize Socket
// Return Type: Boolean
// Parameters: NULL
// This Is Too Simple,I Won't Comment It
//-------------------------------------------------------------------------
BOOL Init()
{
WSADATA data;
WORD ver; ver = MAKEWORD(2,2);
if (WSAStartup( ver, &data ) != 0 )
{
return FALSE;
}
InitializeCriticalSection(&cs);
return TRUE;
}// End Of Init() Method //-------------------------------------------------------------------------
// Purpose: To Check Whether A String Is All Digits
// Return Type: Boolean
// Parameters: cosnt char *String --> The String To Be Checked
//-------------------------------------------------------------------------
BOOL IsDigits(const char *String)
{
unsigned int i = 0;
unsigned int StringLength = strlen(String); // Get The Length Of The String //One By One To Check Every Character
for (i = 0;i < StringLength;i++)
{
if (String[i] < 48 || String[i] > 57) // The Character Is Not One Of 0 To 9
{
return FALSE; // Return False
}
}
return TRUE; // Return True
}// End Of IsDigits() Method
// End Of File

最新文章

  1. 自动生成V字型
  2. 设置float之后vertical-align失效
  3. DotNetBar for Windows Forms 12.5.0.2_冰河之刃重打包版原创发布-带官方示例程序版
  4. [题解]noip2016普及组题解和心得
  5. phpcms v9 数据源
  6. 实例学习Backbone.js(一)
  7. url重写技术
  8. 将spfile存储在ASM中
  9. Hadoop的调度器总结
  10. 多态VI的创建
  11. 在网上浏览.NET的所有代码,并且让你的Visual Studio的go to definition(F12)指向在线代码
  12. SWFObject文件上传使用记录
  13. Run Loop简介
  14. 【Java每日一题】20170317
  15. pandas中遍历dataframe的每一个元素
  16. 在v-html中,js 正则表达式清除字符串里的style属性
  17. 海康威视(iOS集成)
  18. JBPM工作流(二)——数据库表说明
  19. Hive常用操作命令
  20. 添加dubbo.xsd的方法

热门文章

  1. js一些问题总结
  2. python操作postgresql数据库
  3. 线程高级应用-心得6-java5线程并发库中同步工具类(synchronizers),新知识大用途
  4. String.join()方法的使用
  5. haskell rust相关文章
  6. 转 java 类 单例
  7. opencv249配置
  8. 任务调度quartz
  9. SVM中图像常用的HOG特征描述及实现
  10. Hive优化