7126N/A<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
7126N/A<
TITLE>An In-Depth Discussion of VirtualHost Matching</
TITLE>
7126N/A<!-- Background white, links blue (unvisited), navy (visited), red (active) --> 7126N/A<
h1 ALIGN="CENTER">An In-Depth Discussion of VirtualHost Matching</
H1>
7126N/A<
P>This is a very rough document that was probably out of date the moment
7126N/Ait was written. It attempts to explain exactly what the code does when
7126N/Adeciding what virtual host to serve a hit from. It's provided on the
7126N/Aassumption that something is better than nothing. The server version
7126N/Aunder discussion is Apache 1.2.
7126N/A<
P>If you just want to "make it work" without understanding
7126N/Ahow, there's a <
A HREF="#whatworks">What Works</
A> section at the bottom.
7126N/A<
h3>Config File Parsing</
h3>
7126N/A<
P>There is a main_server which consists of all the definitions appearing
7126N/Aoutside of <
CODE>VirtualHost</
CODE> sections. There are virtual servers,
7126N/Acalled <
EM>vhosts</
EM>, which are defined by
7126N/A><
SAMP>VirtualHost</
SAMP></
A>
7141N/A><
SAMP>ServerName</
SAMP></
A>,
7126N/A><
SAMP>ServerPath</
SAMP></
A>,
7126N/A><
SAMP>ServerAlias</
SAMP></
A>
7126N/Acan appear anywhere within the definition of
7126N/Aa server. However, each appearance overrides the previous appearance
7126N/A<
P>The default value of the <
CODE>Port</
CODE> field for main_server
7126N/Ais 80. The main_server has no default <
CODE>ServerName</
CODE>,
7126N/A<
CODE>ServerPath</
CODE>, or <
CODE>ServerAlias</
CODE>.
7141N/Adirectives, the (final if there
7126N/Aare multiple) <
CODE>Port</
CODE> directive in the main_server indicates
7126N/Awhich port httpd will listen on.
7126N/A<
P> The <
CODE>Port</
CODE> and <
CODE>ServerName</
CODE> directives for
7126N/Aany server main or virtual are used when generating URLs such as during
7126N/A<
P> Each address appearing in the <
CODE>VirtualHost</
CODE> directive
7126N/Acan have an optional port. If the port is unspecified it defaults to
7126N/Athe value of the main_server's most recent <
CODE>Port</
CODE> statement.
7126N/AThe special port <
SAMP>*</
SAMP> indicates a wildcard that matches any port.
7126N/ACollectively the entire set of addresses (including multiple
7126N/Aresults from DNS lookups) are called the vhost's <
EM>address set</
EM>.
7126N/A<
P> The magic <
CODE>_default_</
CODE> address has significance during
7126N/Athe matching algorithm. It essentially matches any unspecified address.
7126N/A<
P> After parsing the <
CODE>VirtualHost</
CODE> directive, the vhost server
7126N/Ais given a default <
CODE>Port</
CODE> equal to the port assigned to the
7126N/Afirst name in its <
CODE>VirtualHost</
CODE> directive. The complete
7126N/Alist of names in the <
CODE>VirtualHost</
CODE> directive are treated
7126N/Ajust like a <
CODE>ServerAlias</
CODE> (but are not overridden by any
7126N/A<
CODE>ServerAlias</
CODE> statement). Note that subsequent <
CODE>Port</
CODE>
7126N/Astatements for this vhost will not affect the ports assigned in the
7126N/AAll vhosts are stored in a list which is in the reverse order that
7126N/Athey appeared in the config file. For example, if the config file is:
7126N/AThen the list will be ordered: main_server, C, B, A. Keep this in mind.
7141N/AAfter parsing has completed, the list of servers is scanned, and various
7126N/Amerges and default values are set. In particular:
7126N/A ><
CODE>ServerAdmin</
CODE></
A>,
7126N/A ><
CODE>ResourceConfig</
CODE></
A>,
7126N/A ><
CODE>AccessConfig</
CODE></
A>,
7126N/A ><
CODE>KeepAliveTimeout</
CODE></
A>,
7126N/A ><
CODE>KeepAlive</
CODE></
A>,
7263N/A ><
CODE>MaxKeepAliveRequests</
CODE></
A>,
7126N/A ><
CODE>SendBufferSize</
CODE></
A>
7126N/A directive then the respective value is
7126N/A inherited from the main_server. (That is, inherited from whatever
7126N/A the final setting of that value is in the main_server.)
7126N/A<
LI>The "lookup defaults" that define the default directory
7126N/A for a vhost are merged with those of the main server. This includes
7126N/A any per-directory configuration information for any module.
7126N/A<
LI>The per-server configs for each module from the main_server are
7126N/A merged into the vhost server.
7126N/AEssentially, the main_server is treated as "defaults" or a
7126N/Awhich to build each vhost. But the positioning of these main_server
7126N/Adefinitions in the config file is largely irrelevant -- the entire
7126N/Aconfig of the main_server has been parsed when this final merging occurs.
7126N/ASo even if a main_server definition appears after a vhost definition
7126N/Ait might affect the vhost definition.
7126N/A<
P> If the main_server has no <
CODE>ServerName</
CODE> at this point,
7126N/Athen the hostname of the machine that httpd is running on is used
7126N/Ainstead. We will call the <
EM>main_server address set</
EM> those IP
7126N/Aaddresses returned by a DNS lookup on the <
CODE>ServerName</
CODE> of
7126N/A<
P> Now a pass is made through the vhosts to fill in any missing
7126N/A<
CODE>ServerName</
CODE> fields and to classify the vhost as either
7126N/Aan <
EM>IP-based</
EM> vhost or a <
EM>name-based</
EM> vhost. A vhost is
7126N/Aconsidered a name-based vhost if any of its address set overlaps the
7126N/Amain_server (the port associated with each address must match the
7126N/Amain_server's <
CODE>Port</
CODE>). Otherwise it is considered an IP-based
7126N/A<
P> For any undefined <
CODE>ServerName</
CODE> fields, a name-based vhost
7126N/Adefaults to the address given first in the <
CODE>VirtualHost</
CODE>
7126N/Astatement defining the vhost. Any vhost that includes the magic
7126N/A<
SAMP>_default_</
SAMP> wildcard is given the same <
CODE>ServerName</
CODE> as
7126N/Athe main_server. Otherwise the vhost (which is necessarily an IP-based
7126N/Avhost) is given a <
CODE>ServerName</
CODE> based on the result of a reverse
7141N/ADNS lookup on the first address given in the <
CODE>VirtualHost</
CODE>
7126N/A<
P><
STRONG>Apache 1.3 differs from what is documented
7126N/Ahere, and documentation still has to be written.</
STRONG>
7126N/AThe server determines which vhost to use for a request as follows:
7126N/A<
P> <
CODE>find_virtual_server</
CODE>: When the connection is first made
7126N/Aby the client, the local IP address (the IP address to which the client
7126N/Aconnected) is looked up in the server list. A vhost is matched if it
7126N/Ais an IP-based vhost, the IP address matches and the port matches
7126N/A(taking into account wildcards).
7141N/A<
P> If no vhosts are matched then the last occurrence, if it appears,
7126N/Aof a <
SAMP>_default_</
SAMP> address (which if you recall the ordering of the
7126N/Aserver list mentioned above means that this would be the first occurrence
7126N/Aof <
SAMP>_default_</
SAMP> in the config file) is matched.
7126N/A<
P> In any event, if nothing above has matched, then the main_server is
7126N/A<
P> The vhost resulting from the above search is stored with data
7126N/Aabout the connection. We'll call this the <
EM>connection vhost</
EM>.
7141N/AThe connection vhost is constant over all requests in a particular
TCP/
IP 7126N/A<
P> For each request made on the connection the following sequence of
7126N/Aevents further determines the actual vhost that will be used to serve
7126N/A<
P> <
CODE>check_fulluri</
CODE>: If the requestURI is an absoluteURI, that
7126N/Adetermine if the hostname's address (and optional port) match that of
7126N/Athe connection vhost. If it does then the hostname portion of the URI
7126N/Ais saved as the <
EM>request_hostname</
EM>. If it does not match, then the
7126N/AURI remains untouched. <
STRONG>Note</
STRONG>: to achieve this address
7126N/Athe hostname supplied goes through a DNS lookup unless it matches the
7126N/A<
CODE>ServerName</
CODE> or the local IP address of the client's socket.
7126N/A<
P> <
CODE>parse_uri</
CODE>: If the URI begins with a protocol
7126N/A(<
EM>
i.e.</
EM>, <
CODE>http:</
CODE>, <
CODE>ftp:</
CODE>) then the request is
7126N/Aconsidered a proxy request. Note that even though we may have stripped
7126N/A<
P> <
CODE>read_request</
CODE>: If the request does not have a hostname
7126N/Afrom the earlier step, then any <
CODE>Host:</
CODE> header sent by the
7126N/Aclient is used as the request hostname.
7126N/A<
P> <
CODE>check_hostalias</
CODE>: If the request now has a hostname,
7126N/Athen an attempt is made to match for this hostname. The first step
7126N/Aof this match is to compare any port, if one was given in the request,
7126N/Aagainst the <
CODE>Port</
CODE> field of the connection vhost. If there's
7126N/Aa mismatch then the vhost used for the request is the connection vhost.
7126N/A(This is a bug, see observations.)
7126N/AIf the port matches, then httpd scans the list of vhosts starting with
7126N/Athe next server <
STRONG>after</
STRONG> the connection vhost. This scan does not
7126N/Astop if there are any matches, it goes through all possible vhosts,
7126N/Aand in the end uses the last match it found. The comparisons performed
7126N/A<
LI>Compare the request hostname:port with the vhost
7126N/A <
CODE>ServerName</
CODE> and <
CODE>Port</
CODE>.
7126N/A<
LI>Compare the request hostname against any and all addresses given in
7126N/A the <
CODE>VirtualHost</
CODE> directive for this vhost.
7126N/A<
LI>Compare the request hostname against the <
CODE>ServerAlias</
CODE>
7126N/A<
CODE>check_serverpath</
CODE>: If the request has no hostname
7126N/A(back up a few paragraphs) then a scan similar to the one
7126N/Ain <
CODE>check_hostalias</
CODE> is performed to match any
7146N/A<
CODE>ServerPath</
CODE> directives given in the vhosts. Note that the
7126N/A<
STRONG>last match</
STRONG> is used regardless (again consider the ordering of
7146N/A<
LI>It is difficult to define an IP-based vhost for the machine's
7126N/A "main IP address". You essentially have to create a bogus
7126N/A <
CODE>ServerName</
CODE> for the main_server that does not match the
7126N/A<
LI>During the scans in both <
CODE>check_hostalias</
CODE> and
7126N/A <
CODE>check_serverpath</
CODE> no check is made that the vhost being
7146N/A scanned is actually a name-based vhost. This means, for example, that
7126N/A it's possible to match an IP-based vhost through another address. But
7126N/A because the scan starts in the vhost list at the first vhost that
7126N/A matched the local IP address of the connection, not all IP-based vhosts
7126N/A Consider the config file above with three vhosts A, B, C. Suppose
7126N/A that B is a named-based vhost, and A and C are IP-based vhosts. If
7126N/A a request comes in on B or C's address containing a header
7126N/A "<
SAMP>Host: A</
SAMP>" then
7126N/A it will be served from A's config. If a request comes in on A's
7126N/A address then it will always be served from A's config regardless of
7126N/A<
LI>Unless you have a <
SAMP>_default_</
SAMP> vhost,
7126N/A it doesn't matter if you mix name-based vhosts in amongst IP-based
7126N/A vhosts. During the <
CODE>find_virtual_server</
CODE> phase above no
7126N/A named-based vhost will be matched, so the main_server will remain the
7126N/A connection vhost. Then scans will cover all vhosts in the vhost list.
7126N/A If you do have a <
SAMP>_default_</
SAMP> vhost, then you cannot place
7126N/A named-based vhosts after it in the config. This is because on any
7126N/A connection to the main server IPs the connection vhost will always be
7126N/A the <
SAMP>_default_</
SAMP> vhost since none of the name-based are
7126N/A considered during <
CODE>find_virtual_server</
CODE>.
7126N/A<
LI>You should never specify DNS names in <
CODE>VirtualHost</
CODE>
7126N/A directives because it will force your server to rely on DNS to boot.
7126N/A Furthermore it poses a security threat if you do not control the
7126N/A DNS for all the domains listed.
7126N/A available on this and the next two topics</
A>.
7126N/A<
LI><
CODE>ServerName</
CODE> should always be set for each vhost. Otherwise
7126N/A A DNS lookup is required for each vhost.
7126N/A<
LI>A DNS lookup is always required for the main_server's
7126N/A <
CODE>ServerName</
CODE> (or to generate that if it isn't specified
7141N/A<
LI>If a <
CODE>ServerPath</
CODE> directive exists which is a prefix of
7126N/A another <
CODE>ServerPath</
CODE> directive that appears later in
7141N/A the configuration file, then the former will always be matched
7126N/A and the latter will never be matched. (That is assuming that no
7141N/A Host header was available to disambiguate the two.)
7141N/A<
LI>If a vhost that would otherwise be a name-vhost includes a
7126N/A <
CODE>Port</
CODE> statement that doesn't match the main_server
7126N/A <
CODE>Port</
CODE> then it will be considered an IP-based vhost.
7126N/A Then <
CODE>find_virtual_server</
CODE> will match it (because
7126N/A the ports associated with each address in the address set default
7126N/A to the port of the main_server) as the connection vhost. Then
7126N/A <
CODE>check_hostalias</
CODE> will refuse to check any other name-based
7126N/A vhost because of the port mismatch. The result is that the vhost
7126N/A will steal all hits going to the main_server address.
7126N/A<
LI>If two IP-based vhosts have an address in common, the vhost appearing
7167N/A later in the file is always matched. Such a thing might happen
7126N/A inadvertently. If the config has name-based vhosts and for some reason
7263N/A the main_server <
CODE>ServerName</
CODE> resolves to the wrong address
7126N/A then all the name-based vhosts will be parsed as ip-based vhosts.
7126N/A Then the last of them will steal all the hits.
7126N/A<
LI>The last name-based vhost in the config is always matched for any hit
7126N/A which doesn't match one of the other name-based vhosts.
7126N/A<
h3><
A name="whatworks">What Works</
A></
h3>
7126N/AIssues</
A> page, here are some further tips:
7126N/A<
LI>Place all main_server definitions before any VirtualHost definitions.
7141N/A(This is to aid the readability of the configuration -- the post-config
7141N/Amerging process makes it non-obvious that definitions mixed in around
7141N/Avirtualhosts might affect all virtualhosts.)
7141N/A<
LI>Arrange your VirtualHosts such
7141N/Athat all name-based virtual hosts come first, followed by IP-based
7141N/Avirtual hosts, followed by any <
SAMP>_default_</
SAMP> virtual host
7141N/A<
LI>Avoid <
CODE>ServerPaths</
CODE> which are prefixes of other
7141N/A<
CODE>ServerPaths</
CODE>. If you cannot avoid this then you have to
7141N/Aensure that the longer (more specific) prefix vhost appears earlier in
7141N/Athe configuration file than the shorter (less specific) prefix
7141N/A(<
EM>
i.e.</
EM>, "ServerPath /abc" should appear after
7141N/A"ServerPath /abcdef").
7141N/A<
LI>Do not use <
EM>port-based</
EM> vhosts in the same server as
7141N/Aname-based vhosts. A loose definition for port-based is a vhost which
7141N/Ais determined by the port on the server (<
EM>
i.e.</
EM>, one server with
7141N/Aports 8000, 8080, and 80 - all of which have different configurations).