HTTP Tunneling (HTTP Proxy Socket Client)

Environment: VC6

HTTP Tunneling

HTTP is a text-based protocol to retreive Web pages through a Web browser. Mostly if you are on a LAN connection, you are behind a proxy server; this proxy server has one HTTP proxy running on some defined port. In your Internet Explorer's Connection option, you specify LAN settings as required. This proxy server is definitely running on a text-based protocol and you can only get HTTP-related data from the outside network, right!! Well, there is a small loophole from which you can go through HTTP and connect to the outside world and get any data you want in binary protocol, or even your own protocol. It's through HTTPS.

HTTPS Explanation

In HTTPS, data is transferred from browser to server and server to browser in a secure manner. It's a binary protocol; when it goes through a proxy, the proxy doesn't understand anything. The proxy just allows a binary stream to open and let both server and client exchange the data. Now, we can fool the proxy server and connect to any server and exchange data. The proxy server will think that we doing some secure HTTP session.

For HTTPS, your browser connects to a proxy server and sends a command.

CONNECT neurospeech.com:443 HTTP/1.0 <CR><LF>
HOST neurospeech.com:443<CR><LF>
[... other HTTP header lines ending with <CR><LF> if required]>
<CR><LF>    // Last Empty Line

Then, the proxy server treats this as some HTTP Secure Session, and opens a binary stream to the required server and port as defined. If a connection established, the proxy server returns the following response:

HTTP/1.0 200 Connection Established<CR><LF>
[.... other HTTP header lines ending with <CR><LF>..
ignore all of them]
<CR><LF>    // Last Empty Line

Now, the browser is connected to the end server and can exchange data in both a binary and secure form.

How to Do This

Now, it's your program's turn to fool the proxy server and behave as Internet Explorer behaves for Secure HTTP.

  1. Connect to Proxy Server first.
  2. Issue CONNECT Host:Port HTTP/1.1<CR><LF>.
  3. Issue <CR><LF>.
  4. Wait for a line of response. If it contains HTTP/1.X 200 , the connection is successful.
  5. Read further lines of response until you receive an empty line.
  6. Now, you are connected to outside world through a proxy. Do any data exchange you want.

Sample Source Code

  // You need to connect to mail.yahoo.com on port 25
  // Through a proxy on 192.0.1.1, on HTTP Proxy 4480
  // CSocketClient is Socket wrapping class
  // When you apply operator << on CString, it writes CString
  // To Socket ending with CRLF
  // When you apply operator >> on CString, it receives
  // a Line of response from socket until CRLF


  try
  {
    CString Request,Response;
    CSocketClient Client;

    Client.ConnectTo("192.0.1.1",4480);

    // Issue CONNECT Command
    Request = "CONNECT mail.yahoo.com:25 HTTP/1.0";
    Client<<Request;

    // Issue empty line
    Request = "";
    Client<<Request;

    // Receive Response From Server
    Client>>Response;

    // Ignore HTTP Version

    int n = Response.Find(' ');
    Response = Response.Mid(n+1);

    // Http Response Must be 200 only
    if(Response.Left(3)!="200")
    {
      // Connection refused from HTTP Proxy Server
      AfxMessageBox(Response);
    }


    // Read Response Lines until you receive an empty line.
    do
    {
      Client>>Response;
      if (Response.IsEmpty())
        break;
    }while (true);


    // Coooooooool.... Now connected to mail.yahoo.com:25
    // Do further SMTP Protocol here..

  }
  catch (CSocketException * pE)
  {
    pE->ReportError();
  }

Library Source Code

The Dns.h file contains all DNS-related source code. It uses other libraries, as SocketEx.h, SocketClient.h, and NeuroBuffer.h.

CSocketEx

