博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

tomqq & security

网络安全/IDS/SSL-VPN/WEB技术/java/
  tomqq.cublog.cn

关于作者
姓名:tomqq
职业:挨踢的
位置:成都
个人介绍:2004年毕业于四川大学计算机应用专业,硕士学历,毕业后一直从事IDS和SSL-VPN的研发至今。Email:hekong@gmail.com

|| << >> ||
我的分类


http1.1,socks4,socks4a,socks5代理协议的原理和实现
由于最近需要实现VPN客户端对代理的支持,最近在实现这些代理的协议,主要实现java和c的版本。
java的版本好办,有一个java的proxy类,这个就内置了对代理协议的支持;
c的呢,就要自己来了。先动手看看协议。
协议很简单,我简要的说明一下:
socks4很简单,socks4a是协议4的扩展,主要是增加了域名解析而已,其他不变;socks5在4的基础上增加了各种验证的支持。
读协议之后,就是实现协议。首先安装一个ccproxy作为测试服务器,使用VC6作为开发环境,在网上搜索了一下,大部分要么是不全,要么就是根本没有测试过的代码,全是烂货一把。
为了方便他人实现同样的代码,我把最后测试通过的代码粘贴出来如下:
 
 

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")

class connect1{
public:
 connect1();
 int ConnectSocks5(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort);
 int ConnectSocks4(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort);
 int ConnectHttp(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort);
 to64frombits(unsigned char *out, const unsigned char *in, int inlen);
 test_sending(SOCKET s);
};

connect1::connect1(){
}

//return value:0=success; -1=connect failed; -2=wrong usr and psw

int connect1::ConnectSocks5(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort){
 /*BOOLEAN bNeedAuth = false;
 if(usr!=NULL)
  bNeedAuth = true;
 bNeedAuth = true;
 */

 
 int nLen = 0;
 char szBuffer[1024 + 1] = {""};
 /*if (!bNeedAuth) {
  szBuffer[0] = 5;
  szBuffer[1] = 1;
  szBuffer[2] = 0;
  nLen = 3;
  send(ProxySocket, szBuffer, nLen, 0);
  nLen = 2;
  recv(ProxySocket, szBuffer, nLen, 0);
  if(szBuffer[0] != 5 || szBuffer[1] != 0)
  {
   return -1;
  }
 }
 else */

 {
  szBuffer[0] = 5;
  szBuffer[1] = 2;
  szBuffer[2] = 0;
  szBuffer[3] = 2;
  nLen = 4;
  send(ProxySocket, szBuffer, nLen, 0);
  nLen = 2;
  recv(ProxySocket, szBuffer, nLen, 0);
  char *lpszUserName = usr;
  char *lpszPassword = psw;
  if(szBuffer[0] == 5)//need auth

  {
   if(szBuffer[1] == 2)
   {
    szBuffer[0] = 1;
    nLen = strlen(lpszUserName);
    szBuffer[1] = nLen;
    strncpy(szBuffer+2, lpszUserName,strlen(lpszUserName));
    nLen += 2;
    szBuffer[nLen] = strlen(lpszPassword);
    strcpy(szBuffer+nLen+1, lpszPassword);
    nLen = nLen + 1 + strlen(lpszPassword);
    send(ProxySocket, szBuffer, nLen, 0);
    nLen = 2;
    recv(ProxySocket, szBuffer, nLen, 0);
    if(szBuffer[1] != 0)
    {
     return -2;
    }
   }

  }
  
 }
 
 //translate DestAddr

 long v = inet_addr(DstHost);
 szBuffer[0] = 5;
 szBuffer[1] = 1;
 szBuffer[2] = 0;
 szBuffer[3] = 1;//ipv4

 szBuffer[4] = ((unsigned char *)&(v))[0];//10;

 szBuffer[5] = ((unsigned char *)&(v))[1];//23;

 szBuffer[6] = ((unsigned char *)&(v))[2];//7;

 szBuffer[7] = ((unsigned char *)&(v))[3];//197;

 unsigned short uPort = htons(DstPort);
 memcpy(szBuffer+8, &uPort, 2);
 nLen = 8 + 2;
 send(ProxySocket, szBuffer, nLen, 0);
 nLen = 10;
 recv(ProxySocket, szBuffer, nLen, 0);
 
 if(szBuffer[0] != 5 || szBuffer[1] != 0)
 {
  return -1;
 } else {
  //printf("Connect socks proxy ok!\n");

  return 0;
 }

 return 0;
}

//return value:0=success; -1=connect failed;

int connect1::ConnectSocks4(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort){
 BOOLEAN bNeedAuth = false;
 if(usr!=NULL)
  bNeedAuth = true;
 int nLen = 0;
 char szBuffer[1024 + 1] = {""};
  szBuffer[0] = 4;
  szBuffer[1] = 1;
  //szBuffer[2] = 0;

  unsigned short uPort = htons(DstPort);
  memcpy(szBuffer+2, &uPort, 2);
  long v = inet_addr(DstHost);
  szBuffer[4] = ((unsigned char *)&(v))[0];//10;

  szBuffer[5] = ((unsigned char *)&(v))[1];//23;

  szBuffer[6] = ((unsigned char *)&(v))[2];//7;

  szBuffer[7] = ((unsigned char *)&(v))[3];//197;

  
  nLen = 8;
  send(ProxySocket, szBuffer, nLen, 0);
  nLen = 8;
  recv(ProxySocket, szBuffer, nLen, 0);
  if(szBuffer[0] != 0 || szBuffer[1] != 90)
  {
   return -1;
  }
  else
  {
   //printf("Connect socks proxy ok!\n");

   return 0;
  }

 return 0;
}

