Introduction
A reverse proxy is the same as a proxy except instead of delivering pages for internal users, it delivers them for external users. It can be used to take some load off web servers and provide an additional layer of protection. If you have a content server that has sensitive information that must remain secure, you can set up a proxy outside the firewall as a stand-in for your content server. When outside clients try to access the content server, they are sent to the proxy server instead. The real content resides on your content server, safely inside the firewall. The proxy server resides outside the firewall, and appears to the client to be the content server.
Where to use?
If you have an intranet with IP filtered security, you can offer the functionality of external consultation. You must just add the authentication system of your choice.
Functionality
This reverse proxy can run in two modes:
- Mode 0: all web sites can be requested by clients with an URL like http://RevrseProxyURL/http//www.site.com/
- Mode 1: only one web site can be requested. When the user requests the web application address, the proxy returns the content of this web site.
You can setup this mode in the web configuration file of you web application:
<appSettings>
-->
<add key="ProxyMode" value="1" />
<add key="RemoteWebSite" value="http://www.codeproject.com/">http://www.codeproject.com/" />
</appSettings>
The code
Create an HttpHandler
to intercept all requests:
using System;
using System.Configuration;
using System.Web;
using System.Net;
using System.Text;
using System.IO;
namespace ReverseProxy
{
public class ReverseProxy: IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
fileint proxyMode =
Convert.ToInt32(ConfigurationSettings.AppSettings["ProxyMode"]);
string remoteWebSite =
ConfigurationSettings.AppSettings["RemoteWebSite"];
string remoteUrl;
if (proxyMode==0)
remoteUrl= ParseURL(context.Request.Url.AbsoluteUri);
acceptedelseremoteUrl=
context.Request.Url.AbsoluteUri.Replace("http://"+
context.Request.Url.Host+
context.Request.ApplicationPath,remoteWebSite);
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create(remoteUrl);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse ();
}
catch(System.Net.WebException we)
{
context.Response.StatusCode = 404;
context.Response.StatusDescription = "Not Found";
context.Response.Write("<h2>Page not found</h2>");
context.Response.End();
return;
}
Stream receiveStream = response.GetResponseStream();
if ((response.ContentType.ToLower().IndexOf("html")>=0)
||(response.ContentType.ToLower().IndexOf("javascript")>=0))
{
StreamReader readStream =
new StreamReader (receiveStream, Encoding.Default);
Uri test = new Uri(remoteUrl);
string content;
if (proxyMode==0)
content= ParseHtmlResponse(readStream.ReadToEnd(),
context.Request.ApplicationPath+"/http//"+test.Host);
else
content= ParseHtmlResponse(readStream.ReadToEnd(),
context.Request.ApplicationPath);
context.Response.Write(content);
response.Close();
context.Response.End();
}
else
{
Contentbyte[] buff = new byte[1024];
int bytes = 0;
while( ( bytes = receiveStream.Read( buff, 0, 1024 ) ) > 0 )
{
context.Response.OutputStream.Write (buff, 0, bytes );
}
response.Close();
context.Response.End();
}
}
public string ParseURL(string url)
{
if (url.IndexOf("http/")>=0)
{
string externalUrl=url.Substring(url.IndexOf("http/"));
return externalUrl.Replace("http/","http://") ;
}
else
return url;
}
public string ParseHtmlResponse(string html,string appPath)
{
html=html.Replace("\"/","\""+appPath+"/");
html=html.Replace("'/","'"+appPath+"/");
html=html.Replace("=/","="+appPath+"/");
return html;
}
public bool IsReusable
{
get
{
return true;
}
}
}
}
Configure the handler in web.config
You must add these lines in web.config file to redirect all user queries to the HTTPHandler
:
<httpHandlers>
<add verb="*" path="*" type="ReverseProxy.ReverseProxy, ReverseProxy" />
</httpHandlers>
Configure IIS
If you want to process a request with any file extension, then you need to change IIS to pass all requests through to the ASP.NET ISAPI extension. Add the HEAD, GET and POST verbs to all files with .* file extension and map those to the ASP.NET ISAPI extension - aspnet_isapi.dll (in your .NET framework directory). The complete range of mappings, includes the new .* mapping.
TODO's
Now, you can develop your own security system, based on form, Windows or passport authentication.