Showing posts with label IIS. Show all posts
Showing posts with label IIS. Show all posts

Friday, April 11, 2014

IIS Reverse Proxy to multiple sites running under a single Node.js instance

Subtitled: How to setup Node.js to handle multiple sites and to run on Windows while IIS still occupies port 80


I did this on a Window 7 machine which was running IIS 7.5

 

Setting up your local box for testing

In your HOSTS file add some sites to test:
127.0.0.1     node1.com
127.0.0.1     node2.com
127.0.0.1     node3.com


IIS

Create a new web site in IIS:
Open IIS.
Right click on Sites.
"Add Web Site..."
Site Name: MyReverseProxy
Physical Path: C:\inetpub\wwwroot (can be anything as we're not going to use it)
Host name: node1.com
Now click on Bindings under Actions on RHS
Click Add.
Host name: node2.com
Click Add.
Host name: node3.com
Close.
You now have 3 host names running on port 80 on IIS and your HOSTS file will direct all local requests to this web site.

Click on MyReverseProxy on left panel. If the URL Rewrite widget is not under IIS then you might need to install it and might also need to add Application Request Routing (ARR). I can't remember if it came installed by default on IIS 7.5 or if I added it.

Open the URL Rewrite widget and click on Add Rule(s)...
Select a Reverse Proxy rule and click OK.
Server name: localhost:3000/ (or where the Node server is running.)
If you're using relative URLs in the Node.js code then you don't have to rewrite the domain names of the links in the HTTP responses. If you are using absolute names then you're in trouble if you're handling multiple domains as you won't know at this stage which one it's for. The only solution I have for this is to use relative URLs and DO NOT check the option to "Rewrite the domain names..."

Now start your Node.js application on port 3000 and try and access the sites node1.com, node2.com, and node3.com and they should all return the contents of your site running on port 3000.

We're not done yet. If, in Node.js/Express, you take a look at the req.headers.host value you will see that it reads "localhost:3000" and has not passed through the value you were expecting which was one of node1.com/node2.com/node3.com

To get this to work you need to go to this folder with an Administrator command prompt:
C:\Windows\System32\inetsrv
and run this command:
appcmd.exe set config -section:system.webServer/proxy /preserveHostHeader:"True" /commit:apphost

What this command will do is open this file:
C:\Windows\System32\inetsrv\config\applicationHost.config
and find the section called <system.webServer> and change this:
        <proxy enabled="true" />
 to this:
        <proxy enabled="true" preserveHostHeader="true" />
Recycle the app pool on your reverse proxy site in IIS and try and access it again. The host "head" property will be correctly set.

Now the final "thing" you want to do is to be able to handle multiple sites from your Node.js/Express application.

Here is some basic middleware in app/server.js that will switch between sites:
app.use(function(req, res, next) {
    console.log('Domain is: ' + req.headers.host);
    switch(req.headers.host) {
        case 'node1.com':
            break;
        case 'node2.com':
            break;
        case 'node3.com':
            break;
        default:
            console.log('Unknown domain: ' + req.headers.host);
            break;
    }
    next();
});

You would then setup routes that appropriately handled routes for each host that you were expecting. Where routes are ambiguous you would put a switch statement like above in there to arbitrate among domain functionality.

You could also put a node-proxy in front of these sites to switch between different node apps but then you're defeating the purpose of IIS which can already do that and more efficiently so I can't see the need for a node-proxy.

Some of the answers from this Stackoverflow question might help readers of this topic.

Tuesday, March 13, 2012

Install an HttpModule in IIS 7.5 on Server 2008 R2

Mostly for my own notes for when I next need to do this again. Assumes that the HttpModule has already been compiled and that you have the DLL.

Copy the DLL to the server and put in any folder.

Install the module into the GAC

  1. Right click on a command window and select "Run as administrator"
  2. At the command prompt type "explorer c:\windows\assembly" without the quotes.
  3. Find the folder that you copied the DLL to and while holding down the control key right click this folder and select "Open in a new window".
  4. Drag the HttpModule DLL from the new window and drop it into the c:\windows\assembly window.
  5. The HttpModule is now installed in the GAC.

Add the module to IIS 7.5

(This assumes a .NET 2.0 module (there's a good reason why it's .NET 2.0 and not 4))

  1. Open IIS and navigate to root. This is usually the machine name and adding the module here will ensure that it operates on all websites.
  2. In the Features View find the IIS section and double click on Modules.
  3. Click "Add Managed Module"
  4. In the Name field put any name you want.
  5. In the Type dropdown you should find the module that you added to the GAC above. Select this.
  6. Leave the "Invoke only for requests to ASP.NET applications or managed handlers" unchecked.
  7. Click OK and you're done.

This HttpModule will now execute against every request on all web sites.

Saturday, October 16, 2010

Improving security and reducing HTTP header size in IIS

I've identified four unnecessary HTTP header elements that get transmitted with one of my ASP.NET MVC2 web sites. I wanted to remove these headers to improve security and reduce header size and thought that it would be easy to remove these HTTP headers from IIS7 in the same manner. It turned out that each of them had to be removed with a different technique.

X-Powered-By: ASP.NET

This header is removed through the IIS Manager. You can remove it on a site by site basis or remove it for the server. If removed from the server then it's removed from all sites on that server. This is the approach I prefer.

  1. Bring up IIS Manager.
  2. Click on the server name in the left panel
  3. Under the IIS section in the server area you will see HTTP Response Headers, double click on this.
  4. Click on the line that says "X-Powered-By ASP.NET Local"
  5. In the Actions pane on the right click Remove.

Server: Microsoft-IIS/7.0

This one is a bit more tricky to remove and needed some code to be added to the web site.

In the MasterPage.master code behind file in the Page_Load function I put the following:

HttpContext.Current.Response.Headers.Remove("Server");

X-AspNet-Version    4.0.30319

To get rid of this one I had to edit the web.config file and set the enableVersionHeader attribute to false:

<httpRuntime enableVersionHeader="false" />

X-AspNetMvc-Version: 2.0

In the constructor for the Global class in the global.asax.cs file I set the static DisableMvcResponseHeader property of the MvcHandler class to true.

public Global()
{
      MvcHandler.DisableMvcResponseHeader = true;
}

Friday, February 5, 2010

Viewing connections to a server

I keep on forgetting how to do this so here it is documented for my convenience.

Start Performance Monitor (PerfMon)

Click + to add new monitor.

Enter computer's name

To view connections for a web service

From Performance object drop down select "Web Service"

From Select counters from list drop down select "Current Connections"

From Select instances from list select "_Total"

To view connections for a web app

From Performance object drop down select "ASP.NET Apps v2.0.50727"

Tuesday, August 4, 2009

Configuring IIS5 for ASP.NET MVC

I was trying to setup an ASP.NET MVC application to run under a virtual directory on IIS 5.1. When I click the properties on that virtual directory and then click the "Configuration..." button nothing happens - i.e. the configuration dialog doesn't pop up as it should. I suspect this is because I've also installed the IIS6 manager on this XP machine.

My objective is to Add an Application Extension Mapping to this virtual directory but I can't get into the configuration page which means I can't reach the Add/Edit Application Extension Mapping dialog either. Ironically I can get to this from the IIS6 manager but when I try and add the ".*" extension to the c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll executable I get the message "Wrong extension format." Not being able to add ".*" I added ".mvc" as a placeholder.

The solution is to use the IIS Metabase Explorer. You can install the Internet Information Services (6.0) Resource Kit Tools from here and one of the utilities installed will be the IIS Metabase Explorer.

Once open, navigate the tree in the left panel to LM > W3SVC > 1 > ROOT > AppName. Once selected, in the right panel you'll see a list of records, one of those will be ScriptMaps. Double click ScriptMaps and then scroll down the list until you find the .mvc placeholder. Double click this and change the ".mvc" to ".*" Click Apply and Save

Sunday, November 9, 2008

lsass.exe and SQL Server pegging CPU at 100%

Had an unusual problem with an MS Server 2003 today. The CPU was being pegged at 100% every 15 seconds for about 12 to 14 seconds. When I examined the Processes with Task Manager it showed that lsass.exe was the culprit and that its accomplices were sqlservr.exe and w3wp.exe.

This happened shortly after a deployment of a web site to the server that had been built on an x64 Server (2008) but deployed to an x86 Server (2003) - so I was considering this as a possible problem however I knew that I'd compiled the ASP.NET web app to target any CPU.

I found numerous references on the web to lsass.exe causing problems and also found this hotfix from Microsoft which I installed but it did not help: http://support.microsoft.com/kb/939268/ (when I say that it did not help I mean that it did not immediately fix the problem although it could have later added to a resolution by being there.)

After further hunting and examining event logs and server logs and disabling and stop and starting differenct web sites on the server I narrowed the problem down to one particular web site. This web site is an ASP.NET web app but also has a ASP Snitz forum in one of the sub-folders.

I tried taking the web site offline with the App_Offline.htm file and noticed that unlike when I stopped the web app the problem was still there. So I checked the forum and noticed that App_Offline only works with the ASP.NET part of the site and not the ASP part of the site.

This gave me a breakthrough in the hunt for a solution because I'd managed to separate the ASP and ASP.NET code and determined that it was the former. So I deleted the App_Offline.htm file and went into the forum admin page and took down the forum. The CPU usage immediately returned to normal and the pegging at 100% by lsass.exe and the others stopped.

Even though I'd isolated the problem to a small area I still didn't know what was causing this. Now this is the frustrating part: I switched the forum back online and the problem dissappeared. The CPU usage is back to normal and the problem gone. Although I'm happy that that problem's gone I'm frustrated that I don't know what caused it and fearful that it will return again.

Remember that I rebooted this server after I installed the MS KB patch metioned above which would have obviously stopped and restarted the web app and the forum code as well so I don't think that it was just a matter of stopping and starting it.

Friday, September 26, 2008

Hosts file locked (read-only) on Server 2008

I was trying to edit the HOSTS file on Windows Server 2008 with Notepad++ but after editing it wouldn't let me save it with a "Save failed" - "Please check whether if this file is opened in another program" (the ...whether if... is their message not my typo).

Anyhow, didn't turn out to be read-only as I initially thought or another process as suggested (I did try stopping several services to see if that would help) but instead it turned out to be the fact that I hadn't started Notepad++ as administrator.

I don't understand why I need to run Notepad++ as administrator to edit the HOSTS file but aparently I do. I'm sure that it's just a matter of getting used to this new Vista style UAC that I assume is the underpinning of the security model in Server 2008.

To run Notepad++ (or any other program) as an administrator just right click on the application and select "Run As Administrator."

Friday, June 6, 2008

Request object error

I came across an interesting problem today that I wanted to document in case I hit it again and provide some notes in the hope that this helps somebody else.

An ASP (not .net) forum that I'm responsible had the following error:

Request object error 'ASP 0104 :80004005'
Operation not Allowed
/forum/inc_UploadDefault.asp, line 4

The message wasn't that useful but I finally tracked down that it came from trying to upload a file to the ASP forum that was larger than 200 Kb.

It turns out that IIS 6.0 prevents the uploading of files larger than 200 Kb. This is not a big deal and I would expect there to be some sort of default limit.

What I did find unusual though were the steps that I had to go through to increase this limit.

  1. Stop "IIS Admin Service" - this also stopped "Word Wide Web Publishing Service", "FTP Publishing Service", and "HTTP SSL"
  2. Edit the C:\WINDOWS\system32\inetsrv\MetaBase.xml file and find the entry that read AspMaxRequestEntityAllowed="204800" and change this to read a larger value.
  3. Save the file.
  4. Restart the 4 services.

I would have expected to be able to change this entry through an interface but it appeared that I had to stop the sites to do this. If anybody knows a more elegant way to do this then please post a comment.