- / Author: LZX
- // E-mail: LZX@qq.com
- // Version: V2.0 (AsyncMode)
- // Purpose: A Proxy works on one port and supports SOCKS v4 && v5 && Http protocol.
- // The socks proxy request has not supported BIND method yet.
- // The Http proxy supports three methods:GET(HEAD) POST CONNECT.
- // Test PlatForm: WinXP SP2
- // Compiled On: VC++ 6.0
- #include <winsock2.h>
- #include <stdio.h>
- #pragma comment(lib,"ws2_32")
- #define BUFSIZE 10240
- #define WM_SOCKET (WM_USER+1)
- #define WM_DNS (WM_USER+2)
- #define WM_HOSTRESOLVED (WM_USER+3)
- #define WM_HOSTFAILED (WM_USER+4)
- #define MAX_HOSTNAME 256
- #define LISTENPORT 8080
- #define HEADLEN 7
- char ErrorMsg[]="Http/1.1 403 Forbidden\r\n\r\n<body><h1>403 Forbidden</h1></body>";
- char ConnectionEstablished[]="HTTP/1.0 200 OK\r\n\r\n";
- char Username[256]="\0";
- char Password[256]="\0";
- struct Socks4Req
- {
- BYTE Ver;
- BYTE REP;
- WORD wPort;
- DWORD dwIP;
- BYTE other[1];
- };
- struct Socks5Req
- {
- BYTE Ver;
- BYTE nMethods;
- BYTE Methods[255];
- };
- struct AuthReq
- {
- BYTE Ver;
- BYTE Ulen;
- BYTE UserPass[1024];
- };
- typedef struct
- {
- BYTE Ver; // Version Number
- BYTE CMD; // 0x01==TCP CONNECT,0x02==TCP BIND,0x03==UDP ASSOCIATE
- BYTE RSV;
- BYTE ATYP;
- BYTE IP_LEN;
- BYTE szIP;
- }Socks5Info;
- typedef struct
- {
- DWORD dwIP;
- WORD wPort;
- }IPandPort;
- typedef struct
- {
- BYTE Ver;
- BYTE REP;
- BYTE RSV;
- BYTE ATYP;
- IPandPort IPandPort;
- }Socks5AnsConn;
- typedef struct
- {
- BYTE RSV[2];
- BYTE FRAG;
- BYTE ATYP;
- IPandPort IPandPort;
- BYTE DATA;
- }Socks5UDPHead;
- struct SocketInfo
- {
- SOCKET socks;
- IPandPort IPandPort;
- };
- typedef struct
- {
- SocketInfo Local;
- SocketInfo Client;
- SocketInfo Server;
- }Socks5Para;
- enum{PROXY_UNKNOWN,PROXY_HTTP,PROXY_SOCK4,PROXY_SOCK5};
- struct SOCKETINFO //每个代理连接独享的所用到的变量
- {
- ///
- BYTE IsCorR;
- BYTE ProxyType;
- BYTE IsTunnel;
- BYTE ConnectFlag;
- BYTE IsTalkOver;
- ///
- BYTE SocksVer;
- BYTE IsAuthPassed;
- BYTE SOCKS_CMD_UDP;
- SOCKADDR_IN clientaddr;
- ///
- SOCKET csock;
- SOCKET rsock;
- char buf[BUFSIZE+1];
- HANDLE hGetHost;
- char IPAddress[MAXGETHOSTSTRUCT];
- WORD RemotePort;
- WORD ClientPort;
- int recvbytes;
- int sendbytes;
- BYTE recvdelayed;
- SOCKETINFO *next;
- };
- SOCKETINFO *SocketInfoList=NULL;//链表索引指针
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- void ProcessSocketMessage(HWND, UINT, WPARAM, LPARAM);
- BOOL AddSocketInfo(SOCKET sock);
- SOCKETINFO *GetSocketInfo(SOCKET sock);
- void RemoveSocketInfo(SOCKET sock);
- void err_quit(char *msg);
- void err_display(char *msg);
- void err_display(int errcode);
- int main(int argc, char* argv[])
- //int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE,
- // LPSTR lpCmdLine, int nCmdShow)
- {
- DWORD LisPort=LISTENPORT;
- if(argc>1)
- LisPort=atoi(argv[1]);
- if(argc==4)
- {
- strcpy(Username,argv[2]);
- strcpy(Password,argv[3]);
- }
- printf("SOCKS v4 && v5 && Http Proxy V2.0 By LZX.\r\nUsage:\n%s ProxyPort (Default port 1080)\n%s ProxyPort Username Password\n",argv[0],argv[0]);
- int retval;
- WNDCLASS wndclass;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
- wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wndclass.hInstance = NULL;
- wndclass.lpfnWndProc = (WNDPROC)WndProc;
- wndclass.lpszClassName = "MyWindowClass";
- wndclass.lpszMenuName = NULL;
- wndclass.style = CS_HREDRAW | CS_VREDRAW;
- if(!RegisterClass(&wndclass)) return -1;
- HWND hWnd = CreateWindow("MyWindowClass", "TCP",
- WS_OVERLAPPEDWINDOW, 0, 0, 600, 300,
- NULL, (HMENU)NULL, NULL, NULL);
- if(hWnd == NULL) return -1;
- //ShowWindow(hWnd, SW_SHOWNORMAL);
- //UpdateWindow(hWnd);
- WSADATA wsa;
- if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
- return -1;
- // socket()
- SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, 0);
- if(listen_sock == INVALID_SOCKET){
- printf("Create SOCKET error.\n");
- return 0;
- }
- // WSAAsyncSelect()
- retval = WSAAsyncSelect(listen_sock, hWnd,
- WM_SOCKET, FD_ACCEPT|FD_CLOSE);
- if(retval == SOCKET_ERROR) {
- printf("WSAAsyncSelect SOCKET error.\n");
- return 0;
- }
- // bind()
- SOCKADDR_IN serveraddr;
- ZeroMemory(&serveraddr, sizeof(serveraddr));
- serveraddr.sin_family = AF_INET;
- serveraddr.sin_port = htons(LisPort);
- serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
- retval = bind(listen_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr));
- if(retval == SOCKET_ERROR){
- printf("bind SOCKET error.\n");
- return 0;
- }
- // listen()
- retval = listen(listen_sock, SOMAXCONN);
- if(retval == SOCKET_ERROR){
- printf("listen SOCKET error.\n");
- return 0;
- }
- printf("Now listening on port: %d\r\n",LisPort);
- MSG msg;
- while(GetMessage(&msg, 0, 0, 0) > 0){
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- WSACleanup();
- return msg.wParam;
- }
- LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
- {
- switch(uMsg){
- case WM_SOCKET:
- ProcessSocketMessage(hWnd, uMsg, wParam, lParam);
- return 0;
- case WM_DNS:
- if (WSAGETASYNCERROR(lParam))
- SendMessage(hWnd, WM_SOCKET, wParam, WM_HOSTFAILED);
- else
- SendMessage(hWnd, WM_SOCKET, wParam, WM_HOSTRESOLVED);
- return 0;
- case WM_DESTROY:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- int CheckRequest(SOCKETINFO *socketinfo) //检查请求类型,返回一个的标志
- {
- if(!strnicmp(socketinfo->buf,"GET ",4))
- return 4;
- else if(!strnicmp(socketinfo->buf,"HEAD ",5)) //Looks like the same with GET
- return 5;
- else if(!strnicmp(socketinfo->buf,"POST ",5))
- return 5;
- else if(!strnicmp(socketinfo->buf,"CONNECT ",8))
- return 8;
- Socks5Req *sq;
- char Method[2]={0x05,0};
- sq=(Socks5Req *)socketinfo->buf;
- //printf("%d,%d,%d,%d,%d\n",sq->Ver,sq->nMethods,sq->Methods[0],sq->Methods[1],sq->Methods[2]);
- if(sq->Ver!=5)
- return sq->Ver==4?socketinfo->ProxyType=PROXY_SOCK4:0;
- if((sq->Methods[0]==0)||(sq->Methods[0]==2))//00,无需认证;01,GSSAPI;02,需要用户名和PASSWORD
- {
- if(strlen(Username)==0){
- Method[1]=0x00;
- socketinfo->IsAuthPassed=true;//不用验证也就是passed
- }else
- Method[1]=0x02;
- if(send(socketinfo->csock,Method,2,0) == SOCKET_ERROR)
- return 0;
- socketinfo->recvbytes=socketinfo->sendbytes=0;
- return socketinfo->ProxyType=PROXY_SOCK5;
- }else
- return 0;
- }
- //httpproxy请求中得到主机名和端口
- void GetHostNameAndPort(char *ReceiveBuf,int datalen,char *HostName,WORD *RemotePort)
- {
- char *fp = ReceiveBuf;
- for(int i = 0;i < datalen-1 && *fp != ':' && *fp != '\0' && *fp != '\r' && *fp != '/';i++)
- {
- HostName[i]=*fp++;
- if(*fp == ':')
- *RemotePort=atoi(fp+1);
- else *RemotePort=80; //没指定端口则是默认的80
- }
- HostName[i]='\0';
- }
- char * GetURLRootPoint(char * ReceiveBuf,int DataLen,int *HostNaneLen)
- {
- for(int i = 0;i < DataLen; i++)
- {
- if(ReceiveBuf[i] == '/')
- {
- *HostNaneLen = i;
- return &ReceiveBuf[i];
- }
- }
- return NULL;
- }
- //修改httpproxy请求包,返回修改后需发送的实际字节数,返回0则失败
- int ModifyRequest(char *ReceiveBuf,int *DataLen,int MethodLength, char *HostName, WORD *RemotePort)
- {
- int HedLen = 0;
- char TempBuffer[BUFSIZE];
- if(strncmp(ReceiveBuf+MethodLength,"http://",HEADLEN))
- return 0;
- strncpy(TempBuffer,ReceiveBuf,MethodLength);
- char * Getrootfp = GetURLRootPoint(ReceiveBuf+MethodLength+HEADLEN,(*DataLen)-MethodLength-HEADLEN,&HedLen);
- if(Getrootfp == NULL){
- return 0;
- }
- GetHostNameAndPort(ReceiveBuf+MethodLength+HEADLEN,*DataLen-MethodLength-HEADLEN,HostName,RemotePort);
- memcpy(TempBuffer+MethodLength,Getrootfp,(*DataLen)-MethodLength-HEADLEN-HedLen);
- memcpy(ReceiveBuf,TempBuffer,(*DataLen)-HEADLEN-HedLen);
- *DataLen=(*DataLen)-HEADLEN-HedLen;//修改ptr->recvbytes
- ReceiveBuf[*DataLen]='\0';
- return *DataLen;
- }
- char *DNS(char *HostName)
- {
- HOSTENT *hostent = NULL;
- IN_ADDR iaddr;
- hostent = gethostbyname(HostName);
- if (hostent == NULL)
- {
- return NULL;
- }
- iaddr = *((LPIN_ADDR)*hostent->h_addr_list);
- return inet_ntoa(iaddr);
- }
- //连接到指定的主机端口,
- bool ConnectToRemoteHost(SOCKET *ServerSocket,HWND hWnd, char *HostName,const WORD RemotePort)
- {
- struct sockaddr_in Server;
- memset(&Server, 0, sizeof(Server));
- Server.sin_family = AF_INET;
- Server.sin_port = htons(RemotePort);
- Server.sin_addr.s_addr = inet_addr(HostName);
- // Create Socket
- *ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
- if (*ServerSocket == INVALID_SOCKET)
- return false;
- int retval = WSAAsyncSelect(*ServerSocket, hWnd, WM_SOCKET, FD_CONNECT|FD_CLOSE);
- //异步WSAConnect,关联其连接成功的消息FD_CONNECT到窗口句柄hWnd
- if(retval == SOCKET_ERROR)
- return false;
- WSAConnect(*ServerSocket, (const SOCKADDR *)&Server,sizeof(Server),NULL,NULL,NULL,NULL);
- return true;
- }
- //socks5代理的身份验证
- int Authentication(SOCKETINFO *socketinfo)
- {
- char USER[256];
- char PASS[256];
- memset(USER,0,sizeof(USER));
- memset(PASS,0,sizeof(PASS));
- AuthReq *aq=(AuthReq *)socketinfo->buf;
- if(aq->Ver!=1)
- return 0;
- if((aq->Ulen!=0)&&(aq->Ulen<=256))
- memcpy(USER,socketinfo->buf+2,aq->Ulen);
- int PLen=socketinfo->buf[2+aq->Ulen];
- if((PLen!=0)&&(PLen<=256))
- memcpy(PASS,socketinfo->buf+3+aq->Ulen,PLen);
- //printf("USER %s\nPASS %s\n",USER,PASS);
- //0=login successfully,0xFF=failure;
- if(!strcmp(Username,USER) && !strcmp(Password,PASS))
- {
- socketinfo->buf[1]=0x00;
- socketinfo->IsAuthPassed=true;
- //printf("Socks5 Authentication Passed\n");
- }
- else
- {
- socketinfo->buf[1]=0xFF;
- //printf("Invalid Password\n");
- }
- if(send(socketinfo->csock,socketinfo->buf,2,0) == SOCKET_ERROR)
- return 0;
- socketinfo->recvbytes=socketinfo->sendbytes=0;
- return 1;
- }
- //从socks代理请求包中分析出请求的目标主机名和端口,在udp模式中分析后返回真正数据入口点
- int GetAddressAndPort(char *RecvBuf, int ATYP, char *HostName, WORD *RemotePort)
- {
- DWORD Socks5InfoSize = sizeof(Socks5Info);
- DWORD dwIndex = 0;
- Socks4Req *Socks4Request=(Socks4Req *)RecvBuf;
- Socks5Info *Socks5Request=(Socks5Info *)RecvBuf;
- memset(HostName,0,MAX_HOSTNAME);
- struct sockaddr_in in;
- if(ATYP==2) //Socks v4 !!!
- {
- *RemotePort=ntohs(Socks4Request->wPort);
- if(RecvBuf[4]!=0x00){ //USERID !!
- in.sin_addr.s_addr = Socks4Request->dwIP;
- memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
- }else
- memcpy(HostName, (char*)&Socks4Request->other+1,strlen((char*)&Socks4Request->other+1)+1);
- return 1;
- }
- //ATYP=0x01代表IP V4地址 0x03代表域名;
- if((Socks5Request->Ver==5)&&(ATYP==1))
- {
- IPandPort *IPP=(IPandPort *)&Socks5Request->IP_LEN;
- in.sin_addr.S_un.S_addr = IPP->dwIP;
- memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
- *RemotePort = ntohs(IPP->wPort);
- }
- else if((Socks5Request->Ver==5)&&(ATYP==3))
- {
- memcpy(HostName, &Socks5Request->szIP, Socks5Request->IP_LEN);
- memcpy(RemotePort, &Socks5Request->szIP+Socks5Request->IP_LEN, 2);
- *RemotePort=ntohs(*RemotePort);
- }else if((Socks5Request->Ver==0)&&(Socks5Request->CMD==0)&&(ATYP==1))
- {
- IPandPort *IPP=(IPandPort *)&Socks5Request->IP_LEN;
- in.sin_addr.S_un.S_addr = IPP->dwIP;
- memcpy(HostName, inet_ntoa(in.sin_addr),strlen(inet_ntoa(in.sin_addr)));
- *RemotePort = ntohs(IPP->wPort);
- return 10; //return Data Enter point
- }else if((Socks5Request->Ver==0)&&(Socks5Request->CMD==0)&&(ATYP==3))
- {
- memcpy(HostName, &Socks5Request->szIP, Socks5Request->IP_LEN);
- memcpy(RemotePort, &Socks5Request->szIP+Socks5Request->IP_LEN, 2);
- *RemotePort=ntohs(*RemotePort);
- return 7+Socks5Request->IP_LEN; //return Data Enter point
- }else
- return 0;
- return 1;
- }
- //Get and return the work mode. 1:TCP CONNECT 3:UDP ASSOCIATE
- int GetProxyInfo(SOCKETINFO *socketinfo, char *HostName, WORD *RemotePort)
- {
- Socks5Info *Socks5Request=(Socks5Info *)socketinfo->buf;
- if(Socks5Request->Ver == 4)
- return GetAddressAndPort(socketinfo->buf, 2, HostName, RemotePort);
- //Get IP Type //0x01==IP V4地址 0x03代表域名;0x04代表IP V6地址;not Support
- if((Socks5Request->ATYP==1)||(Socks5Request->ATYP==3))
- {
- if(!GetAddressAndPort(socketinfo->buf, Socks5Request->ATYP, HostName, RemotePort))
- return 0;
- }else return 0;
- //Get and return the work mode. 1:TCP CONNECT 3:UDP ASSOCIATE
- if((Socks5Request->CMD == 1)||(Socks5Request->CMD == 3))
- return Socks5Request->CMD;
- return 0;
- }
- //Get local IP
- char *GetInetIP(char *OutIP)
- {
- // Get host adresses
- char addr[16];
- struct hostent * pHost;
- pHost = gethostbyname("");
- for( int i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
- {
- OutIP[0]=0;
- for( int j = 0; j < pHost->h_length; j++ )
- {
- if( j > 0 ) strcat(OutIP,".");
- sprintf(addr,"%u", (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);
- strcat(OutIP,addr);
- }
- }
- return OutIP;
- }
- //本地创建绑定一个udp套接字
- BOOL CreateUDPSocket(Socks5AnsConn *SAC, SOCKET *socks)
- {
- char szIP[256];
- struct sockaddr_in UDPServer;
- struct sockaddr_in in;
- memset(&in,0,sizeof(sockaddr_in));
- int structsize=sizeof(sockaddr_in);
- UDPServer.sin_family=AF_INET;
- UDPServer.sin_addr.s_addr= INADDR_ANY;
- UDPServer.sin_port=INADDR_ANY;
- SOCKET Locals = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if(Locals == SOCKET_ERROR)
- {
- //printf("UDP socket create failed.\n");
- return 0;
- }
- if(bind(Locals,(SOCKADDR*)&UDPServer, sizeof(UDPServer)) == SOCKET_ERROR)
- {
- //printf("UDP socket bind failed.\n");
- return 0;
- }
- //UINT TimeOut = TIMEOUT;
- //setsockopt(Locals,SOL_SOCKET,SO_RCVTIMEO,(char *)&TimeOut,sizeof(TimeOut));
- *socks = Locals;
- getsockname(Locals,(struct sockaddr *)&in,&structsize);
- SAC->IPandPort.dwIP = inet_addr(GetInetIP(szIP));
- SAC->IPandPort.wPort = in.sin_port;
- //printf("UDP Bound to %s:%d\r\n", szIP, ntohs(in.sin_port));
- return 1;
- }
- int UDPSend(SOCKET s, char *buff, int nBufSize, struct sockaddr_in *to,int tolen)
- {
- int nBytesLeft = nBufSize;
- int idx = 0, nBytes = 0;
- while(nBytesLeft > 0)
- {
- nBytes = sendto(s, &buff[idx], nBytesLeft, 0, (SOCKADDR *)to, tolen);
- if(nBytes == SOCKET_ERROR)
- {
- //printf("Failed to send buffer to socket %d.\r\n", WSAGetLastError());
- return SOCKET_ERROR;
- }
- nBytesLeft -= nBytes;
- idx += nBytes;
- }
- return idx;
- }
- //套接字消息处理函数
- void ProcessSocketMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- SOCKETINFO *ptr;
- SOCKET sock;
- SOCKET client_sock;
- SOCKADDR_IN clientaddr;
- struct sockaddr_in SenderAddr;
- struct sockaddr_in UDPClient,UDPServer;
- int SenderAddrSize=sizeof(SenderAddr);
- HOSTENT *hostent;
- WSABUF DataBuf;
- DWORD RecvBytes=0,SendBytes=0;
- DWORD Flags=0;
- int ProxyFlag,PTYP;
- int addrlen=sizeof(sockaddr_in);
- int retval;
- bool IsTransmit=false;
- char HostName[MAX_HOSTNAME];
- ///
- Socks4Req Socks4Request;
- Socks5AnsConn SAC;
- if(WSAGETSELECTERROR(lParam)){
- //err_display(WSAGETSELECTERROR(lParam));
- RemoveSocketInfo(wParam);
- return;
- }
- switch(WSAGETSELECTEVENT(lParam)){
- case FD_ACCEPT:
- addrlen = sizeof(clientaddr);
- client_sock = accept(wParam, (SOCKADDR *)&clientaddr, &addrlen);
- if(client_sock == INVALID_SOCKET){
- if(WSAGetLastError() != WSAEWOULDBLOCK)
- //err_display("accept()");
- return;
- }
- //printf("[TCP] Accept IP:%s:%d\n",
- // inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
- if(!AddSocketInfo(client_sock)){
- printf("AddSocketInfo error.\n");
- closesocket(client_sock);
- return;
- }
- retval = WSAAsyncSelect(client_sock, hWnd,
- WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);
- if(retval == SOCKET_ERROR){
- //err_display("WSAAsyncSelect()");
- RemoveSocketInfo(client_sock);
- }
- break;
- case FD_READ:
- //printf("SOCKET:%d case FD_READ\n",wParam);
- ptr = GetSocketInfo(wParam);
- if(!ptr){
- closesocket(wParam);
- //printf("ptr==NULL\n");
- return;
- }
- //sock5 udp代理模式的接收和转发处理 START:
- //需要域名DNS的转发处理仍不理想,即异步WSAAsyncGetHostByName后数据的处理
- //不用异步WSAAsyncGetHostByName的话没问题,但有些域名的解释可能会花几秒时间,
- //这样就违背了这个程序的异步模式框架
- if(wParam==ptr->rsock&&ptr->SOCKS_CMD_UDP){
- if(ptr->recvdelayed==true){
- //printf("case FD_READ: ptr->recvdelayed==true!!!!!!!!!!!\n");
- return; //WSAAsyncGetHostByName...还没消息,缓冲区数据还未发出,
- //所以应该延迟接收数据,但不知道为什么测试qq效果不行,注释掉反而好点
- }
- memset(&UDPServer,0,sizeof(sockaddr_in));
- //DataBuf.buf=ptr->buf+10; //空出10个字节缓冲区,方便增加转发给Client的udp报头
- //DataBuf.len=BUFSIZE -10;
- RecvBytes=recvfrom(ptr->rsock,
- ptr->buf+10, BUFSIZE-10, 0, (struct sockaddr FAR *)&SenderAddr, &SenderAddrSize);
- if(RecvBytes == SOCKET_ERROR){
- err_display("recvfrom()");
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- printf("WSARecvFrom SOCKET_ERROR\n");
- return;
- }
- if(SenderAddr.sin_port==ptr->clientaddr.sin_port)
- {//Data come from client
- int retval=GetAddressAndPort(ptr->buf+10, ptr->buf[13], HostName, &ptr->RemotePort);
- if(retval)
- {
- //printf("Data come from client IP: %s:%d | %d Bytes.\n",
- // inet_ntoa(SenderAddr.sin_addr),ntohs(SenderAddr.sin_port),RecvBytes);
- //send data to server
- //printf("Target IP: %s:%d || DataPoint: %d\n",HostName,ptr->RemotePort,retval);
- UDPServer.sin_family=AF_INET;
- UDPServer.sin_port=htons(ptr->RemotePort);
- if (ptr->buf[13] == 0x03){//域名,需要dns,
- //异步WSAAsyncGetHostByName
- /*printf("recvdelayed=true,WSAAsyncGetHostByName...\n");
- ptr->recvbytes=RecvBytes;
- ptr->sendbytes=retval;
- ptr->recvdelayed=true;
- ptr->hGetHost=WSAAsyncGetHostByName(hWnd, WM_DNS , HostName, ptr->IPAddress, MAXGETHOSTSTRUCT);
- return;*/
- UDPServer.sin_addr.s_addr = inet_addr(DNS(HostName));//同步的域名解析
- }else
- UDPServer.sin_addr.s_addr = inet_addr(HostName);
- if(UDPSend(ptr->rsock,ptr->buf+retval+10, RecvBytes-retval,&UDPServer,sizeof(UDPServer)) == SOCKET_ERROR)
- {
- //printf("sendto server error!!!!\n");
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- }
- //printf("Data(%d) sent to server succeed.\n",RecvBytes-retval);
- }else{
- //printf("GetAddressAndPort error\n");
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- return;
- }
- }else
- {//Data come from server
- //printf("Data come from server IP: %s:%d | %d Bytes.\n",
- // inet_ntoa(SenderAddr.sin_addr),ntohs(SenderAddr.sin_port),RecvBytes);
- Socks5UDPHead *UDPHead = (Socks5UDPHead*)ptr->buf;
- memset(UDPHead,0,10);
- UDPHead->ATYP=0x01;
- //UDPHead->IPandPort=sPara->Client.IPandPort;
- UDPHead->IPandPort.dwIP =ptr->clientaddr.sin_addr.S_un.S_addr;
- UDPHead->IPandPort.wPort=ptr->clientaddr.sin_port;
- //memcpy(&UDPHead->DATA-2,RecvBuf,DataLength);//UDPHead->DATA-2!!!!!!!!!!!!
- if(UDPSend(ptr->rsock,ptr->buf,RecvBytes+10,&ptr->clientaddr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
- {
- //printf("sendto client error!!!!!!!!!!\n");
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- return;
- }
- //printf("sendto client ok\n");
- }
- break;
- }sock5 udp代理模式的接收和转发处理 END!
- //sock5 tcp代理模式的接收和转发处理 start
- sock=ptr->IsCorR?ptr->csock:ptr->rsock;
- if(ptr->recvbytes > 0){
- //printf("SOCKET: %d recvdelayed = TRUE\n", wParam);
- ptr->recvdelayed = TRUE;
- //PostMessage(hWnd, WM_SOCKET, ptr->IsCorR?ptr->rsock:ptr->csock, FD_WRITE);
- return;
- }
- DataBuf.buf=ptr->buf;
- DataBuf.len=BUFSIZE;
- //retval = recv(sock, ptr->buf, BUFSIZE, 0);
- if(WSARecv(sock, &DataBuf, 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR){
- if(WSAGetLastError() != WSAEWOULDBLOCK){
- //err_display("recv()");
- RemoveSocketInfo(wParam);
- }
- return;
- }
- ptr->recvbytes = RecvBytes;
- ptr->buf[RecvBytes] = '\0';
- //addrlen = sizeof(clientaddr);
- //getpeername(wParam, (SOCKADDR *)&ptr->clientaddr, &addrlen);
- //if(ptr->IsCorR && !ptr->IsTunnel)
- //printf("[TCP/%s:%d] \n%s\n", inet_ntoa(clientaddr.sin_addr),
- // ntohs(clientaddr.sin_port), ptr->buf);
- //接收到的数据是来自client并且还没进入纯转发模式(如http connect 代理模式以及socks5还没通过所有协议对话)
- if(ptr->IsCorR && !ptr->IsTunnel)
- {
- //ptr->IsTalkOver=false; //该结构new创建后memset清零了,已经是false,所以注释掉无所谓
- if(ptr->ProxyType==PROXY_SOCK5 && ptr->IsAuthPassed)//代理类型是sock5而且已经通过身份验证
- {
- PTYP = GetProxyInfo(ptr, HostName, &ptr->RemotePort);//分析获得代理信息(目标IP和端口,代理模式)
- if(PTYP==1){//1:TCP CONNECT 模式
- //printf("GetProxyInfo: %s:%d\n",HostName, &ptr->RemotePort);
- if (inet_addr(HostName) == INADDR_NONE)//HostName是域名的情况下要DNS
- ptr->hGetHost=WSAAsyncGetHostByName(hWnd, WM_DNS , HostName, ptr->IPAddress, MAXGETHOSTSTRUCT);
- else{
- retval = ConnectToRemoteHost(&ptr->rsock, hWnd, HostName, ptr->RemotePort);//连接目标
- if(!retval)
- RemoveSocketInfo(wParam);
- }
- break;
- }else if(PTYP==3)//3:UDP ASSOCIATE 模式
- {
- ptr->ClientPort = ptr->RemotePort;
- getpeername(ptr->csock, (SOCKADDR *)&ptr->clientaddr, &addrlen);
- ptr->clientaddr.sin_port=htons(ptr->ClientPort);
- memset(&SAC,0,sizeof(SAC));
- if(!CreateUDPSocket(&SAC,&ptr->rsock)) //Create a local UDP socket
- SAC.REP=0x01;
- SAC.Ver=5;
- SAC.ATYP=1;
- if(send(ptr->csock, (char *)&SAC, 10, 0) == SOCKET_ERROR)//After Create a local UDP socket successfully,reply client is ready.
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- retval = WSAAsyncSelect(ptr->rsock, hWnd, WM_SOCKET, FD_READ|FD_CLOSE);
- if(retval == SOCKET_ERROR){
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- }
- ptr->SOCKS_CMD_UDP=true;
- break;
- }else
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- break;
- }else if(ptr->ProxyType==PROXY_SOCK5 && !ptr->IsAuthPassed)
- {
- Authentication(ptr);///!!!sock5代理模式,!ptr->IsAuthPassed则验证之
- break;
- }
- ProxyFlag=CheckRequest(ptr);//检查请求包头,分析代理类型
- if(!ProxyFlag){//不可识别
- //printf("!HTTPProxyFlag\n");
- if(!ptr->ProxyType){//且代理类型仍不明,也就是首次的请求,前请求不可识别
- RemoveSocketInfo(wParam);//非法请求,关闭
- return;
- }
- }else if(ProxyFlag==4||ProxyFlag==5) // "get "==4,"head "=="post "==5
- {
- ptr->ProxyType=PROXY_HTTP;
- if(!ModifyRequest(ptr->buf,&ptr->recvbytes,ProxyFlag,HostName,&ptr->RemotePort)){//获取http代理请求中的目标主机和端口并修改该包
- printf("!ModifyRequest\n");
- RemoveSocketInfo(wParam);
- return;
- }
- //http代理的非connect模式的,标志协议对话完毕
- ptr->IsTalkOver=true;
- }else if(ProxyFlag==8)//http proxy "connect " mode =8
- {
- ptr->ProxyType=PROXY_HTTP;
- GetHostNameAndPort(ptr->buf+ProxyFlag,ptr->recvbytes-ProxyFlag-HEADLEN,HostName,&ptr->RemotePort);
- }else if(ProxyFlag==PROXY_SOCK4)//socks4代理,第一个包就带请求目的ip和端口信息了
- {
- ptr->IsAuthPassed=true;//socks4不支持验证,也就是通过了
- PTYP = GetProxyInfo(ptr, HostName, &ptr->RemotePort);//分析获取代理信息:IP AND PORT
- if(PTYP){
- //printf("GetProxyInfo: %s:%d\n",HostName, &ptr->RemotePort);
- if (inet_addr(HostName) == INADDR_NONE)
- ptr->hGetHost=WSAAsyncGetHostByName(hWnd, WM_DNS , HostName, ptr->IPAddress, MAXGETHOSTSTRUCT);
- else{
- retval = ConnectToRemoteHost(&ptr->rsock, hWnd, HostName, ptr->RemotePort);
- if(!retval)
- RemoveSocketInfo(wParam);
- }
- }
- break;
- }
- if(ptr->ProxyType==PROXY_HTTP)//http 代理,dns主机名后连接目标主机
- {
- ptr->ConnectFlag=false;//标志为远程主机未连接
- //printf("ConnectToRemoteHost=>%s:%d\n", HostName, ptr->RemotePort);
- if (inet_addr(HostName) == INADDR_NONE)//DNS
- ptr->hGetHost=WSAAsyncGetHostByName(hWnd, WM_DNS , HostName, ptr->IPAddress, MAXGETHOSTSTRUCT);
- else{
- retval = ConnectToRemoteHost(&ptr->rsock, hWnd, HostName, ptr->RemotePort);
- if(!retval)
- RemoveSocketInfo(wParam);
- }
- break;
- }
- }
- IsTransmit=true;//所有FD_READ之后缓冲区的数据都要转发到目的地
- case FD_WRITE:
- //printf("SOCKET: %d case FD_WRITE\n",wParam);
- ptr = GetSocketInfo(wParam);
- if(!ptr){
- closesocket(wParam);
- //printf("ptr==NULL\n",wParam);
- return;
- }
- if(IsTransmit) //是要转发的话,如果wParam是客户端套接字则设sock为远程端的套接字,反之亦然,否则sock仍为当前wParam值
- sock=ptr->IsCorR?ptr->rsock:ptr->csock;
- else
- sock=ptr->IsCorR?ptr->csock:ptr->rsock;
- if(ptr->recvbytes <= ptr->sendbytes || !ptr->IsTalkOver || !ptr->ConnectFlag)//协议对话完毕且目的IP连接已经标志才进行数据转发
- return;
- //开始发送缓冲区数据
- //if(ptr->rsock==sock && !ptr->IsTunnel)
- // printf("Send: \n%s\n",ptr->buf);
- //retval = send(sock, ptr->buf + ptr->sendbytes,
- // ptr->recvbytes - ptr->sendbytes, 0);
- DataBuf.buf=ptr->buf + ptr->sendbytes;
- DataBuf.len=ptr->recvbytes - ptr->sendbytes;
- if(WSASend(sock, &DataBuf, 1, &SendBytes, Flags, NULL, NULL)== SOCKET_ERROR){
- if(WSAGetLastError() != WSAEWOULDBLOCK){
- //err_display("send()");
- RemoveSocketInfo(wParam);
- }
- return;
- }
- ptr->sendbytes += SendBytes;
- if(ptr->recvbytes == ptr->sendbytes){
- ptr->recvbytes = ptr->sendbytes = 0;
- if(ptr->recvdelayed){
- ptr->recvdelayed = FALSE;
- //printf("ptr->recvdelayed = FALSE\n");
- PostMessage(hWnd, WM_SOCKET, sock==ptr->csock?ptr->rsock:ptr->csock, FD_READ);
- }
- }
- break;
- case FD_CONNECT://ConnectToRemoteHost的结果,目标连接成功
- ptr = GetSocketInfo(wParam);
- if(!ptr){
- //printf("ptr==NULL\n",wParam);
- return;
- }
- ptr->ConnectFlag=true;//标志为已连接
- WSAAsyncSelect(wParam, hWnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);//关联该套接字的读写和关闭消息到窗口
- //printf("Connect To Remote Host OK\n");
- if(!ptr->IsTalkOver&&ptr->ProxyType==PROXY_HTTP){//http代理类型如果在连接目标后IsTalkOver仍未标志,则表示是connect模式
- DataBuf.buf=ConnectionEstablished;
- DataBuf.len=strlen(ConnectionEstablished)+1;//最后一个协议对话,即回复客户端目标连接 ready
- if(WSASend(ptr->csock, &DataBuf, 1, &SendBytes, Flags, NULL, NULL)== SOCKET_ERROR){
- if(WSAGetLastError() != WSAEWOULDBLOCK){
- //err_display("send()");
- RemoveSocketInfo(wParam);
- }
- return;
- }
- ptr->IsTalkOver=true;//标志协议对话完毕
- ptr->IsTunnel=true;//已经可以进入纯转发模式
- ptr->recvbytes = ptr->sendbytes = 0;
- }else if(!ptr->IsTalkOver&&ptr->ProxyType==PROXY_SOCK5)//socks5代理在连接目标后回复客户端ready
- {
- memset(&SAC,0,sizeof(SAC));
- SAC.Ver=0x05;
- SAC.ATYP=0x01;
- if(send(ptr->csock, (char *)&SAC, 10, 0) == SOCKET_ERROR)
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- ptr->recvbytes=ptr->sendbytes=0;
- ptr->IsTalkOver=true;//标志协议对话完毕
- ptr->IsTunnel=true;//已经可以进入纯转发模式
- }else if(!ptr->IsTalkOver&&ptr->ProxyType==PROXY_SOCK4)//socks4 同socks5
- {
- memset(&Socks4Request, 0, 9);
- Socks4Request.REP = 0x5A; //GRANT
- if(send(ptr->csock, (char *)&Socks4Request, 8, 0) == SOCKET_ERROR)
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- ptr->recvbytes=ptr->sendbytes=0;
- ptr->IsTalkOver=true;
- ptr->IsTunnel=true;
- }
- break;
- case WM_HOSTRESOLVED://异步WSAAsyncGetHostByName成功的结果
- ptr = SocketInfoList;
- while(ptr){
- if(ptr->hGetHost==(HANDLE)wParam)
- break;
- ptr = ptr->next;
- }
- if(!ptr){
- //printf("ptr==NULL\n",wParam);
- return;
- }
- hostent=(HOSTENT*)ptr->IPAddress;
- //printf("WM_HOSTRESOLVED:%s:%d\n",inet_ntoa(*((LPIN_ADDR)*hostent->h_addr_list)),ptr->RemotePort);
- if(ptr->SOCKS_CMD_UDP)//socks5 udp模式代理(面向非连接协议)所以在dns后不用connect就可以直接转发数据
- {
- memset(&UDPServer,0,sizeof(UDPServer));
- UDPServer.sin_family=AF_INET;
- UDPServer.sin_port=htons(ptr->RemotePort);
- UDPServer.sin_addr.s_addr= inet_addr(inet_ntoa(*((LPIN_ADDR)*hostent->h_addr_list)));
- if(UDPSend(ptr->rsock,ptr->buf+ptr->sendbytes+10, ptr->recvbytes-ptr->sendbytes,&UDPServer,sizeof(UDPServer)) == SOCKET_ERROR)
- {
- //printf("WM_HOSTRESOLVED sendto server error!!!!\n");
- PostMessage(hWnd, WM_SOCKET, ptr->csock, FD_CLOSE);
- }
- //printf("WM_HOSTRESOLVED sendto server success!!!!\n");
- ptr->recvdelayed=ptr->sendbytes=ptr->recvbytes=0;
- break;
- }
- retval = ConnectToRemoteHost(&ptr->rsock, hWnd, inet_ntoa(*((LPIN_ADDR)*hostent->h_addr_list)), ptr->RemotePort);
- if(!retval)
- RemoveSocketInfo(ptr->csock);
- break;
- case WM_HOSTFAILED://dns 失败消息
- ptr = SocketInfoList;
- while(ptr){
- if(ptr->hGetHost==(HANDLE)wParam)
- break;
- ptr = ptr->next;
- }
- if(ptr){
- RemoveSocketInfo(ptr->csock);
- }
- break;
- case FD_CLOSE:
- RemoveSocketInfo(wParam);
- break;
- }
- }
- //将新的请求的套接字信息加到此链中
- BOOL AddSocketInfo(SOCKET sock)
- {
- SOCKETINFO *ptr = new SOCKETINFO;
- if(ptr == NULL){
- printf("new SOCKETINFO error!\n");
- return FALSE;
- }
- memset(ptr,0,sizeof(SOCKETINFO));
- //ptr->ProxyType = PROXY_UNKNOWN;
- ptr->csock = sock;
- //ptr->recvbytes = 0;
- //ptr->sendbytes = 0;
- //ptr->recvdelayed = FALSE;
- ptr->next = SocketInfoList;
- SocketInfoList = ptr;
- return TRUE;
- }
- //从SOCKETINFO链中获得指定套接字的指针
- SOCKETINFO *GetSocketInfo(SOCKET sock)
- {
- SOCKETINFO *ptr = SocketInfoList;
- while(ptr){
- if(ptr->csock == sock||ptr->rsock == sock)
- {
- ptr->IsCorR=(ptr->csock == sock)?true:false;
- return ptr;
- }
- ptr = ptr->next;
- }
- return NULL;
- }
- //从SOCKETINFO链中删除指定套接字的指针
- void RemoveSocketInfo(SOCKET sock)
- {
- //SOCKADDR_IN clientaddr;
- //int addrlen = sizeof(clientaddr);
- //getpeername(sock, (SOCKADDR *)&clientaddr, &addrlen);
- //printf("[Close] IP:%s:%d\n",
- // inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
- SOCKETINFO *curr = SocketInfoList;
- SOCKETINFO *prev = NULL;
- while(curr){
- if(curr->csock == sock||curr->rsock == sock){
- if(prev)
- prev->next = curr->next;
- else
- SocketInfoList = curr->next;
- closesocket(curr->csock);
- closesocket(curr->rsock);
- delete curr;
- return;
- }
- prev = curr;
- curr = curr->next;
- }
- }
- void err_quit(char *msg)
- {
- /*
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER|
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf, 0, NULL);
- MessageBox(NULL, (LPCTSTR)lpMsgBuf, msg, MB_ICONERROR);
- LocalFree(lpMsgBuf);
- exit(-1);
- */
- printf("%s\n",msg);
- }
- void err_display(char *msg)
- {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER|
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, WSAGetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf, 0, NULL);
- printf("[%s] %s", msg, (LPCTSTR)lpMsgBuf);
- LocalFree(lpMsgBuf);
- printf("%s\n",msg);
- }
- void err_display(int errcode)
- {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER|
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, errcode,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf, 0, NULL);
- printf("[Error] %s", (LPCTSTR)lpMsgBuf);
- LocalFree(lpMsgBuf);
- }
socks5
最新推荐文章于 2022-04-09 16:26:45 发布