Apache2, IIS, ASP.NET


Apache2 SSL on Windows

In August 2006, I was running Apache 2.0.x on Windows for Subversion and I needed to get SSL working so I could access my repository securely (e.g. with a "https" URL). This turned out to be a bit more difficult than I thought it would be. The Apache2 installer for Windows does not come with SSL, because that requires OpenSSL which is a completely different package. You can get a version containing it, but you won't get a fancy installer.

So ... this tutorial will show you how to manually install Apache2 with SSL support. I will show you how to create a self-signed certificate which is secure, but will cause web browsers to issue a warning, because it won't be from/signed-by a trusted Certificate Authority such as GeoTrust or Verisign.

Attention Apache 2.2.x Users! Luke Holladay wrote apache223ssl.doc for you. It modifies my instructions for use with Apache 2.2.x. I haven't tried them myself and cannot answer questions about it; I'm still using Apache 2.0.x and the instructions on this page are targeted to that version which I sometimes refer to as Apache2 for short.

1. Install OpenSSL

OpenSSL from Hunter

OpenSSL is free but the main site only distributes source code. They have a binary distributions page that only links to an installer made by Shining Light Productions. I haven't tried that because I don't want any more crap in Add/Remove Programs.

Instead, I download the latest Openssl-version-Win32.zip from hunter, which is presently Openssl-0.9.8b-Win32.zip. It's about 1mb and is usually about the second link on the page. Don't get the links that say "Apache" in them just yet, be patient.

Unzip the file somewhere on your computer and copy all the libeay32.dll and ssleay32.dll to your Windows\System32 directory. If you've dealt with SSL at all before, especially as a developer, you might already have copies of these there. Keep whatever is newest.

openssl version

For a basic sanity check, open a command prompt and go to the directory where you unzipped OpenSSL. Run openssl version and it should report both the version of OpenSSL, matching what was embedded in the ZIP you downloaded, as well as when it was built. Generally the more recent, the better.

You'll also need an openssl.cnf which is an OpenSSL configuration file that, for some reason, doesn't come with Hunter's distribution. Download this one or this one and save it to the folder where you unzipped OpenSSL.

2. Create Self-Signed Certificate

Several files related to your your SSL certificate will be created in this section, so choose a common base name to use. In my examples I use "blarg", which I've italicised to show it should be replaced by your choice. In practice, I recommend extracting the essence from your domain name; for example, if I was creating a certificate for https://www.neilstuff.com/ then I'd use "neilstuff".

Open up a command prompt and go to the directory where you unzipped OpenSSL and run the following command to create a new certificate request:

openssl req -config openssl.cnf -new -out blarg.csr -keyout blarg.pem

openssl req

You'll be prompted to answer many questions, which ones depend on your openssl.cnf file; all except two of these can be left blank:

Now it's time to create a non-password protected key for Apache 2.0.X by executing the following:

openssl rsa -in blarg.pem -out blarg.key

The only thing you'll be asked is the password you had used. Your resulting KEY file is essential the same thing as the PEM, just not password protected.

Before we go on, delete the .rnd file. This contains entropy information which could be used by malicious people to try and crack your certificate later on (if they get a hold of it).

Finally, run the following command to create an X.509 certificate, e.g. the kind of certificate that SSL likes to munch:

openssl x509 -in blarg.csr -out blarg.cert -req -signkey blarg.key -days 365

openssl x509

Congratulations, you've created a self-signed certificate! Keep the KEY and CERT files some place safe, we'll be using them soon.

3. Install Apache 2.0.X w/ mod_ssl.so

You can skip this section if you already have Apache 2 installed with mod_ssl.so.

Apache2 from Hunter

Back to hunter to download the latest Apache2 binary distribution for Windows with SSL, which is presently Apache_2.0.59-Openssl_0.9.8b-Win32.zip. It's about 6.5mb and is usually about the third link on the page.

Create a folder for this such as C:\Program Files\Apache Group\Apache2 and unzip the contents there.

Open conf\httpd.conf in a text editor and ...

If you want to have Apache2 listen on a different port than 80 (the default), change the Listen and ServerName directives in conf\httpd.conf.

httpd.conf Listen

Open a command prompt, get to the bin directory (under the folder you created), and run the following command to install Apache2 as a service:

apache -k install

apache install (service)

Anytime you wish to start Apache2, you can go to the same directory and run apache -k start. Restarting and stopping are much the same except you'll specify "restart" and "stop" after the "-k". It's also possible to just use the NET START and NET STOP commands you're probably familiar with; the name of the service for those commands will be "Apache2".

3. Enable SSL in Apache 2.0.X

