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?