Virtual Host Proxy Server

Environment: VC++ 6, Windows 95/98/NT

From time to time, I pick-up ideas from codeguru.com so I thought that I should contribute as well.

The program I'm submitting today is aimed at solving a problem that sounds simple but appears to be next to impossible: running multiple Web servers on a single Windows 95/98 machine. If you are running NT, you can assign multiple IP addresses to your networks card, edit the hosts file to translate domain names into IP addresses and assign multiple Websites to Internet Information Server...

It's a bit tricky but feasible. If you're running Windows 95 or 98, it's virtually impossible so I had to find a way around that.

What I've done is write a very simple proxy server that translate server names into a sub folder of your local machine so your can host as many Websites as you want with one single HTTP server.

Let's imagine your web root is C:\WebRoot\, you will put the files for http://www.a.com into C:\WebRoot\www.a.com\. The files for www.b.com will go in C:\WebRoot\www.b.com\ and so on.

What the proxy will actually do is replace http://www.a.com/index.htm by http://127.0.0.1/www.a.com/index.htm on the fly (127.0.0.1 is equivalent to localhost and is by definition the IP address of your local machine).

So to test the program, what you really need is a Web server, something as simple as Personal Web Server (PWS) from Microsoft and a browser (Netscape Navigator, Internet Explorer or anything else).

You have to create the directories for the virtual servers as mentioned above and you have to configure your browser to use a proxy.

Here is an example with Internet Explorer 5.0 from Microsoft (Tools>Internet Options>Connections>LAN Settings)

As you can see, by default the proxy is running on port 5060.

Something else you have to be aware of is that the proxy doesn't support HTTP 1.1. The way HTTP 1.1 handles connections is slightly more complicated than HTTP 1.0. To keep the code as simple as possible, I decided to support HTTP 1.0 only. Anyway it's the default behavior of the browser when you go through a proxy as you can see on the following screenshot of IE5.

The code is very basic and there are numerous ways to improve it but a) it solved my problem and b) it's short and easy to read. It also provides a very good example on how to use the CSocket classes which are very high level classes and not very well documented.



