SOCKS5 代理协议是他人定的,要编写程序首先必须了解其协议规则。所以先必须仔细地阅读rfc1928。这样对能够编写socket程序员来讲是易如反掌。本文是专门面对SOCKS5 UDP(无验证方式)
/* Test Socks5 UDP proxy Write by nenlong http://newnan.8u8.com mail:nnelong@tom.com At Yanji 2004.2.26 send 5 0 recv 5 0
send 5 3 0 1 IP(4) Port(2) recv 5 0 0 1 IP(4) Port(2)
data 0 0 0 1 IP(4) Port(2) DATA
UDP ASSOCIATE The UDP ASSOCIATE request is used to establish an association within the UDP relay process to handle UDP datagrams. The DST.ADDR and DST.PORT fields contain the address and port that the client expects to use to send UDP datagrams on for the association. The server MAY use this information to limit access to the association. If the client is not in possesion of the information at the time of the UDP ASSOCIATE, the client MUST use a port number and address of all zeros.
If the reply code (REP value of X'00') indicates a success, and the request was either a BIND or a CONNECT, the client may now start passing data.
*/ #include "StdAfx.h" #include "winsock2.h" #include <stdlib.h> #include <conio.h> #include <ctype.h> void closesocks(SOCKET s); int senddata(char *data,int isize,sockaddr_in sa);//UDP #pragma comment (lib,"ws2_32.lib") char szMyIP[20]; char szProxyIP[20]; char szMsg[50]; int isc; void main(void) { // 开始使用ws2_32.dll sprintf(szProxyIP,"192.168.0.1");
WSADATA wsaData; int iRetVal,i; iRetVal = WSAStartup ( MAKEWORD ( 1,1 ), &wsaData ); if ( 0 != iRetVal) { printf("WSAStartup %d", iRetVal ); return; } printf("WSAStartup [OK]\n");
//取得主机名称 char szhostname[128]; if(SOCKET_ERROR ==gethostname(szhostname,128)) { printf("gethostname %X\n",WSAGetLastError()); return; } printf("hostname %s[OK]\n",szhostname);
struct hostent FAR * lps; lps=gethostbyname(szhostname); if(lps==NULL) { printf("gethostbyname error\n"); } else { IN_ADDR ia; memcpy(&ia,lps->h_addr_list[0],4); sprintf(szMyIP,"%s",inet_ntoa (ia)); printf(" addr:%s\n",szMyIP); }
//建立socket //AF_INET ---->to AF_INET for IPv4 addressing //SOCK_STREAM --->TCP SOCKET s; s=socket(AF_INET,SOCK_STREAM,0); if(s==INVALID_SOCKET) { printf("socket %X\r",WSAGetLastError()); closesocket(s); return; } printf("socket TCP [OK]\n"); sockaddr_in sa; sa.sin_family=AF_INET; sa.sin_port=htons(1080); //Port sa.sin_addr.s_addr= inet_addr(szProxyIP); //IP
//建立连接 到代理服务器 iRetVal=connect (s,(SOCKADDR*)&sa,sizeof(sockaddr_in)); if(iRetVal==SOCKET_ERROR) { printf ("connect %X\n",WSAGetLastError()); closesocket(s); return; } printf("connect %s %d[OK]\n",szProxyIP,1080); //请求无验证 char buff[255]; buff[0]=5;buff[1]=0; iRetVal=send(s,buff,2,0); if(iRetVal==SOCKET_ERROR) { printf ("send 50 %X\n",WSAGetLastError()); closesocket(s); return; } printf("Send 5 0 [OK]\n"); memset(buff,0,4); printf("Recv "); iRetVal=recv(s,buff,4,0); printf("%02X %02X %02X %02X [OK]\n",buff[0],buff[1],buff[2],buff[3]);
//返回 5 0 请求成功 if(buff[0]!=5 || buff[1]!=0) { printf ("not proxy service\n"); closesocket(s); return; }
printf("find proxy server[OK]\n");
//报文10字节
buff[0]=5; //Ver buff[1]=3; //UDP buff[2]=0; buff[3]=1; //IP V4 address buff[4]=(unsigned char)0; buff[5]=(unsigned char)0; buff[6]=(unsigned char)0; buff[7]=(unsigned char)0; buff[8]=(unsigned char)0; buff[9]=(unsigned char)0;
//发送报文 iRetVal=send(s,buff,10,0); if(iRetVal==SOCKET_ERROR) { printf ("send 530100001388 %X\n",WSAGetLastError()); closesocket(s); return; } printf("Send 05 03 00 01 00 00 00 00 00 00 [OK]\n"); memset(buff,0,10); iRetVal=recv(s,buff,10,0); if(iRetVal==SOCKET_ERROR) { printf ("recv %X\n",WSAGetLastError()); closesocket(s); return; } printf("Recv "); for(i=0;i<10;i++) printf ("%02X ",(unsigned char)buff[i]); printf("[OK]\n"); if(buff[0]!=5 || buff[1]!=0) { printf ("not UDP proxy service\n"); closesocket(s); return; }
char szIP[20]; sprintf(szIP,"%d.%d.%d.%d", (unsigned char)buff[4], (unsigned char)buff[5], (unsigned char)buff[6], (unsigned char)buff[7]); int port; port=(buff[8]<<8)+buff[9]; Sleep(500); printf("UDP Proxy Add:%s Port:%d\nPress any key Send ...\n",szIP,port); getch(); isc=0; int ikey; while((ikey=getch())!=0x1b) { //send data sockaddr_in sato; sato.sin_family=AF_INET; sato.sin_port=htons(port); sato.sin_addr.s_addr= inet_addr(szIP);
buff[0]=0; //RSV buff[1]=0; //RSV buff[2]=0; //FRAG buff[3]=1; //IPV4 buff[4]=(unsigned char)192; buff[5]=(unsigned char)168; buff[6]=(unsigned char)0; buff[7]=(unsigned char)1; buff[8]=(unsigned char)0x13; buff[9]=(unsigned char)0x88;//5000 isc++; if(isc>50)isc=0; if(ikey==17) //ctrl+Q sprintf(szMsg,"Q"); else sprintf(szMsg,"Hello SOCKS5 (UDP) %d ",isc);
for(i=0;i<(int)strlen(szMsg);i++) { buff[10+i]=szMsg[i]; } buff[10+i]=0;
senddata(buff,10+strlen(szMsg)+1,sato);
if(iRetVal==SOCKET_ERROR) { printf ("send data %X\n",WSAGetLastError()); closesocket(s); return; } printf("Press ESC key to exit Ctrl+Q Close RECV5000 Windows\n"); } closesocket(s); return; }
void closesocks(SOCKET s) { closesocket(s); WSACleanup(); }
int senddata(char *data,int isize,sockaddr_in sa) { int ret,i; SOCKET s; s=socket(AF_INET,SOCK_DGRAM,0); ret=connect(s,(SOCKADDR*)&sa,sizeof(sockaddr_in)); if(ret==SOCKET_ERROR) { printf("UDP connect %X\n",ret); closesocket(s); return ret; } printf("UDP Send IP:%s Port:%d\nSend ",inet_ntoa (sa.sin_addr),ntohs (sa.sin_port)); for(i=0;i<isize;i++) printf("%02X ",(unsigned char)data[i]); printf("\n\n"); ret=send(s,data,isize,0); closesocket(s); return ret; }
以上即关于UDP穿透Socks5代理(无验证)的一点心得,希望能够得到大家的指正。
|