主页 PC知识 网管技术 黑客帝国 安全技术 开放系统 程序设计 搜索 技术论坛

 

相关联接
 
RHU本级分类

编程语言
程序代码
WIN/*NIX编程
其他类别
JAVA专区

 
RHU阅读排行
·新欢乐时光病毒源代码
·ShixxNote 6.net缓冲区溢出代码
·“BBSxp 5.15”暴库工具源码
·Serv-u本地权限提升漏洞Exp源代码
·一个写硬盘的VBS脚本程序
·冲击波病毒源代码
·超级DDOS源码~每秒>4W
·socks5协议转http协议源码
·得到远程机器MAC地址源代码
·一个简单的CMDSHELL后门

 
 
RHU最新文章
·Python写的蜘蛛程序代码
·C#抓取alexa排名的代码
·一个超级mail蠕虫的诞生
·洪水攻击原理及代码实现全攻略(附源代码)
·修改了一个抓包的程序(c语言队列)
·企业内部AD脆弱密码审计
·用vbs加用户的绝妙方法
·黑客编程利用Debug Api 获得QQ2007密码
·Firewire搞定你的WIN PC的攻击代码来了
·机器狗写入到userinit.exe文件的下载者源码

 
 
RHU相关搜索









 
 
RHU广而告之

 
 
>您的位置:首页 -> 程序设计 -> 程序代码
socks5协议转http协议源码

作者:RHU-TAC编辑员 来自:RHU网络采集 时间:2005-3-31 双击滚屏 收藏本页 字体:


点击 查看RHU2004全年文章


socks5代理可以看rfc 1928
socks5的用户名口令认证方法看rfc 1929

http代理可以看 rfc2616
socks5代理可以支持tcp和udp 而http只支持tcp

所以这个代理转换器只支持tcp


写作原因
很多软件都有socks5认证方法 但是它们不支持http认证方法
而从原理上可以使用http认证方法(因为它们没有使用udp)
所以写这个软件可以方便的使其它程序可以使用http代理

如联众 或是foxmail

CODE

#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#define INIT_SOCKET(){WSADATA   wsadata;WSAStartup(MAKEWORD(2,2),&wsadata);}
#define CLOSESOCKET(x) closesocket(x)
#define CLEAN_SOCKET()  {WSACleanup();}
//  http.c  实现http代理功能

#define PROTO_EXCHANGE_TIMEOUT 15
#define PROTO_RECVRESP_TIMEOUT 75
#define PROTO_SENDRESP_TIMEOUT 10

#define WAIT_AND_RECV(sd,buf,len,waittime,recvflags)    do{\
   struct fd_set sset;\
   struct timeval waited;\
   waited.tv_sec   = waittime;waited.tv_usec   = 0;\
   FD_ZERO(&sset);FD_SET(sd,&sset);\
   if(select(sd+1,&sset,NULL,NULL,&waited) != 1 || (len = recv(sd,buf,len,recvflags)) == -1 )\
   len = -1;\
}while(0);

#define DEBUG_DUMP      printf

static int httpproxy_connect(const char*proxyaddr,int proxyport,
       const char*dstaddr,int dstport)
{
   int                 proxysd = -1;
   char                buf[2048];
   int                 len;
   char                *ptoken;
   int                 status;

   struct  sockaddr_in inaddr;

   if( !proxyaddr || !proxyaddr[0] || proxyport < 1
           ||!dstaddr || !dstaddr[0] )
       return -1;

   DEBUG_DUMP("代理:%s:%d,目标:%s:%d\n",proxyaddr,proxyport,dstaddr,dstport);

   len                 = sizeof(inaddr);
   memset(&inaddr,0,len);
   if( (inaddr.sin_addr.s_addr = inet_addr(proxyaddr) ) == INADDR_NONE )
       return -1;

   inaddr.sin_family    = AF_INET;
   inaddr.sin_port      = htons(proxyport);

   //  connect to proxy
   if((proxysd = socket(AF_INET,SOCK_STREAM,0)) == -1 )
       return -1;
   if( connect(proxysd,(struct sockaddr*)&inaddr,len))
       goto errorparse;

   //  发送connect请求并判断返回,根据HTTP协议说明,详细内容请看RFC2616
   //  HTTP代理使用CONNECT指令实现,CONNECT时指定选端的地址与端口号,
   //  当代理服务器返回成功后(状态值是2xx),后面的代理服务器不再对此连接的数据
   //  进行HTTP协议处理
   if( dstport > 0 )
       len = sprintf(buf,"CONNECT %s:%d HTTP/1.1\r\n\r\n",dstaddr,dstport);
   else
       len = sprintf(buf,"CONNECT %s HTTP/1.1\r\n\r\n",dstaddr);

   if( send(proxysd,buf,len,0) != len ){
       DEBUG_DUMP("发送CONNECT请求失败:包内容:%s\n",buf);
       goto errorparse;
   }

   len = sizeof(buf)-1;
   WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,MSG_PEEK);
   if( len == -1){
       DEBUG_DUMP("接收CONNECT响应失败\n");
       goto errorparse;
   }

   buf[len]    = 0;
   DEBUG_DUMP("CONNECT响应为:%s|\n",buf);
   if( 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);
   if( status < 300 && status > 199 ){
       ptoken  = strstr(buf,"\r\n\r\n");
       if( ptoken )
           len  = ptoken - buf +4;
       else{
           ptoken = strstr(buf,"\n\n");
           len  = ptoken - buf +2;
       }
       WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,0);
       return proxysd;
   }

errorparse:
   CLOSESOCKET(proxysd);
   return -1;
}

//  sd          [in]    使用socks5的客户端的连接id
//  proxyaddr   [in]    http代理地址
//  proxyport   [in]    http代理端口
//  return:
//          -1  失败
//          >=0 与http代理的连接id
static int socks5_accept(int sd,const char *proxyaddr,int proxyport)
{
   unsigned char       buf[512];
   int                 len = 2;
   int                 i   = 0;
   char                dstaddr[260];
   int                 dstport;

   if( !proxyaddr || !proxyaddr[0] || proxyport <1 )
       return -1;

   //  处理协商,现在只处理无认证情况,无论对方会不会处理这种情况
   //  没有要求无认证方式,sorry,那我就不理它
   //  另外只处理SOCKS5的CONNECT命令,其它不处理
   WAIT_AND_RECV(sd,(char*)buf,len,PROTO_EXCHANGE_TIMEOUT,0);
   if( len != 2 || buf[0] != 5 ){
       DEBUG_DUMP("接收socks5协商包失败,len:%d,buf[0]:%d\n",len,buf[0]);
       return -1;
   }
   len = buf[1];
   i   = len;
   WAIT_AND_RECV(sd,(char*)buf,i,PROTO_EXCHANGE_TIMEOUT,0);
   if( len != i ){
       DEBUG_DUMP("接收socks5协商包失败,想接收%d,收到:%d\n",len,i);
       return -1;
   }

   for( i = 0;i< len && buf[i];i++ );

   if( i == len ){
       DEBUG_DUMP("用户没有请求socks5无认证方法:\n");
       return -1;
   }

   buf[0]  = 5;
   buf[1]  = 0;
   if( send(sd,(char*)buf,2,0) != 2)
       return -1;

   len     = 5;
   WAIT_AND_RECV(sd,(char*)buf,len,PROTO_RECVRESP_TIMEOUT,0);
   if( 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]);
       return -1;
   }

   switch( buf[3] ){
       case 1:     //  是IP地址
           len = 5;
           WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0);
           if( len != 5 ){
               DEBUG_DUMP("处理socks5CONNECT命令[IP方式]失败:len:%d\n",len);
               return -1;
           }
           {
               struct in_addr  addr;
               memcpy((char*)&addr.s_addr,buf+4,4);
               strcpy(dstaddr,inet_ntoa(addr));
               dstport = ntohs(*(unsigned short*)(buf+8));
           }
           break;
       case 3:     //  是域方式
           len = buf[4]+2;
           WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0);
           if( len != buf[4]+2 ){
               DEBUG_DUMP("处理socks5CONNECT命令[域方式]失败:len:%d\n",len);
               return -1;
           }
           memcpy(dstaddr,buf+5,buf[4]);
           dstaddr[buf[4]] = 0;
           dstport     = ntohs(*(unsigned short*)(buf+5+buf[4]));
           break;
       default:
           DEBUG_DUMP("处理socks5CONNECT命令[]失败:未知方式:type:0x%x\n",buf[3]);
           return -1;
   }

   return httpproxy_connect(proxyaddr,proxyport,dstaddr,dstport);
}

int listenport(int port,const char*addr)
{
   int                 len = sizeof(struct sockaddr_in);
   struct sockaddr_in  bindaddr;

   int                 sd          = socket(AF_INET,SOCK_STREAM,0);
   if( sd == -1)
       return -1;

   memset(&bindaddr,0,len);
   bindaddr.sin_family             = AF_INET;
   bindaddr.sin_port               = htons(port);
   if( addr && addr[0] )
       bindaddr.sin_addr.s_addr    = inet_addr(addr);

   if( bind ( sd,(struct sockaddr*)&bindaddr,&len) || listen(sd,100 )){
       DEBUG_DUMP("打开端口失败,port:%d\n",port);
       CLOSESOCKET(sd);
       return -1;
   }

   return sd;
}

void running(int sd){
   int ad;
   if( sd == -1 )
       return;

   while(1){
       int proxyid;
       char    buf[10240];
       int     len;
       int     maxid;
       int     actcount;

       ad  = accept(sd,NULL,NULL);
       if( ad == -1 )
           break;

       DEBUG_DUMP("有客户连接,id:%d\n",ad);
       if((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_set   sset;
           FD_ZERO(&sset);
           FD_SET(ad,&sset);
           FD_SET(proxyid,&sset);

           actcount = select(maxid+1,&sset,NULL,NULL,&waittime);
           while(actcount > 0 ){
               int actid   = FD_ISSET(proxyid,&sset)?proxyid:ad;
               int sendid  = actid == ad? proxyid:ad;

               FD_CLR(actid,&sset);
   len = sizeof(buf)-1;
               WAIT_AND_RECV(actid,buf,len,10,0);
               if( len > 0 ){
    buf[len] = 0;
                   send(sendid,buf,len,0);
               DEBUG_DUMP("%d接口活动,内容为:%s\n",actid,buf);
   }
               else{
                   DEBUG_DUMP("接收失败,id:%d\n",actid);
                   CLOSESOCKET(ad);
                   ad  = -1;
                   break;
               }
               actcount --;
           }
       }
       //  某一方已经关闭,继续下一组转发
       CLOSESOCKET(proxyid);
   }
   CLOSESOCKET(sd);
}

main(){
   int ld;
   INIT_SOCKET();
   ld  = listenport(1080,NULL);
   if( ld != -1)
       running(ld);
   else
       DEBUG_DUMP("监听失败\n");
   CLEAN_SOCKET();
}
http及socks5代理只是在CONNECT时进行协商
后面的操作不需要附加的信息
同时代理也不会对数据进行解释 只是进行转发

这只是一个测试程序

可以自己使用httpproxy_connect与socks5_accept来实现自己的代理转换程序

另外在flashfxp上测试成功

在foxmail上还没有测试成功

主要函数说明
httpproxy_connect
通过http代理创建到目标机器的连接

socks5_accept
接收socks5连接请求,并把它转换成http代理,
创建http代理通道成功后返回http代理通道的socketid

以上两个失败都返回-1

创建成功后
客户端 <-数据-->socks5 sd <---数据--->http proxy sd<---->目标

OVER

[1] 页 RedHyphone.Union 投稿邮箱
[特别声明]:
本站文章大多搜索转载自网络中,如果侵犯了您的权利,请告之我们。本站将立即删除。
本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
查看评论】【向上滚屏】【关闭窗口】【 打印
-相关文章
  • 认知盲区 解惑双网卡双线路DNS解析
  • FlashFXP 简体中文版 3.7.5 Build 1303 Beta[烈火]
  • 确认:番茄花园作者洪磊被检察院批准逮捕
  • 1983年的今天 DNS诞生
  • Windows 2003 IIS 6.0搭建asp+.net+php+jsp+mysql+mssql
  • -文章评论 (关闭)
    ·还没有相关的评论!

    网上大名:
    红旋风网络技术联盟 RHUTech.Union
     
    Copyright © 2000-2007 RedHyphone.Union All Rights Reserved. 红旋风联盟版权所有.皖ICP备05011033号
    中国红旋风网络技术联盟 | www.RedHyphone.net
    Mailto:Redhyphone@gamil.com