C语言写的linux socks Proxy

C语言写的Linux平台socks5代理程序

信息来源:邪恶八进制信息安全团队(www.eviloctal.com)

前几天MSN老上不去,我还以为是公司做了防火墙限制。于是把去年这个时候写得一个代理程序改了改,拿出来用。结果发现MSN是因为微软的问题,鄙视啊……

因为写得比较急,这个只支持TCP代理,UDP的我没写,因为MSN用不上。这个代码可以随意修改分发,不过最好能给我一份。

这是头文件:

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Socks5代理头文件,定义协议相关数据包结构

//版本0.1,作者云舒

//2007年1月9日凌晨1点15分,GF回家已经11天了。

//2008年1月25日修改,今年GF一直在我身边,哈哈

//

//参考:

//http://www.rfc-editor.org/rfc/rfc1928.txt

//http://www.rfc-editor.org/rfc/rfc1929.txt

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndefSOCKS5_H

#defineSOCKS5_H

#defineVERSION0x05

#defineCONNECT0x01

#defineIPV40x01

#defineDOMAIN0x03

#defineIPV60x04

typedefstruct_method_select_response//协商方法服务器响应

{

charversion;//服务器支持的Socks版本,0x04或者0x05

charselect_method;//服务器选择的方法,0x00为匿名,0x02为密码认证

}METHOD_SELECT_RESPONSE;

typedefstruct_method_select_request//协商方法服务端请求

{

charversion;//客户端支持的版本,0x04或者0x05

charnumber_methods;//客户端支持的方法的数量

charmethods[255];//客户端支持的方法类型,最多255个,0x00为匿名,0x02为密码认证

}METHOD_SELECT_REQUEST;

typedefstruct_AUTH_RESPONSE//用户密码认证服务端响应

{

charversion;//版本,此处恒定为0x01

charresult;//服务端认证结果,0x00为成功,其他均为失败

}AUTH_RESPONSE;

typedefstruct_AUTH_REQUEST//用户密码认证客户端请求

{

charversion;//版本,此处恒定为0x01

charname_len;//第三个字段用户名的长度,一个字节,最长为0xff

charname[255];//用户名

charpwd_len;//第四个字段密码的长度,一个字节,最长为0xff

charpwd[255];//密码

}AUTH_REQUEST;

typedefstruct_SOCKS5_RESPONSE//连接真实主机,Socks代理服务器响应

{

charversion;//服务器支持的Socks版本,0x04或者0x05

charreply;//代理服务器连接真实主机的结果,0x00成功

charreserved;//保留位,恒定位0x00

charaddress_type;//Socks代理服务器绑定的地址类型,IPV4为0x01,IPV6为0x04,域名为0x03

charaddress_port[1];//如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为Socks代理服务器绑定端口

}SOCKS5_RESPONSE;

typedefstruct_SOCKS5_REQUEST//客户端请求连接真实主机

{

charversion;//客户端支持的Socks版本,0x04或者0x05

charcmd;//客户端命令,CONNECT为0x01,BIND为0x02,UDP为0x03,一般为0x01

charreserved;//保留位,恒定位0x00

charaddress_type;//客户端请求的真实主机的地址类型,IPV4为0x00,IPV6为0x04,域名为0x03charaddress_port[1];//如果address_type为域名,此处第一字节为域名长度,其后为域名本身,无0字符结尾,域名后为真实主机绑定端口

}SOCKS5_REQUEST;

#endif

主程序来了:

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Socks5程序,只支持TCP代理

//版本0.1,作者云舒

//2007年1月9日凌晨1点15分,GF回家已经11天了。

//2008年1月25日修改,今年GF一直在我身边,哈哈

//

//参考:

//http://www.rfc-editor.org/rfc/rfc1928.txt

//http://www.rfc-editor.org/rfc/rfc1929.txt

//编译:

//gcc-osocks5-O2Socks5.c-lpthread(RedHatAS5测试)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include<stdio.h>

#include<netinet/in.h>

#include<netdb.h>

#include<sys/time.h>

#include<sys/types.h>

#include<unistd.h>

#include<stdlib.h>

#include<signal.h>

#include<pthread.h>

#include<errno.h>

#include<string.h>

#include<sys/socket.h>

#include<arpa/inet.h>

#include"Socks5.h"

#defineMAX_USER10

#defineBUFF_SIZE1024

#defineAUTH_CODE0x02

#defineTIME_OUT6000000

#defineUSER_NAME"yunshu"

#definePASS_WORD"ph4nt0m"

//Selectauthmethod,return0ifsuccess,-1iffailed

intSelectMethod(intsock)

