details_1_2.html revision f9b3be308809978f797e0c57b296147532a4313c
7126N/A<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
7126N/A<HTML><HEAD>
7126N/A<TITLE>An In-Depth Discussion of VirtualHost Matching</TITLE>
7126N/A</HEAD>
7126N/A
7126N/A<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
7126N/A<BODY
7126N/A BGCOLOR="#FFFFFF"
7126N/A TEXT="#000000"
7126N/A LINK="#0000FF"
7126N/A VLINK="#000080"
7126N/A ALINK="#FF0000"
7126N/A>
7126N/A<!--#include virtual="header.html" -->
7126N/A<h1 ALIGN="CENTER">An In-Depth Discussion of VirtualHost Matching</H1>
7126N/A
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
7126N/A<P>If you just want to &quot;make it work&quot; without understanding
7126N/Ahow, there's a <A HREF="#whatworks">What Works</A> section at the bottom.
7126N/A
7126N/A<h3>Config File Parsing</h3>
7126N/A
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<A
7141N/A HREF="mod/core.html#virtualhost"
7126N/A><SAMP>VirtualHost</SAMP></A>
7126N/Asections.
7126N/A
7126N/A<P>The directives
7126N/A<A
7126N/A HREF="mod/core.html#port"
7126N/A><SAMP>Port</SAMP></A>,
7126N/A<A
7126N/A HREF="mod/core.html#servername"
7141N/A><SAMP>ServerName</SAMP></A>,
7126N/A<A
7126N/A HREF="mod/core.html#serverpath"
7126N/A><SAMP>ServerPath</SAMP></A>,
7141N/Aand
7126N/A<A
7126N/A HREF="mod/core.html#serveralias"
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(within that server).
7126N/A
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>.
7126N/A
7126N/A<P>In the absence of any
7126N/A<A
7126N/A HREF="mod/core.html#listen"
7126N/A><SAMP>Listen</SAMP></A>
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
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/Aredirects.
7126N/A
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/A<SAMP>A</SAMP> record
7126N/Aresults from DNS lookups) are called the vhost's <EM>address set</EM>.
7126N/A
7126N/A<P> The magic <CODE>_default_</CODE> address has significance during
7126N/Athe matching algorithm. It essentially matches any unspecified address.
7126N/A
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/Aaddress set.
7126N/A
7126N/A<P>
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/A
7126N/A<BLOCKQUOTE><PRE>
7126N/A &lt;VirtualHost A&gt;
7126N/A ...
7141N/A &lt;/VirtualHost&gt;
7126N/A
7126N/A &lt;VirtualHost B&gt;
7126N/A ...
7126N/A &lt;/VirtualHost&gt;
7126N/A
7126N/A &lt;VirtualHost C&gt;
7126N/A ...
7126N/A &lt;/VirtualHost&gt;
7126N/A</PRE></BLOCKQUOTE>
7126N/A
7126N/AThen the list will be ordered: main_server, C, B, A. Keep this in mind.
7126N/A
7126N/A<P>
7141N/AAfter parsing has completed, the list of servers is scanned, and various
7126N/Amerges and default values are set. In particular:
7126N/A
7126N/A<OL>
7126N/A<LI>If a vhost has no
7126N/A <A
7141N/A HREF="mod/core.html#serveradmin"
7126N/A ><CODE>ServerAdmin</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#resourceconfig"
7126N/A ><CODE>ResourceConfig</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#accessconfig"
7126N/A ><CODE>AccessConfig</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#timeout"
7126N/A ><CODE>Timeout</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#keepalivetimeout"
7126N/A ><CODE>KeepAliveTimeout</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#keepalive"
7126N/A ><CODE>KeepAlive</CODE></A>,
7126N/A <A
7126N/A HREF="mod/core.html#maxkeepaliverequests"
7263N/A ><CODE>MaxKeepAliveRequests</CODE></A>,
7141N/A or
7126N/A <A
7126N/A HREF="mod/core.html#sendbuffersize"
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
7126N/A<LI>The &quot;lookup defaults&quot; that define the default directory
7126N/A permissions
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
7126N/A<LI>The per-server configs for each module from the main_server are
7126N/A merged into the vhost server.
7126N/A</OL>
7126N/A
7126N/AEssentially, the main_server is treated as &quot;defaults&quot; or a
7126N/A&quot;base&quot; on
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
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/Athe main_server.
7126N/A
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/Avhost.
7126N/A
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/Astatement.
7126N/A
7126N/A<P>
7126N/A
7126N/A<h3>Vhost Matching</h3>
7126N/A
7126N/A
7126N/A<P><STRONG>Apache 1.3 differs from what is documented
7126N/Ahere, and documentation still has to be written.</STRONG>
7126N/A
7126N/A<P>
7126N/AThe server determines which vhost to use for a request as follows:
7126N/A
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).
7126N/A
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
7126N/A<P> In any event, if nothing above has matched, then the main_server is
7126N/Amatched.
7126N/A
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/Asession -- that is, over all requests in a KeepAlive/persistent session.
7126N/A
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/Athe request.
7126N/A
7126N/A<P> <CODE>check_fulluri</CODE>: If the requestURI is an absoluteURI, that
7126N/Ais it includes <CODE>http://hostname/</CODE>, then an attempt is made to
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/Acomparison,
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
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/Aan <CODE>http://hostname/</CODE> in the previous step, this could still
7141N/Abe a proxy request.
7141N/A
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
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/A
7126N/A<P>
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/Aare as follows:
7126N/A
7126N/A<UL>
7126N/A<LI>Compare the request hostname:port with the vhost
7126N/A <CODE>ServerName</CODE> and <CODE>Port</CODE>.
7126N/A
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
7126N/A<LI>Compare the request hostname against the <CODE>ServerAlias</CODE>
7126N/A given for the vhost.
7126N/A</UL>
7126N/A
7126N/A<P>
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
7126N/Athe virtual hosts).
7126N/A
7146N/A<h3>Observations</h3>
7126N/A
7126N/A<UL>
7126N/A
7146N/A<LI>It is difficult to define an IP-based vhost for the machine's
7126N/A &quot;main IP address&quot;. You essentially have to create a bogus
7126N/A <CODE>ServerName</CODE> for the main_server that does not match the
7126N/A machine's IPs.
7126N/A <P>
7126N/A
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 can be matched.
7126N/A <P>
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 &quot;<SAMP>Host: A</SAMP>&quot; 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 any Host: header.
7126N/A </P>
7126N/A
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 <P>
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 </P>
7126N/A
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 <A HREF="dns-caveats.html">There's more information
7126N/A available on this and the next two topics</A>.
7126N/A <P>
7141N/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 <P>
7126N/A
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
7126N/A in the config).
7126N/A <P>
7126N/A
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 <P>
7126N/A
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.
7167N/A <P>
7263N/A
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 <P>
7126N/A
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
7126N/A</UL>
7126N/A
7126N/A<h3><A name="whatworks">What Works</A></h3>
7126N/A
7126N/A<P>In addition to the tips on the <A HREF="dns-caveats.html#tips">DNS
7126N/AIssues</A> page, here are some further tips:
7126N/A
7126N/A<UL>
7126N/A
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<P>
7141N/A
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<P>
7141N/A
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>, &quot;ServerPath /abc&quot; should appear after
7141N/A&quot;ServerPath /abcdef&quot;).
7141N/A<P>
7141N/A
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).
7141N/A<P>
7141N/A
7141N/A</UL>
7141N/A
7141N/A<!--#include virtual="footer.html" -->
7141N/A</BODY>
7141N/A</HTML>
7126N/A