//**********************************************************************
#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

基于SOCK4网络协议的代理服务器端代码示例的更多相关文章

  1. 基于RabbltMQ延迟插件实现延迟队列代码示例

    上一篇文章写了docker安装RabbitMQ及延迟插件的安装,这篇的话是基于RabbitMQ延迟插件实现延迟队列的示例 那么废话不多说 直接上代码!! 首先创建延迟队列配置类 DelayedQueu ...

  2. GAN生成式对抗网络(二)——tensorflow代码示例

    代码实现 当初学习时,主要学习的这个博客 https://xyang35.github.io/2017/08/22/GAN-1/ ,写的挺好的. 本文目的,用GAN实现最简单的例子,帮助认识GAN算法 ...

  3. Netty中解码基于分隔符的协议和基于长度的协议

    在使用Netty的过程中,你将会遇到需要解码器的基于分隔符和帧长度的协议.本节将解释Netty所提供的用于处理这些场景的实现. 基于分隔符的协议 基于分隔符的(delimited)消息协议使用定义的字 ...

  4. c++ 网络编程(四) LINUX/windows下 socket 基于I/O复用的服务器端代码 解决多进程服务端创建进程资源浪费问题

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9613861.html 好了,继上一篇说到多进程服务端也是有缺点的,每创建一个进程就代表大量的运 ...

  5. NETPLIER : 一款基于概率的网络协议逆向工具(一)理论

    本文系原创,转载请说明出处:信安科研人 关注微信公众号 信安科研人 获取更多网络安全学术技术资讯 今日介绍一篇发表在2021 NDSS会议上的一项有关协议逆向的工作: @ 目录 1 网络协议逆向工程简 ...

  6. 基于TCP/IP协议的C++网络编程(API函数版)

    源代码:http://download.csdn.net/detail/nuptboyzhb/4169959 基于TCP/IP协议的网络编程 定义变量——获得WINSOCK版本——加载WINSOCK库 ...

  7. Raknet是一个基于UDP网络传输协议的C++网络库(还有一些其它库,比如nanomsg,fastsocket等等)

    Raknet是一个基于UDP网络传输协议的C++网络库,允许程序员在他们自己的程序中实现高效的网络传输服务.通常情况下用于游戏,但也可以用于其它项目. Raknet有以下好处: 高性能 在同一台计算机 ...

  8. EPF:一种基于进化、协议感知和覆盖率引导的网络协议模糊测试框架

    本文系原创,转载请说明出处:from 信安科研人 目录 实验 工具的安装 1.安装AFL++ 2.安装epf 对IEC104协议库进行fuzz 实验准备 使用AFL++中的编译器插桩 开始fuzz 原 ...

  9. 网络协议 21 - RPC 协议(中)- 基于 JSON 的 RESTful 接口协议

        上一节我们了解了基于 XML 的 SOAP 协议,SOAP 的 S 是啥意思来着?是 Simple,但是好像一点儿都不简单啊! 传输协议问题     对于 SOAP 来讲,比如我创建一个订单, ...

随机推荐

  1. sql概要

    sql(structured query language) 1.比较运算符一共有六种,分别为等于(=),小于(<),大于(>),小于或等于(<=),大于或等于(>=)以及不等 ...

  2. 选择列表控件的使用(PickList)

    需要下载picklist.dll类库配合使用 <%@ Register TagPrefix="cc1" Namespace="PickListControl&quo ...

  3. RedHat 7配置yum源

    卸载自带的yum软件包 rpm -e yum-utils--.el7.noarch --nodeps rpm -e yum-rhn-plugin--.el7.noarch --nodeps rpm - ...

  4. 有趣的JavaScript小程序

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Java 默认/缺省 内存大小,如果没有 -Xms -Xmx

    命令 java -XX:+PrintCommandLineFlags -version 会直观的输出下面默认值 -XX:InitialHeapSize=16336768 -XX:MaxHeapSize ...

  6. 转!!常用的4种动态网页技术—CGI、ASP、JSP、PHP

    1.CGI   CGI(Common Gateway Interface,公用网关接口)是较早用来建立动态网页的技术.当客户端向Web服务器上指定的CGI程序发出请求时,Web服务器会启动一个新的进程 ...

  7. Embed对象

    1.EMBED 元素 | embed 对象 http://www.jb51.net/shouce/dhtml/objects/EMBED.html 2. 3.

  8. android程序中界面太大太长太宽如何滚动?

    使用ScrollView即可. ScrollView只能容纳一个直接的子控件. 在Android中编写布局一般会用到scrollview嵌套LinearLayout,使页面可以自适应其高度.但是有的机 ...

  9. 在多线程环境下使用HttpWebRequest或者调用Web Service(连接报超时问题)

    .net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制,这个限制在桌面操作系统如 windows xp , windows  7 下默认是2,在服务器操作 ...

  10. 利用php CI force_download($filename, $data) 下载.csv 文件解决文件名乱码,文件内容乱码

    利用php CI force_download($filename, $data) 下载.csv 文件解决文件名乱码,文件内容乱码 2014-07-31 12:53 1047人阅读 评论(0) 收藏  ...