{

charrecv_buffer[BUFF_SIZE]={0};

charreply_buffer[2]={0};

METHOD_SELECT_REQUEST*method_request;

METHOD_SELECT_RESPONSE*method_response;

//recvMETHOD_SELECT_REQUEST

intret=recv(sock,recv_buffer,BUFF_SIZE,0);

if(ret<=0)

{

perror("recverror");

close(sock);

return-1;

}

//printf("SelectMethod:recv%dbytes\n",ret);

//ifclientrequestawrongversionorawrongnumber_method

method_request=(METHOD_SELECT_REQUEST*)recv_buffer;

method_response=(METHOD_SELECT_RESPONSE*)reply_buffer;

method_response->version=VERSION;

//ifnotsocks5

if((int)method_request->version!=VERSION)

{

method_response->select_method=0xff;

send(sock,method_response,sizeof(METHOD_SELECT_RESPONSE),0);

close(sock);

return-1;

}

method_response->select_method=AUTH_CODE;

if(-1==send(sock,method_response,sizeof(METHOD_SELECT_RESPONSE),0))

{

close(sock);

return-1;

}

return0;

}

//testpassword,return0forsuccess.

intAuthPassword(intsock)

{

charrecv_buffer[BUFF_SIZE]={0};

charreply_buffer[BUFF_SIZE]={0};

AUTH_REQUEST*auth_request;

AUTH_RESPONSE*auth_response;

//authusernameandpassword

intret=recv(sock,recv_buffer,BUFF_SIZE,0);

if(ret<=0)

{

perror("recvusernameandpassworderror");

close(sock);

return-1;

}

//printf("AuthPass:recv%dbytes\n",ret);

auth_request=(AUTH_REQUEST*)recv_buffer;

memset(reply_buffer,0,BUFF_SIZE);

auth_response=(AUTH_RESPONSE*)reply_buffer;

auth_response->version=0x01;

charrecv_name[256]={0};

charrecv_pass[256]={0};

//auth_request->name_lenisachar,maxnumberis0xff

charpwd_str[2]={0};

strncpy(pwd_str,auth_request->name+auth_request->name_len,1);

intpwd_len=(int)pwd_str[0];

strncpy(recv_name,auth_request->name,auth_request->name_len);

strncpy(recv_pass,auth_request->name+auth_request->name_len+sizeof(auth_request->pwd_len),pwd_len);

//printf("username:%s\npassword:%s\n",recv_name,recv_pass);

//checkusernameandpassword

if((strncmp(recv_name,USER_NAME,strlen(USER_NAME))==0)&&

(strncmp(recv_pass,PASS_WORD,strlen(PASS_WORD))==0)

)

{

auth_response->result=0x00;

if(-1==send(sock,auth_response,sizeof(AUTH_RESPONSE),0))

{

close(sock);

return-1;

}

else

{

return0;

}

}

else

{

auth_response->result=0x01;

send(sock,auth_response,sizeof(AUTH_RESPONSE),0);

close(sock);

return-1;

}

}

//parsecommand,andtrytoconnectrealserver.

//returnsocketforsuccess,-1forfailed.

intParseCommand(intsock)

{

charrecv_buffer[BUFF_SIZE]={0};

charreply_buffer[BUFF_SIZE]={0};

SOCKS5_REQUEST*socks5_request;

SOCKS5_RESPONSE*socks5_response;

//recvcommand

intret=recv(sock,recv_buffer,BUFF_SIZE,0);

if(ret<=0)

{

perror("recvconnectcommanderror");

close(sock);

return-1;

}

socks5_request=(SOCKS5_REQUEST*)recv_buffer;

if((socks5_request->version!=VERSION)||(socks5_request->cmd!=CONNECT)||

(socks5_request->address_type==IPV6))

{

//printf("connectcommanderror.\n");

close(sock);

return-1;

}

//begainprocessconnectrequest

structsockaddr_insin;

memset((void*)&sin,0,sizeof(structsockaddr_in));

sin.sin_family=AF_INET;

//getrealserver&#39;sipaddress

if(socks5_request->address_type==IPV4)

{

memcpy(&sin.sin_addr.s_addr,&socks5_request->address_type+sizeof(socks5_request->address_type),4);

memcpy(&sin.sin_port,&socks5_request->address_type+sizeof(socks5_request->address_type)+4,2);

//printf("RealServer:%s%d\n",inet_ntoa(sin.sin_addr),ntohs(sin.sin_port));

}

elseif(socks5_request->address_type==DOMAIN)

{

chardomain_length=*(&socks5_request->address_type+sizeof(socks5_request->address_type));

chartarget_domain[256]={0};

strncpy(target_domain,&socks5_request->address_type+2,(unsignedint)domain_length);

//printf("target:%s\n",target_domain);

structhostent*phost=gethostbyname(target_domain);

if(phost==NULL)

{

//printf("Resolve%serror!\n",target_domain);

close(sock);

return-1;

}

memcpy(&sin.sin_addr,phost->h_addr_list[0],phost->h_length);

memcpy(&sin.sin_port,&socks5_request->address_type+sizeof(socks5_request->address_type)+

sizeof(domain_length)+domain_length,2);

}

//trytoconnecttorealserver

intreal_server_sock=socket(AF_INET,SOCK_STREAM,0);

if(real_server_sock<0)

{

perror("Socketcreationfailed\n");

close(sock);

return-1;

}

memset(reply_buffer,0,sizeof(BUFF_SIZE));

socks5_response=(SOCKS5_RESPONSE*)reply_buffer;

socks5_response->version=VERSION;

socks5_response->reserved=0x00;

socks5_response->address_type=0x01;

memset(socks5_response+4,0,6);

ret=connect(real_server_sock,(structsockaddr*)&sin,sizeof(structsockaddr_in));

if(ret==0)

{

socks5_response->reply=0x00;

if(-1==send(sock,socks5_response,10,0))

{

close(sock);

return-1;

}

}

else

{

perror("Connecttorealservererror");

socks5_response->reply=0x01;

send(sock,socks5_response,10,0);

close(sock);

return-1;

}

returnreal_server_sock;

}

