Hello!

I write my proxy server in C ++. Studied all man`s and standards. I implemented absolutely all the request methods that the HTTP protocol implies from GET to DELETE and now I am faced with the problem of processing the CONNECT method. I absolutely can not understand how to properly handle and forward it between the client and the server. If everything is simple with HTTP requests, a request of the following type has arrived:

GET http://examples.ru/i/20140904/source.js HTTP/1.1 Host: examples.ru Proxy-Connection: keep-alive Accept: */* User-Agent: Mozilla/5.0 (Windows NT 5.1) Chrome/41.0.2272.118 Safari/537.36 DNT: 1 Accept-Encoding: gzip, deflate, sdch Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 

We make the following of it:

 GET /i/20140904/source.js HTTP/1.1 Host: examples.ru Connection: keep-alive Accept: */* Accept-Encoding: gzip, deflate, sdch Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 User-Agent: Mozilla/5.0 (Windows NT 5.1) Chrome/41.0.2272.118 Safari/537.36 DNT: 1 

And we send this case to port 80 and look forward to hearing. We read the answer and close the connection if any of the subscribers specified "Connection: close" or if the server is no longer available. I opened the connection in general only for processing 1 request and closed it after receiving a response from the server.

But here I faced CONNECT, the request of a type comes:

 CONNECT www.google.ru:443 HTTP/1.1 Host: www.google.ru Proxy-Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) Chrome/40.0.2214.111 Safari/537.36 

Matter of course, that I redo it as follows:

 CONNECT / HTTP/1.1 Host: www.google.ru Connection: keep-alive 

And then send to the client the code 200 Connection Established. I receive data from the client, which I redirect to the server on port 443. At the next moment, a handshake should occur between the client and the server, which is probably what happens - an abracadabra comes from the server, which I send to the client, and I receive the same abracadabra from the client, which when I try to send to the server, an error occurs in the send () function 10053 - WSAECONNABORTED . And here I am so until the end and I can not understand how to properly handle the CONNECT HTTP method after all.

Please explain in detail how to handle it. Thank.

Here, actually code of how I process CONNECT.

  // Выше принимается запрос и парсится. // Создаем внешний сокет с сервером. t_error = createSocketClient( ThisClient ); if ( t_error == -1 ) return -1; t_error = sendStatusCodeToClient(ThisClient, 200); if ( t_error == -1 ) return -1; while ( true ) { // Прием запроса от клиента и передача серверу. while ( true ) { bytes_recv = recv(ThreadInfo[ThisClient].ClientSocket, &buffer[0], SIZE_BLOCK_4096, 0); if ( bytes_recv > 0 ) { flagData = true; bytes_send = send(ThreadInfo[ThisClient].ServerSocket, &buffer[0], bytes_recv, 0); if ( bytes_send == SOCKET_ERROR ) { return -1; } } else if ( bytes_recv == 0 ) break; else return -2; } if ( flagData == true ) { // Прием ответа от сервера и передача клиенту. while ( true ) { bytes_recv = recv(ThreadInfo[ThisClient].ServerSocket, &buffer[0], SIZE_BLOCK_8192, 0); if ( bytes_recv > 0 ) { bytes_send = send(ThreadInfo[ThisClient].ClientSocket, &buffer[0], bytes_recv, 0); if ( bytes_send == SOCKET_ERROR ) { return -3; } } else if ( bytes_recv == 0 ) break; else return -4; } } } 
  • something in this spirit is not read? - aleksandr barakin
  • Well, so I do. CONNECT comes to it, if I could connect to the specified server, send the response of Connection Connection Established to the client, then send what the client sent me to the server, to which I get the answer from the server, which is 5, and send it to the client, I receive from the client 6 and it costs me to send it to the server as I get an error in send () at number 10053. This should be, as I understand it, one connection session. - Vitali

3 answers 3

One of the reasons may be that the firewall blocks https connections, or any outgoing traffic that is not clear to it. Either an error in the logic of the program that closes the socket during the session, log your actions in the logs and see if this is so.

    And in my opinion everything is simpler, connect does not need to send anything to a remote server. It is necessary to establish a tcp connection and, if successful, reply to the client that everything is ok and only to the client. because in this tcp session, the handshake will first take place and only after that the client will send his GET to the encrypted channel or what he wanted to do there

      Yes, Mike correctly described, with the CONNECT method, the exchange of headers occurs only with the client, the parent proxy or the site do not send anything from the headers. Order:

      1. The client sends a request (as in your example)
      2. Your proxy server opens a socket with endpoint from this request, pre-resolving the host name from the request to the un IP address.
      3. If everything went well, your proxy should send a 200 Connection Established response to the client.
      4. All the exchange after this, the proxy transmits all data between the client and the endpoint.

      This scenario is for a client with an explicitly specified proxy server, if you use a transparent proxy using iptables, tproxy, etc., then the order is reduced by step 3, the answer 200 is not sent to the client, if his request was not a CONNECT method. In the case of 'transparent proxying' technologies, the endpoint address is taken from the socket, by means of getsockopt it is necessary to specify the flags SOL_IP, SO_ORIGINAL_DST. If you use the technology TPROXY , you must use the following construction to remove the address: setsockopt, SOL_IP, IP_TRANSPARENT. an example .

      If it is something encrypted, then it’s not destiny to see there :) And pay special attention to the sizes when transferring both headers and data. An incorrectly specified length of data in the HTTP header usually entails a lot of problems with different browsers. And quite crete when translating encrypted data.