Open up conf\httpd.conf in a text editor and look for the line LoadModule ssl_module modules/mod_ssl.so and remove any pound sign (#) characters preceding it. If you don't see that line where it probably should be (among the other LoadModule lines), then your installation may not have mod_ssl.so ... can't help you there!

httpd.conf LoadModule mod_ssl.so

Also, while you're in conf\httpd.conf, make sure the following lines exist somewhere (they should if you got Apache2 from hunter):

<IfModule mod_ssl.c>
    Include conf/ssl.conf

Create a directory under conf called ssl and copy the blarg.key and blarg.cert files there; the ones you created in step 2.

ssl.conf general

Crack open conf\ssl.conf in a text editor and ...

If IIS is installed, it will listen on port 443 (default for HTTPS) and drop any connections made to it. Apache2 doesn't appear to report a problem when it can't listen for SSL, so you might just see that weird dropped connection behavior. I recommend using a port besides 443 if you're running Apache2 side-by-side with IIS.

Restart the Apache2 service and voila! You got Apache2 running with SSL on Windows!


Common IIS + ASP.NET Issues

Here are various things I've encountered while setting up and/or managing ASP.NET websites using IIS, and how I solved them. Feel free to email me additions, comments, and/or questions.

HTTP 404: The page cannot be found. (ASMX or ASPX)

IIS 6+ is setup to return a 404 on executable types that are unrecognized or prohibited. This is the case with both ASP.NET 1.1 and 2.0.

  1. Open the "Internet Information Services (IIS) Manager" under "Administrative Tools".
  2. Navigate to the "Web Service Extensions" node.
  3. Select "ASP.NET v1.1.4322" or "ASP.NET v2.0.50727" in the right pane.
  4. Click "Allow".

If you don't see the expected version of ASP.NET listed under "Web Service Extensions", it's typically because IIS was installed after .NET. You can run the aspnet_regiis.exe utility to remedy this:

  1. Get to a command prompt, e.g. Start>Run "cmd".
  2. Enter "CD /D C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322" or "CD /D C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727" depending on which version of ASP.NET.
  3. Enter "aspnet_regiis.exe -i".
  4. Wait for the finished message; "Start installing ASP.NET (1.1.4322.0)" or "Start installing ASP.NET (2.0.50727.0)" depending on which version of ASP.NET.
  5. Follow the previous set of steps to enabled ASP.NET in Web Service Extensions.

A Windows Authentication dialog box is popping up when trying to view ASPX; it won't accept any credentials and eventually will display a "Not Authorized" error page.

ASP.NET is getting an Access Denied error when trying to use "C:\Windows\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\". The identity used by the application pool does not have read/write permissions to that directory.

"Service Unavailable"

Check the System Event Log (run "eventvwr /s"). You should see and Error and maybe a Warning as well from the W3SVC Source at the time you were trying to view the web site/service. One of these will give you a slightly more specific problem which should be resolved in this document.

"A failure was encountered while launching the process serving application pool 'blarg'. The application pool has been disabled."

The most likely cause is the identity specified could not be used for the application pool. In this case there should be a warning that occurred just before this error in the Event Log which is detailed below.

"The identity of application pool '%1' is invalid, so the World Wide Web Publishing Service can not create a worker process to serve the application pool. Therefore, the application pool has been disabled."

A user is considered invalid if it isn't a member of IIS_WPG (Internet Information Services Worker Process Group) or it hasn't been granted the right to logon as a service. To check and possibly fix the latter, follow these steps:

  1. Run Local Security Policy applet which is usually under Administrative Tools or you can Start>Run with "secpol.msc".
  2. Expand the Local Policies node and click User Rights Assignment.
  3. Open the "Log on as service" policy either by double-clicking or right-clicking and selecting Properties.
  4. Click "Add User or Group..." and enter the name of the user for the app pool's identity.
  5. Restart the machine. The security policy is only read on boot.

If this doesn't solve the problem, or for more detailed information you can check the Security Event Log for the user you specified as the identity around the time the problem occurred. There will usually be three entries under the categories: Logon/Logoff, Privilege Use, and then another Logon/Logoff. You can look at these to see what privileges that user was granted when it logged in, what came up when privileges were queried, etc. It's fairly hefty material.

A FileNotFound exception is being thrown for a DLL and the filename is always different.

Generally this is caused by the constructor of components created on the fly with XmlSerializer, such as SOAP client classes. Make sure the user the process is running under (the identity of the application pool for websites) has read/write permissions to the system temp directory, i.e. "C:\WINDOWS\TEMP\".

"Configuration Error: File or assembly name Blarg, or one of it's dependencies, was not found."

This is the equivalent of the ol' "Module not found" error from regsvr32 which didn't tell you what it was looking for that it didn't find either. Most commonly this will be msvcr71d.dll, and it's because you're using a debug version of the assembly.

"Mutex could not be created."

This can happen on ASP.NET sites when you attempt to change application pools while IIS is still running. The surest fix is simply an IISRESET. Unless the IIS service itself is restarted, there doesn't appear to be any way to fix this.

"Parameter is incorrect."

If you get this when setting up a new website with the IIS Manager then it could be that the DefaultAppPool has been deleted. If that's the case, then just select an existing app pool in the website properties.

"No primary driver specified in configuration"

The ASP.NET application can't find its "web.config" file.


Comments or questions? Email me at webmaster@neilstuff.com.