http转socks5:socks5协议转http协议源码来源: 发布时间:星期六, 2009年9月12日 浏览:59次 评论:0
作者:无双 来源:http://www.loveunix.net/
socks5代理可以看rfc 1928 socks5用户名口令认证思路方法看rfc 1929 http代理可以看 rfc2616 socks5代理可以支持tcp和udp 而http只支持tcp 所以这个代理转换器只支持tcp 写作原因 很多软件Software都有socks5认证思路方法 但是它们不支持http认证思路方法 而从原理上可以使用http认证思路方法(它们没有使用udp) 所以写这个软件Software可以方便使其它可以使用http代理 如联众 或是foxmail CODE # # # # INIT_SOCKET{WSADATA wsadata;WSAStartup(MAKEWORD(2,2),&wsadata);} # CLOSESOCKET(x) close(x) # CLEAN_SOCKET {WSACleanup;} // http.c 实现http代理功能 # PROTO_EXCHANGE_TIMEOUT 15 # PROTO_RECVRESP_TIMEOUT 75 # PROTO_SENDRESP_TIMEOUT 10 # WAIT_AND_RECV(sd,buf,len,waittime,recvflags) do{\ struct fd_ s;\ struct timeval waited;\ waited.tv_sec = waittime;waited.tv_usec = 0;\ FD_ZERO(&s);FD_SET(sd,&s);\ (select(sd+1,&s,NULL,NULL,&waited) != 1 || (len = recv(sd,buf,len,recvflags)) -1 )\ len = -1;\ }while(0); # DEBUG_DUMP prf httpproxy_connect(const char*proxyaddr, proxyport, const char*dstaddr, dstport) { proxysd = -1; char buf[2048]; len; char *ptoken; status; struct sockaddr_in inaddr; ( !proxyaddr || !proxyaddr[0] || proxyport < 1 ||!dstaddr || !dstaddr[0] ) -1; DEBUG_DUMP("代理:%s:%d,目标:%s:%d\n",proxyaddr,proxyport,dstaddr,dstport); len = (inaddr); mem(&inaddr,0,len); ( (inaddr.sin_addr.s_addr = inet_addr(proxyaddr) ) INADDR_NONE ) -1; inaddr.sin_family = AF_INET; inaddr.sin_port = htons(proxyport); // connect to proxy ((proxysd = (AF_INET,SOCK_STREAM,0)) -1 ) -1; ( connect(proxysd,(struct sockaddr*)&inaddr,len)) goto errorparse; // 发送connect请求并判断返回,根据HTTP协议介绍说明,详细内容请看RFC2616 // HTTP代理使用CONNECT指令实现CONNECT时指定选端地址和端口号, // 当代理服务器返回成功后(状态值是2xx),后面代理服务器不再对此连接数据 // 进行HTTP协议处理 ( dstport > 0 ) len = sprf(buf,"CONNECT %s:%d HTTP/1.1\r\n\r\n",dstaddr,dstport); len = sprf(buf,"CONNECT %s HTTP/1.1\r\n\r\n",dstaddr); ( send(proxysd,buf,len,0) != len ){ DEBUG_DUMP("发送CONNECT请求失败:包内容:%s\n",buf); goto errorparse; } len = (buf)-1; WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,MSG_PEEK); ( len -1){ DEBUG_DUMP("接收CONNECT响应失败\n"); goto errorparse; } buf[len] = 0; DEBUG_DUMP("CONNECT响应为:%s|\n",buf); ( strnicmp(buf,"HTTP/1.",7) || (!strstr(buf,"\r\n\r\n") && !strstr(buf,"\n\n"))) goto errorparse; ptoken = buf; while(!isspace(*ptoken) && *ptoken) ptoken ; status = atoi(ptoken); ( status < 300 && status > 199 ){ ptoken = strstr(buf,"\r\n\r\n"); ( ptoken ) len = ptoken - buf +4; { ptoken = strstr(buf,"\n\n"); len = ptoken - buf +2; } WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,0); proxysd; } errorparse: CLOSESOCKET(proxysd); -1; } // sd [in] 使用socks5客户端连接id // proxyaddr [in] http代理地址 // proxyport [in] http代理端口 // : // -1 失败 // >=0 和http代理连接id socks5_accept( sd,const char *proxyaddr, proxyport) { unsigned char buf[512]; len = 2; i = 0; char dstaddr[260]; dstport; ( !proxyaddr || !proxyaddr[0] || proxyport <1 ) -1; // 处理协商,现在只处理无认证情况,无论对方会不会处理这种情况 // 没有要求无认证方式,sorry,那我就不理它 // 另外只处理SOCKS5CONNECT命令,其它不处理 WAIT_AND_RECV(sd,(char*)buf,len,PROTO_EXCHANGE_TIMEOUT,0); ( len != 2 || buf[0] != 5 ){ DEBUG_DUMP("接收socks5协商包失败,len:%d,buf[0]:%d\n",len,buf[0]); -1; } len = buf[1]; i = len; WAIT_AND_RECV(sd,(char*)buf,i,PROTO_EXCHANGE_TIMEOUT,0); ( len != i ){ DEBUG_DUMP("接收socks5协商包失败,想接收%d,收到:%d\n",len,i); -1; } for( i = 0;i< len && buf[i];i ); ( i len ){ DEBUG_DUMP("用户没有请求socks5无认证思路方法:\n"); -1; } buf[0] = 5; buf[1] = 0; ( send(sd,(char*)buf,2,0) != 2) -1; len = 5; WAIT_AND_RECV(sd,(char*)buf,len,PROTO_RECVRESP_TIMEOUT,0); ( len != 5 || buf[0] != 5 || buf[1] != 1 ){ DEBUG_DUMP("处理socks5CONNECT命令失败:len:%d,buf[0]:0x%x,buf[1]:0x%x\n",len,buf[0],buf[1]); -1; } switch( buf[3] ){ 1: // 是IP地址 len = 5; WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0); ( len != 5 ){ DEBUG_DUMP("处理socks5CONNECT命令[IP方式]失败:len:%d\n",len); -1; } { struct in_addr addr; memcpy((char*)&addr.s_addr,buf+4,4); strcpy(dstaddr,inet_ntoa(addr)); dstport = ntohs(*(unsigned *)(buf+8)); } ; 3: // 是域方式 len = buf[4]+2; WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0); ( len != buf[4]+2 ){ DEBUG_DUMP("处理socks5CONNECT命令[域方式]失败:len:%d\n",len); -1; } memcpy(dstaddr,buf+5,buf[4]); dstaddr[buf[4]] = 0; dstport = ntohs(*(unsigned *)(buf+5+buf[4])); ; default: DEBUG_DUMP("处理socks5CONNECT命令失败:未知方式:type:0x%x\n",buf[3]); -1; } httpproxy_connect(proxyaddr,proxyport,dstaddr,dstport); } listenport( port,const char*addr) { len = (struct sockaddr_in); struct sockaddr_in bindaddr; sd = (AF_INET,SOCK_STREAM,0); ( sd -1) -1; mem(&bindaddr,0,len); bindaddr.sin_family = AF_INET; bindaddr.sin_port = htons(port); ( addr && addr[0] ) bindaddr.sin_addr.s_addr = inet_addr(addr); ( bind ( sd,(struct sockaddr*)&bindaddr,&len) || listen(sd,100 )){ DEBUG_DUMP("打开端口失败,port:%d\n",port); CLOSESOCKET(sd); -1; } sd; } void running( sd){ ad; ( sd -1 ) ; while(1){ proxyid; char buf[10240]; len; maxid; actcount; ad = accept(sd,NULL,NULL); ( ad -1 ) ; DEBUG_DUMP("有客户连接,id:%d\n",ad); ((proxyid = socks5_accept(ad,"172.16.68.21",80)) -1 ){ CLOSESOCKET(ad); continue; } // 进行代理转发工作 maxid = ad > proxyid? ad:proxyid; while( ad > -1 ){ struct timeval waittime = {10,0}; struct fd_ s; FD_ZERO(&s); FD_SET(ad,&s); FD_SET(proxyid,&s); actcount = select(maxid+1,&s,NULL,NULL,&waittime); while(actcount > 0 ){ actid = FD_ISSET(proxyid,&s)?proxyid:ad; sendid = actid ad? proxyid:ad; FD_CLR(actid,&s); len = (buf)-1; WAIT_AND_RECV(actid,buf,len,10,0); ( len > 0 ){ buf[len] = 0; send(sendid,buf,len,0); DEBUG_DUMP("%d接口活动,内容为:%s\n",actid,buf); } { DEBUG_DUMP("接收失败,id:%d\n",actid); CLOSESOCKET(ad); ad = -1; ; } actcount --; } } // 某方已经关闭,继续下组转发 CLOSESOCKET(proxyid); } CLOSESOCKET(sd); } { ld; INIT_SOCKET; ld = listenport(1080,NULL); ( ld != -1) running(ld); DEBUG_DUMP("监听失败\n"); CLEAN_SOCKET; } http及socks5代理只是在CONNECT时进行协商 后面操作不需要附加信息 同时代理也不会对数据进行解释 只是进行转发 这只是个测试 可以自己使用httpproxy_connect和socks5_accept来实现自己代理转换 另外在flashfxp上测试成功 在foxmail上还没有测试成功 主要介绍说明 httpproxy_connect 通过http代理创建到目标机器连接 socks5_accept 接收socks5连接请求,并把它转换成http代理, 创建http代理通道成功后返回http代理通道id 以上两个失败都返回-1 创建成功后 客户端 <-数据-->socks5 sd <---数据--->http proxy sd<---->目标 0
相关文章读者评论发表评论 |