// VirtualHostProxy.cpp 
// // Virtual Host Proxy Server
// (c) Franck JEANNIN 1999 - fjeannin@linkguard.com
// // Simulate multiple Web servers on one single Windows 95/98 machine 
// // Does not support HTTP 1.1 (HTTP 1.0 only)
// Use high level MFC socket classes: CSocket
// #include "stdafx.h"
#include <afxsock.h> // MFC socket extensions
#include <conio.h>
#define BUFFERSIZE 10000
#define SERVERNAMEMAXSIZE 256
#define PROXYPORT 5060
#define SERVERADDRESS "127.0.0.1"
#define SERVERPORT 80
char Buffer[BUFFERSIZE+SERVERNAMEMAXSIZE];
int main(int argc, char* argv[])
{ CSocket Proxy;
CSocket Client;
CSocket Server;
// initialize MFC
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { printf("Fatal Error: MFC initialization failed\nPress any key\n"); getch(); return -1; } // initialize Socket support if (!AfxSocketInit()) { printf("Fatal Error: Socket initialization failed\nPress any key\n"); getch(); return -1; } // create Proxy socket if (!Proxy.Create(PROXYPORT)) { printf("Fatal Error: Proxy socket creation failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } if (!Proxy.Listen(1)) { printf("Fatal Error: Proxy socket activation failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } else { printf("Virtual Host Proxy Server started on port %d\n(c) Franck JEANNIN 1999\n\n",PROXYPORT); } while(1) { if (!Proxy.Accept(Client)) { printf("Fatal Error: Client connection to Proxy failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } int n = Client.Receive(Buffer,BUFFERSIZE); if (n == -1) { printf("Fatal Error: Client transmission to Proxy failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } Buffer[n] = 0; printf("Received from client: %s\n",Buffer); // calls to http://www.a.com/mypage.htm are transformed to calls to http://127.0.0.1/www.a.com/mypage.htm char* p = strstr(Buffer,"//"); if (p) { p += 2; memmove(p+sizeof(SERVERADDRESS),p,n); memcpy(p,SERVERADDRESS,sizeof(SERVERADDRESS)-1); *(p+sizeof(SERVERADDRESS)-1) = '/'; n += sizeof(SERVERADDRESS); } if (!Server.Create()) { printf("Fatal Error: Server socket creation failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } if (!Server.Connect(SERVERADDRESS,SERVERPORT)) { printf("Fatal Error: Server socket connection to HTTP server failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } n = Server.Send(Buffer,n); if (n == -1) { printf("Fatal Error: Proxy transmission to Server failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } Buffer[n] = 0; printf("Sent to server: %s\n",Buffer); while ( (n = Server.Receive(Buffer,BUFFERSIZE)) != 0) { if (n == -1) { printf("Fatal Error: Server transmission to Proxy failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } Buffer[n] = 0; printf("Received from server: %s\n",Buffer); n = Client.Send(Buffer,n); if (n == -1) { printf("Fatal Error: Proxy transmission to Server failed\nError %d\n\nPress any key\n",GetLastError()); getch(); return -1; } Buffer[n] = 0; printf("Sent to Client: %s\n",Buffer); }  printf("Closing Client & Server sockets\n"); Client.Close(); Server.Close(); } return 0; }

Download demo project - 47KB

History



Comments

  • Very good starting point

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

    Originally posted by: Edgar Leon

    Great and simple, I've succesfully modify it to meet my needs.

    I'm very thankfull

    Reply
  • "www.163.com" cann't be logged on, use the proxy

    Posted by Legacy on 10/25/2001 12:00am

    Originally posted by: wisber

    Your proxy don't work properly,
    the website "www.163.com" cann't be logged on.

    Reply
  • Virtual Host Proxy Server

    Posted by Legacy on 06/28/2001 12:00am

    Originally posted by: George

    Any ideas on how HTTP/1.1 persistant connections work?
    I have done some experimentation and I am still mystified.
    If I recv twice before sending something to the HTTP server I get a broken pipe, or error.

    Reply
  • Anyway you have to add .

    Posted by Legacy on 05/18/2001 12:00am

    Originally posted by: michel

    Very usefull for my first step in CSocket; Merci.

    Insert a CWinApp instance at the beginning of your main().
    for exemple CWinApp MyApp;
    Have a look to the "help" for AfxWinInit and AfxSocketInit.

    Reply
  • no response from client

    Posted by Legacy on 04/20/2001 12:00am

    Originally posted by: Adrian Austin

    Hi,
    Please Help. I found your code on the net. Good stuff. I'm currently trying to write a simple proxy server to sit in between our windows clients and the real proxy server. We're doing this so that we can do some clever authentication on client ip addresses.

    Anyway, I found your code and thought this was the answer. I'd already tried a very similar thing in visual basic.

    I still have a problem however,
    in the command prompt window it all seems to work great. The http request comes in, is sent to the proxy server and the correct response comes back BUT, when I step throught the code I can see that it thinks it has successfully sent the response back to the client but Internet Explorer just sits there and eventually times out. I can't work out why this is happening.

    Any ideas very much appretiated?

    Also, will this work for ftp and all other protocols?

    Reply
  • For me either

    Posted by Legacy on 03/13/2001 12:00am

    Originally posted by: Chris

    If I had a webpage with a graphic in it. The page would load the html page fine but would not continue loading graphics embedded in the page. It would stick on the while( n = server.receive(Buffer.BUFFERSIZE) ) != 0 ) line.

    If I change the logic to check to see if the last receive was less then BUFFERSIZE it works under DEBUG mode only. I am not an expert at this so my debugging that error was futile.

    Reply
  • Your proxy not work propery

    Posted by Legacy on 01/16/2000 12:00am

    Originally posted by: JP

    Your proxy not work propery

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

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • Due to internal controls and regulations, the amount of long term archival data is increasing every year. Since magnetic tape does not need to be periodically operated or connected to a power source, there will be no data loss because of performance degradation due to the drive actuator. Read this white paper to learn about a series of tests that determined magnetic tape is a reliable long-term storage solution for up to 30 years.

Most Popular Programming Stories

More for Developers

RSS Feeds