intForwardData(intsock,intreal_server_sock)

{

charrecv_buffer[BUFF_SIZE]={0};

fd_setfd_read;

structtimevaltime_out;

time_out.tv_sec=0;

time_out.tv_usec=TIME_OUT;

intret=0;

while(1)

{

FD_ZERO(&fd_read);

FD_SET(sock,&fd_read);

FD_SET(real_server_sock,&fd_read);

ret=select((sock>real_server_sock?sock:real_server_sock)+1,&fd_read,NULL,NULL,&time_out);

if(-1==ret)

{

perror("selectsocketerror");

break;

}

elseif(0==ret)

{

//perror("selecttimeout");

continue;

}

//printf("[DEBUG]testingreadable!\n");

if(FD_ISSET(sock,&fd_read))

{

//printf("clientcanread!\n");

memset(recv_buffer,0,BUFF_SIZE);

ret=recv(sock,recv_buffer,BUFF_SIZE,0);

if(ret>0)

{

//printf("%s",recv_buffer);

//printf("recv%dbytesfromclient.\n",ret);

ret=send(real_server_sock,recv_buffer,ret,0);

if(ret==-1)

{

perror("senddatatorealservererror");

break;

}

//printf("send%dbytestoclient!\n",ret);

}

elseif(ret==0)

{

//printf("clientclosesocket.\n");

break;

}

else

{

//perror("recvfromclienterror");

break;

}

}

elseif(FD_ISSET(real_server_sock,&fd_read))

{

//printf("realservercanread!\n");

memset(recv_buffer,0,BUFF_SIZE);

ret=recv(real_server_sock,recv_buffer,BUFF_SIZE,0);

if(ret>0)

{

//printf("%s",recv_buffer);

//printf("recv%dbytesfromrealserver.\n",ret);

ret=send(sock,recv_buffer,ret,0);

if(ret==-1)

{

perror("senddatatoclienterror");

break;

}

}

elseif(ret==0)

{

//printf("realserverclosesocket.\n");

break;

}

else

{

perror("recvfromrealservererror");

break;

}

}

}

return0;

}

intSocks5(void*client_sock)

{

intsock=*(int*)client_sock;

if(SelectMethod(sock)==-1)

{

//printf("socksversionerror\n");

return-1;

}

if(AuthPassword(sock)==-1)

{

//printf("authpassworderror\n");

return-1;

}

intreal_server_sock=ParseCommand(sock);

if(real_server_sock==-1)

{

//printf("parsecommanderror.\n");

return-1;

}

ForwardData(sock,real_server_sock);

close(sock);

close(real_server_sock);

return0;

}

intmain(intargc,char*argv[])

{

if(argc!=2)

{

printf("Socks5proxyfortest,codebyYunShu\n");

printf("Usage:%s<proxy_port>\n",argv[0]);

printf("Options:\n");

printf("<proxy_port>---whichportofthisproxyserverwilllisten.\n");

return1;

}

structsockaddr_insin;

memset((void*)&sin,0,sizeof(structsockaddr_in));

sin.sin_family=AF_INET;

sin.sin_port=htons(atoi(argv[1]));

sin.sin_addr.s_addr=htonl(INADDR_ANY);

intlisten_sock=socket(AF_INET,SOCK_STREAM,0);

if(listen_sock<0)

{

perror("Socketcreationfailed\n");

return-1;

}

intopt=SO_REUSEADDR;

setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

if(bind(listen_sock,(structsockaddr*)&sin,sizeof(structsockaddr_in))<0)

{

perror("Binderror");

return-1;

}

if(listen(listen_sock,MAX_USER)<0)

{

perror("Listenerror");

return-1;

}

structsockaddr_incin;

intclient_sock;

intclient_len=sizeof(structsockaddr_in);

while(client_sock=accept(listen_sock,(structsockaddr*)&cin,(socklen_t*)&client_len))

{

printf("Connectedfrom%s,processing......\n",inet_ntoa(cin.sin_addr));

pthread_twork_thread;

if(pthread_create(&work_thread,NULL,(void*)Socks5,(void*)&client_sock))

{

perror("Createthreaderror...");

close(client_sock);

}

else

{

pthread_detach(work_thread);

}

}

}

相关推荐