Socket functions as a wrapper class. (CSocket is very heavy and unreliable if you don't have the exact idea of how it works.) All the functions are of same name as CSocket. You can use this class directly.

CSocketClient

Derived from CSocketEx and throws proper exceptions with details of Winsock errors. It defines two operators, >> and <<, for easy sending and receiving; it also changes network to host and host to network order of bytes if required.

CHttpProxySocketClient

Derived from CSocketClient, you can call the SetProxySettings(ProxyServer,Port) method and set proxy settings. Then, you can connect to the desired host and port as you need. The ConnectTo method is overridden and it automatically implements an HTTP proxy protocol and gives you a connection without any hassle.

How to Use CHttpProxySocketClient

  // e.g. You need to connect to mail.yahoo.com on port 25
  // Through a proxy on 192.0.1.1, on HTTP Proxy 4480
  // CSocketClient is Socket wrapping class
  // When you apply operator << on CString, it writes CString
  // To Socket ending with CRLF
  // When you apply operator >> on CString, it receives
  // Line of response from socket until CRLF
  try
  {
    CHttpProxySocketClient Client;

    Client.SetProxySettings("192.0.1.1",1979);

    // Connect to server mail.yahoo.com on port 25
    Client.ConnectTo("mail.yahoo.com",25);

    // You now have access to mail.yahoo.com on port 25
    // If you do not call SetProxySettings, then
    // you are connected to mail.yahoo.com directly if
    // you have direct access, so always use
    // CHttpProxySocketClient and no need to do any
    // extra coding.

  }
  catch(CSocketException * pE) {
    pE->ReportError();
  }
Note: I usually don't program in the form of .h and .cpp different files, because using them the next time somewhere else is a big problem because you must move both files here and there. So, I put all the code in my .h file only; I don't write to the .cpp file unless it's required. You need to copy only the SocketEx.h, SocketClient.h, and HttpProxySocket.h files into your project's directory, and add line

    #include "HttpProxySocket.h"
after your
#if !defined(.....
and so forth code of your Visual Studio-generated file. If you put anything above this, you will get n number of errors.

Downloads

Download source - 17 Kb


Comments

  • Also you can use a free http tunneling SDK, support http proxy, get it from http://www.networktunnel.net

    Posted by test118114 on 09/26/2010 10:09pm

    good

    Reply
  • Goodo<

    Posted by test118114 on 09/26/2010 10:08pm

    Also you can use a free http tunneling SDK, support http proxy, get it from http://www.networktunnel.net

    Reply
  • This is fantastic - available in C# ??

    Posted by gvanto on 08/23/2006 04:40am

    Is this app available in C# flavor? I'd so appreciate it (or any help on implementing it!) Thanks! gvanto@hotmail.com

    Reply
  • How to Upload a file to Sharepoint Server?

    Posted by sayeed_awed on 10/07/2004 08:11am

    Provide Solution

    Reply
  • How to connect thru proxy with authentication

    Posted by Legacy on 01/09/2004 12:00am

    Originally posted by: Rohan

    Hi my proxy server also happens to use authentication, How do i authenticate first and then transfer data?
    Please let me know..

    • How to connect thru proxy with authentication

      Posted by IMM on 02/01/2005 12:13pm

      Look at RFC 2616 14.33 'Proxy-Authenticate' and Proxy 14.34 'Proxy-Authorization' (http://www.ietf.org/rfc). You have to add following Http-Header to your Request: Proxy-Authorization: Base username:password [username:password has to be Base64 encoded. Use in .Net for example: System.Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes("username:password"))]

      Reply
    • How to connect thru proxy with authentication

      Posted by panlq on 06/17/2004 10:00pm

      How to connect thru proxy with authentication

      Reply
    Reply
  • Error in CSocketEx

    Posted by Legacy on 12/10/2003 12:00am

    Originally posted by: Johann Jobst

    Great Job!
    
    I think there is an error in this function.

    1 BOOL Close()
    2 {
    3 SOCKET hSocket = m_hSocket;
    4 m_hSocket = INVALID_SOCKET;
    5 if(m_hSocket != INVALID_SOCKET)
    6 {
    7 return (closesocket(hSocket) != SOCKET_ERROR);
    8 }
    9 return true;
    10 }
    ...
    Line 5 should be:

    5 if(hSocket != INVALID_SOCKET)

    • Not really

      Posted by firemaker on 10/17/2005 08:47am

      Well what you wrote is basically 2 negatives while you only wrote one so i think what he put down must be right

      Reply
    Reply
  • Where will i put the WSAstartup()?

    Posted by Legacy on 10/13/2003 12:00am

    Originally posted by: Celso D. Presa Jr.

    after executing the program an error occurs. could not connect to my proxy server.system error detail: either the application has not called wsastartup or wsastartup failed... can you help me? what will i do? i already copied your program but i don't know what else to do. thank you

    Reply
  • Could you provide an example please ?

    Posted by Legacy on 09/17/2003 12:00am

    Originally posted by: Francois

    Hello it seems great but I really don't understand how to use it.
    
    

    With such very small dev (the one I provide ;-)), I connect to a server socket.
    Can you impact this code to use your HttpProxy support.

    Thanks for everything.

    Regards


    #include <winsock.h>
    #pragma comment(lib, "wsock32.lib")

    void main()
    {
    WSADATA WSAData;
    WSAStartup(MAKEWORD(2,0), &WSAData);
    SOCKET sock;
    SOCKADDR_IN sin;
    char *buffer = new char[255];
    sock = socket(AF_INET, SOCK_STREAM, 0);
    sin.sin_addr.s_addr = inet_addr("10.0.2.85");
    sin.sin_port = htons(5901);

    sin.sin_family = AF_INET;
    connect(sock, (SOCKADDR *)&sin, sizeof(sin));

    recv(sock, buffer, 255, 0);

    closesocket(sock);
    WSACleanup();
    }

    Reply
  • some question

    Posted by Legacy on 08/07/2003 12:00am

    Originally posted by: Tony David

    First i can't connect any other ports except 443,although Mr. Kava have explained it,but i find myself not understood.
    
    and the most important is how can i find a way to connect a outside port except 443,because it's no use if i can connect that port only.

    Reply
  • Can't connect

    Posted by Legacy on 08/04/2003 12:00am

    Originally posted by: Phlip

    I'm trying to use the code in the first half of the page, and I can't get it to work...

    I connect to the proxy and send (as a test) "CONNECT www.google.com:80 HTTP/1.1\r\n\r\n" and then the socket to the proxy closes

    I know my proxy required a username and password to connect, and I suspect this is a cause of the problems.

    What am I doing wrong?

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 28, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT The Financial Services industry is a target today like never before, as attackers leverage different techniques to breach and exploit IT security. In recent months, there have been a number of high profile data breaches and attacks that have impacted the Financial Services industry. By examining the recent attacks, several key trends emerge about what attackers are targeting and how organizations can bolster their defenses. Join us for this …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds