2012-03-06 99 views
3

我已阅读SSL TUNNELING INTERNET-DRAFT of December 1995并设置了一个HTTP透明代理,可与未加密的流量完美协作。如何通过透明代理实现SSL隧道?

看了上面的,还有GOOGLE了我的脑袋,被接受的方法是通过代理来创建安全流量的隧道似乎是:

连接请求的主机,然后让代理发送“HTTP 200 ...”确认消息返回给客户端,然后从这一点简单地传递客户端和服务器之间所有进一步的数据流量。然而,当我尝试这样做时,客户端(Chrome浏览器)使用三个wingdings字符来响应“HTTP 200 ...”消息,这些字符将转发给远程主机。此时没有回应,连接失败。

这里是我使用这个代码,具有连接到主机后:

if((*request=='C')&&(*(request+1)=='O')&&(*(request+2)=='N')&&(*(request+3)=='N')) 
{ 

    int recvLen; 

    send(output,htok,strlen(htok),0); //htok looks like "HTTP/1.0 200 Connection Established\nProxy-Agent: this_proxy\r\n\r\n" 

    std::memset(buff,0,bSize); 
    int total; 
     int bytes; 
     int n; 
     char cdata[MAXDATA]; 
     while ((recvLen = recv(output, buff, bSize-1,0)) > 0) //recving from client - here we get wingdings 
     { 
      memset(cdata,0, MAXDATA); 
      strcat(cdata, buff); 
      while(recvLen>=bSize-1)//just in case buff is too small 
      { 
       std::memset(buff,0,bSize); 
       recvLen=recv(output,buff,bSize-1,0); 
       strcat(cdata, buff); 
      } 

      total = 0; 
      bytes = strlen(cdata);      
      cout << cdata << endl;//how I see the wingdings 
      while (total < strlen(cdata)) 
      {  
       n = send(requestSock, cdata + total, bytes,0);//forwarding to remote host 
       if(n == SOCKET_ERROR) 
       { 
        cout << "secure sending error" << endl; 
        break; 
       } 
       total += n; 
       bytes -= n; 
      } 

      std::memset(buff,0,bSize); 
      recvLen=recv(requestSock, buff, bSize,0);//get reply from remote host 
      if (recvLen > 0) 
      { 
       do 
       { 
        cout<<"Thread "<<threadid<<" [Connection:Secure]: "<<recvLen<<endl; 


        send(output, buff, recvLen,0);//forward all to client 

        recvLen= recv(requestSock, buff, bSize,0); 

        if(0==recvLen || SOCKET_ERROR==recvLen)   
        { 
         cout<<"finished secure receiving or socket error"<<endl; 
         break; 
        } 

       }while(true); 
      } 
         }//end while, loop checks again for client data 

任何人能发现我的方式错误?

+0

send()调用可以发送少于recvLen,并且您忽略这个事实。另一个问题是将SSL中的二进制数据作为文本处理(您的代码可以用于文本HTTP请求,但无论如何都会以二进制数据失败)。 – 2012-03-06 07:02:44

回答

3

您的代码比必要的复杂得多。只需读入char数组,保存返回的长度,然后在同一个数组中写入多个字节,直到recv()返回零。 4行代码包括两个大括号。不要尝试收集整个传入的消息,只是传递任何进来的消息。否则,你只是增加延迟和编程错误。摆脱所有的strXXX()调用。

+0

最初我是这么做的,但后来想看看什么时候没有发生什么样的数据来自客户端。一个客户端'你好'应该包含超过3个wingding chars ... – 2012-03-06 02:53:19

+0

@PhilipLangford将二进制数据作为ASCII处理并不会告诉你任何有用的东西。同样,称他们为'wingdings'是徒劳的。什么是字节的实际值? – EJP 2012-03-06 03:02:14

+0

我接受了您的建议并简化了传输,现在可以看到字节交换,但是,我的逻辑导致远程主机无法完成其请求的无限循环。 伪代码: 'while(recv from client> 0) { 发送给主机; while(recv from host> 0) send to client; } – 2012-03-06 18:06:26

2

我不认为你应该作一个假设,交通不包含ASCII字符NUL

  strcat(cdata, buff); 
     } 

     total = 0; 
     bytes = strlen(cdata); 

如果有ASCII NUL S上的数据流中,这些都将失败。

+0

好点。我这样做是通过使用std :: string来保存几个周期,但网络操作可能会使这种效应无效。 – 2012-03-06 02:47:11

+0

'std :: string'也不好处理'0x00'字节。二进制数据是_binary_,不能使用字符串类来处理。 EJP的回答表明比我更好的方法 - 根本不要试图解释数据。 – sarnold 2012-03-06 08:45:52