Why is Apache ignoring VirtualHost directive for first name in hosts file?

Posted by Peter Taylor on Pro Webmasters See other posts from Pro Webmasters or by Peter Taylor
Published on 2012-11-27T19:25:27Z Indexed on 2012/11/27 23:31 UTC
Read the original article Hit count: 527

Filed under:
|
|
|

Standard pre-emptive disclaimer: host names, IP addresses, and directories are anonymised.

Problem

We have a server with Apache 2.2 (WAMP) listening on one IP and IIS listening on another. An ASP.Net application running under IIS needs to do some simple GETs from the PHP applications running under Apache to build a unified search results page. This is a virtual server, so the internal IPs are mapped somehow to external ones. The internal DNS system doesn't resolve the publicly published names under which the applications are accessed externally, so the obvious solution was to add them to etc/hosts with the internal IP address:

127.0.0.1  localhost

# 10.0.1.17 is the IP address Apache listens on
10.0.1.17  phpappone.example.com
10.0.1.17  phpapptwo.example.com

After restarting Apache, phpappone.example.com stopped working. Instead of returning pages from that app, Apache was returning pages from the default site. The other PHP apps worked fine.

Relevant configuration

httpd.conf, summarised, says:

ServerAdmin [email protected]
ServerRoot  "c:/server/Apache2"
ServerName  www.example.com
Listen      10.0.1.17:80
Listen      10.0.1.17:443

# Not obviously related config options elided
# Nothing obviously astandard
# If you want more details, post a comment

DocumentRoot "c:/server/Apache2/htdocs"

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

# Fallback for unknown host names
<Directory "c:/server/Apache2/htdocs">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

# PHP apps common config
<Directory "C:/Inetpub/wwwroot/phpapps">
    Options FollowSymLinks -Indexes +ExecCGI
    AllowOverride All
    Order Allow,Deny
    Allow from All
</Directory>

# Virtual hosts

NameVirtualHost 10.0.1.17:80
NameVirtualHost 10.0.1.17:443

<VirtualHost _default_:80>
</VirtualHost>

<VirtualHost _default_:443>
  SSLEngine             On
  SSLCertificateFile    "certs/example.crt"
  SSLCertificateKeyFile "certs/example.key"
</VirtualHost>

Include conf/vhosts/*.conf

and the vhosts files are e.g.

<VirtualHost 10.0.1.17:80>
  ServerName    phpappone.example.com
  DocumentRoot  "c:/Inetpub/wwwroot/phpapps/phpappone"
</VirtualHost>

<VirtualHost 10.0.1.17:443>
  ServerName    phpappone.example.com
  DocumentRoot  "c:/Inetpub/wwwroot/phpapps/phpappone"

  SSLEngine             On
  SSLCertificateFile    "certs/example.crt"
  SSLCertificateKeyFile "certs/example.key"
</VirtualHost>

Buggy behaviour or our misunderstanding?

The documentation for name-based virtual hosts says that

Now when a request arrives, the server will first check if it is using an IP address that matches the NameVirtualHost. If it is, then it will look at each <VirtualHost> section with a matching IP address and try to find one where the ServerName or ServerAlias matches the requested hostname. If it finds one, then it uses the configuration for that server. If no matching virtual host is found, then the first listed virtual host that matches the IP address will be used.

Yet that isn't what we observe. It seems that if the hostname is the first hostname listed against the IP address in etc/hosts then it uses the configuration from the main server and skips the virtual host lookup.

Workarounds

The workaround we've put in place for the time being is to add a fake line to the hosts file:

127.0.0.1  localhost

# 10.0.1.17 is the IP address Apache listens on
10.0.1.17  fakename.example.com
10.0.1.17  phpappone.example.com
10.0.1.17  phpapptwo.example.com

This fixes the problem, but it's not very elegant. In addition, it seems a bit brittle: reordering lines in the hosts file (or deleting the nonsense value) can break it.

The other obvious workaround is to make the main server configuration match that of the troublesome virtual host, but that is equally brittle.

A third option, which is just ugly, would be to change the ASP.Net code to take separate config items for the IP address and the hostname and to implement HTTP manually. Ugh.

The question

Is there a good solution to this problem which localises any "Do not touch this!" explanations to the Apache config files?

© Pro Webmasters or respective owner

Related posts about apache

Related posts about httpd.conf