//return value:0=success; -1=connect failed; -2=wrong usr and psw

int connect1::ConnectHttp(SOCKET ProxySocket,char *usr,char *psw,char *DstHost,int DstPort){
 BOOLEAN bNeedAuth = false;
 if(usr!=NULL)
  bNeedAuth = true;
 int nLen = 0;
 char szBuffer[1024 + 1] = {""};
 if (!bNeedAuth) {
  sprintf(szBuffer,"CONNECT %s:%d HTTP/1.0\r\n\r\n",DstHost,DstPort);
 }
 else
 {
  //Proxy-Authorization: Basic

  char szAuth[1024+1] = {""};
  char szAuthT[1024+1] = {""};
  sprintf(szAuthT, "%s:%s", usr, psw);
  to64frombits((unsigned char*)szAuth,(unsigned char*)szAuthT,strlen(szAuthT));
  sprintf(szBuffer, "CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization:Basic %s\r\n\r\n",DstHost,DstPort,szAuth);
 }
 
 nLen = strlen(szBuffer);
 send(ProxySocket, szBuffer, nLen, 0);
 nLen = 1024;
 recv(ProxySocket,szBuffer,nLen,0);
 if(strnicmp(szBuffer,"HTTP/1.0 200",strlen("HTTP/1.0 200"))==0 ||
  strnicmp(szBuffer,"HTTP/1.1 200",strlen("HTTP/1.1 200")) == 0)
  return 0;
 else
  return -1;
 
 return 0;
}

//base64 encode

connect1::to64frombits(unsigned char *out, const unsigned char *in, int inlen){
 const char base64digits[] =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 for (; inlen >= 3; inlen -= 3)
 {
  *out++ = base64digits[in[0] >> 2];
  *out++ = base64digits[((in[0] << 4) & 0x30)|(in[1] >> 4)];
  *out++ = base64digits[((in[1] << 2) & 0x3c)|(in[2] >> 6)];
  *out++ = base64digits[in[2] & 0x3f];
  in += 3;
 }
 if (inlen > 0)
 {
  unsigned char fragment;
  *out++ = base64digits[in[0] >> 2];
  fragment = (in[0] << 4) & 0x30;
  if (inlen > 1)
   fragment |= in[1] >> 4;
  *out++ = base64digits[fragment];
  *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
  *out++ = '=';
 }
 *out = NULL;
}

connect1::test_sending(SOCKET MySocket){
 //tests ending

 //+=+=+=+=+=

 char send_string [ ] =
  "CONNECT 10.23.7.194:443 HTTP/1.0\r\nUser-Agent: sslvpn\r\n\r\n";
 
 int nret = 0;
 nret = send( MySocket, send_string, sizeof( send_string ) -1, 0 );
 if( nret <= 0 )
 {
  printf("Could not send any data.");
  exit(1);
 }
 
 int MAX = 1024;
 char *recv_string = new char [MAX];
 memset(recv_string,0,MAX-1);
 nret = 0;
 nret = recv( MySocket, recv_string, MAX -1, 0 );
 if( nret <= 0 )
 {
  printf("Did not receive any data.");
  exit(1);
 }
  printf("%s\n",recv_string);
}

int main(){
 WSADATA wsaData;
 WORD wVersionRequested = MAKEWORD(2, 0);
 WSAStartup(wVersionRequested, &wsaData);
 
 if (WSAStartup(wVersionRequested, &wsaData) < 0 )
 {
  printf("Wrong version");
  exit(1);
 }
 
 SOCKET MySocket = socket(AF_INET, SOCK_STREAM, 0);
 char *targetip = "10.23.4.180";
 //char *targetip = "10.23.7.197";

 struct hostent *target_ptr = gethostbyname( targetip );
 
 if( target_ptr == NULL )
 {
  printf("Can not resolve name.");
  exit(1);
 }
 
 sockaddr_in sock;
 memcpy( &sock.sin_addr.s_addr, target_ptr->h_addr, target_ptr->h_length );
 sock.sin_family = AF_INET;
 sock.sin_port = htons( 1080 );
 
 if ( connect (MySocket, (struct sockaddr *)&sock, sizeof (sock) ) )
 {
  printf("Failed to connect proxy.\n");
  exit(1);
 }

 connect1 toms;
 connect1 *p;
 p = &toms;
 if(p->ConnectSocks5(MySocket,"tomqq","888888","10.23.7.197",808)!=0)
  printf("connect failed!\n");
 else
  //test connect

  p->test_sending(MySocket);

 return 0;
}

发表于: 2008-05-03,修改于: 2008-05-06 17:33,已浏览57次,有评论0条 推荐 投诉


网友评论
 发表评论