专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »C 教程 » socks5代理服务器:Socks5代理服务 »正文

socks5代理服务器:Socks5代理服务

来源: 发布时间:星期四, 2009年2月12日 浏览:485次 评论:0


假期时候把socks5代理RFC全部读完了有些体会不敢独享在这里写出来大家起评论评论如有敬请提出

  下面假设使用TCP连接方式首先需要和代理服务器的间建立连接这里没什么复杂简单connect(serverIP, serverPort)就可以了连接成功的后需要使用send发送命令字以便确定是否需要验证下面是RFC里面命令字格式:

项目
版本
方式数目
连接方式


项目长度
1
1
1-255



  首先\"版本\"这项固定是 X\"05\"(socks version 5)方式数目告诉server究竟提交了几种连接方式请求至于连接方式则可以有多个下面就是方式列表:

连接方式
含义

X’00’
无需验证直接继续

X’01’
GSSAPI

X’02’
需要用户名/密码

X’03’ to X’7F’
IANA ASSIGNED

X’80’ to X’FE’
保留方式可以自己灵活选用

X’FF’
未包含符合要求方式


  接下来是server回应:

项目
版本
允许连接方式

项目长度
1
1


  版本不必说仍然固定是 X\"05\"允许连接方式则是在你提交众多连接方式中由server选出个可以接受然后返回来;如果没有那么返回就是 X\"FF\"其中般用到就是 X\"00\"X\"02\"它们的间区别就在于 X\"02\"方式需要发送用户名/密码验证通过后过程则和 X\"00\"方式没有任何区别

  客户端识别到server返回 X\"02\"的后发送下列格式验证字串:

项目
VER


用户名长度
用户名
密码长度
密码

项目长度
1
1
1-255
1
1-255


  注意:这里VER有别于上边固定是 X\"01\"用户名/密码最大长度是255

  server端验证完毕后返回结果:

项目
VER
验证结果

项目长度
1
1


  验证结果是 X\"00\"就表示验证通过否则都是不过…

  接下来过程就是发送请求命令字了:

项目
版本
命令字
保留
地址类型
地址
端口

项目长度
1
1
X\"00\"
1
不固定
2


  版本固定 X\"05\";命令字分 3种: CONNECT X\"01\"BIND X\"02\"UDP X\"03\"CONNECT就是普通TCP连接;BIND要求你client支持接受server连接请求(FTP协议就是个典型例子);UDP则是个特例我还没有完全理解… 保留项固定是 X\"00\"

  地址类型有 3种:X\"01\"、X\"03\"、X\"04\"分别对应IP-V4DOMAINNAMEIP-V6而接下来地址长度也根据地址类型区别而变化IP-V4长度是4位DOMAINNAME长度则根据实际情况变化但是地址内容要设成域名长度IP-V6就是16位

  端口长度固定两位没什么可说

  而server返回内容格式也大致相同

项目


版本
返回值
保留
地址类型
地址(BND)
端口

项目长度
1
1
X\"00\"
1
不固定
2


  返回值可能是下列值中个:

连接方式
含义

X’00’
成功

X’01’
general SOCKS server failure

X’02’
连接不符合server规格

X’03’
目标网络无法到达

X’04’
目标主机无法到达

X’05’
连接拒绝

X’06’
TTL expired

X’07’
命令不支持

X’08’
地址格式不支持

X’09 to X’FF’
保留


  估计各位看完上面解读的后仍然是头雾水那么我就来贴段代码大家就明白了

///////////////////////////////////////////////////////////////////
//
// socks 5 范例
//
//

unsigned char command[10];//准备连接命令字
mem(command,0,10);

command[0]=5;//版本号 05
command[1]=m_bUseSocks5Logon?2:1;//如果需要验证要发送两位方式字
command[2]=m_bUseSocks5Logon?2:0;
TRY
{
 Send(command,m_bUseSocks5Logon?4:3,0);
  num=Receive(command,2);
  (num!=2)
 {
  m_nProxyError=PROXYERROR_REQUESTFAILED;
   FALSE;
 }
}
CATCH_ALL(e)
{
 m_nProxyError=PROXYERROR_REQUESTFAILED;
  FALSE;
}
END_CATCH_ALL

(command[1]0xFF)
{
 m_nProxyError=PROXYERROR_AUTHREQUIRED;// 0xFF

表示失败没有合适连接方式
  FALSE;
}

(command[1])
{
  (command[1]!=2)
 {
  m_nProxyError=PROXYERROR_AUTHTYPEUNKNOWN;// 验证方式未知
   FALSE;
 }
  (m_bUseSocks5Logon)
 {
  unsigned char *buffer= unsigned
     char[3+m_ProxyUser.GetLength+m_ProxyPass.GetLength];
  sprf((char *)buffer,\" %s %s\",m_ProxyUser,m_ProxyPass);//分配用户名密码缓冲区
  buffer[0]=5;
  buffer[1]=m_ProxyUser.GetLength;
  buffer[2+m_ProxyUser.GetLength]=m_ProxyPass.GetLength;
  TRY
  {
   Send(buffer,3+m_ProxyUser.GetLength+m_ProxyPass.GetLength,0);
   //Get auth response
    num=Receive(command,2);
    (num!=2)
   {
    delete buffer;
    m_nProxyError=PROXYERROR_AUTHFAILED;
     FALSE;
   }
  }
  CATCH_ALL(e)
  {
   delete buffer;
   m_nProxyError=PROXYERROR_AUTHFAILED;
    FALSE;
  }
  END_CATCH_ALL

   (command[1]!=0x00)
  {
   delete buffer;
   m_nProxyError=PROXYERROR_AUTHFAILED;
    FALSE;
  }
  delete buffer;
 }
 
 {
  m_nProxyError=PROXYERROR_AUTHNOLOGON;
   FALSE;
 }
}

//构建请求
mem(command,0,10);
command[0]=5;
command[1]=1;
command[2]=0;
command[3]=1;
memcpy(&command[4],&sockAddr->sin_addr.S_un.S_addr,4);
memcpy(&command[8],&sockAddr->sin_port,2);

//上面只提供了IP-4地址方式其他可以自行更改代码

TRY
{
 Send(command,10,0);


  num=Receive(command,10);
  (num!=10)
 {
  m_nProxyError=PROXYERROR_REQUESTFAILED;
   FALSE;
 }
}
CATCH_ALL(e)
{
 m_nProxyError=PROXYERROR_REQUESTFAILED;
  FALSE;
}
END_CATCH_ALL

(command[1]!=0x00)
{
 m_nProxyError=PROXYERROR_REQUESTFAILED;
  FALSE;
}

  总的就是这个样子了如果还有不明白地方欢迎在论坛发贴询问

0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: