You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dean Gaudet <dg...@arctic.org> on 1997/03/16 03:48:12 UTC
[PATCH] continue after DNS errors, and document vhosts better
This patch is large because of the two new documentation files it
includes. One of them is an update to the link I posted a week or so ago.
The other describes the reliability and security issues regarding DNS
in the configuration process (and warning warning! it includes some of
*my opinion* which is one of those things that I'm not supposed to just
commit willy-nilly into the doc tree). These docs are included with the
code because they assume that the code portion of the patch is accepted.
The code portion of this patch attempts to deal gracefully with DNS errors
during configuration. It attempts to disable the offending virtual hosts.
It is hoped that people will just read the above docs, but this at least
will prevent them from getting rudely burned when an error happens.
I seriously hope that this will iron out most of the common configuration
problems people have. The documentation gives suggestions as to how to
structure the configuration files, and how to avoid the various known
problems. It would be nice if someone could take these basic docs and
use them to update other sections of our documentation -- in particular we
have misleading examples of how to configure virtual hosts (which are good
for pedagogical purposes, but fail in real use because of DNS problems).
Dean
P.S. Is there some stupid CVS incantation to produce a recursive diff
properly? I get diffs that don't include the path names on the files,
making it quite useless.
diff --new-file -c3 -r -x CVS apache3/htdocs/manual/bind.html apache-vhost-cleanup/htdocs/manual/bind.html
*** apache3/htdocs/manual/bind.html Sat Mar 15 18:29:07 1997
--- apache-vhost-cleanup/htdocs/manual/bind.html Sat Mar 15 18:33:13 1997
***************
*** 89,95 ****
<a href="virtual-host.html">Virtual Hosts</a>,
<a href="host.html">Non-IP virtual hosts</a>,
<a href="mod/core.html#bindaddress">BindAddress directive</a>,
! <a href="mod/core.html#port">Port directive</a>
and
<a href="mod/core.html#virtualhost"><VirtualHost> section</a>.
</ul>
--- 89,96 ----
<a href="virtual-host.html">Virtual Hosts</a>,
<a href="host.html">Non-IP virtual hosts</a>,
<a href="mod/core.html#bindaddress">BindAddress directive</a>,
! <a href="mod/core.html#port">Port directive</a>,
! <a href="dns-caveats.html">DNS Issues</a>
and
<a href="mod/core.html#virtualhost"><VirtualHost> section</a>.
</ul>
diff --new-file -c3 -r -x CVS apache3/htdocs/manual/dns-caveats.html apache-vhost-cleanup/htdocs/manual/dns-caveats.html
*** apache3/htdocs/manual/dns-caveats.html Wed Dec 31 16:00:00 1969
--- apache-vhost-cleanup/htdocs/manual/dns-caveats.html Sat Mar 15 18:33:13 1997
***************
*** 0 ****
--- 1,190 ----
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+ <html><head>
+ <title>Issues Regarding DNS and Apache</title>
+ </head><body>
+
+ <!--#include virtual="header.html" -->
+ <h1>Issues Regarding DNS and Apache</h1>
+
+ <p>This page could be summarized with the statement: <i>don't require
+ Apache to use DNS for any parsing of the configuration files</i>.
+ If Apache has to use DNS to parse the configuration files then your
+ server may be subject to reliability problems (it might not boot), or
+ denial and theft of service attacks (including users able to steal hits
+ from other users).
+
+ <h3>A Simple Example</h3>
+
+ Consider this configuration snippet:
+
+ <blockquote><pre>
+ <VirtualHost www.abc.dom>
+ ServerAdmin webgirl@abc.dom
+ DocumentRoot /www/abc
+ </VirtualHost>
+ </pre></blockquote>
+
+ <p>In order for Apache to function properly it absolutely needs
+ to have two pieces of information about each virtual host: the
+ <a href="mod/core.html#servername"><code>ServerName</code></a>
+ and at least one ip address that the server
+ responds to. This example does not include the ip address, so Apache
+ must use DNS to find the address of <code>www.abc.dom</code>. If for
+ some reason DNS is not available at the time your server is parsing its
+ config file, then this virtual host <b>will not be configured</b>. It
+ won't be able to respond to any hits to this virtual host (prior to
+ Apache version 1.2 the server would not even boot).
+
+ <p>Suppose that <code>www.abc.dom</code> has address 10.0.0.1. Then
+ consider this configuration snippet:
+
+ <blockquote><pre>
+ <VirtualHost 10.0.0.1>
+ ServerAdmin webgirl@abc.dom
+ DocumentRoot /www/abc
+ </VirtualHost>
+ </pre></blockquote>
+
+ <p>Now Apache needs to use reverse DNS to find the <code>ServerName</code>
+ for this virtualhost. If that reverse lookup fails then it will partially
+ disable the virtualhost (prior to Apache version 1.2 the server would not
+ even boot). If the virtual host is name-based then it will effectively
+ be totally disabled, but if it is ip-based then it will mostly work.
+ However if Apache should ever have to generate a full URL for the server
+ which includes the server name then it will fail to generate a valid URL.
+
+ <p>Here is a snippet that avoids both of these problems.
+
+ <blockquote><pre>
+ <VirtualHost 10.0.0.1>
+ ServerName www.abc.dom
+ ServerAdmin webgirl@abc.dom
+ DocumentRoot /www/abc
+ </VirtualHost>
+ </pre></blockquote>
+
+ <h3>Denial of Service</h3>
+
+ <p>There are (at least) two forms that denial of service can come in.
+ If you are running a version of Apache prior to version 1.2 then your
+ server will not even boot if one of the two DNS lookups mentioned above
+ fails for any of your virtual hosts. In some cases this DNS lookup may
+ not even be under your control. For example, if <code>abc.dom</code>
+ is one of your customers and they control their own DNS then they
+ can force your (pre-1.2) server to fail while booting simply by deleting the
+ <code>www.abc.dom</code> record.
+
+ <p>Another form is far more insidious. Consider this configuration
+ snippet:
+
+ <blockquote><pre>
+ <VirtualHost www.abc.dom>
+ ServerAdmin webgirl@abc.dom
+ DocumentRoot /www/abc
+ </VirtualHost>
+ </pre></blockquote>
+
+ <blockquote><pre>
+ <VirtualHost www.def.dom>
+ ServerAdmin webguy@def.dom
+ DocumentRoot /www/def
+ </VirtualHost>
+ </pre></blockquote>
+
+ <p>Suppose that you've assigned 10.0.0.1 to <code>www.abc.dom</code> and
+ 10.0.0.2 to <code>www.def.dom</code>. Furthermore, suppose that
+ <code>def.com</code> has control of their own DNS. With this config
+ you have put <code>def.com</code> into a position where they can steal
+ all traffic destined to <code>abc.com</code>. To do so, all they have to
+ do is set <code>www.def.dom</code> to 10.0.0.1.
+ Since they control their own DNS you can't stop them from pointing the
+ <code>www.def.com</code> record wherever they wish.
+
+ <p>Requests coming in to 10.0.0.1 (including all those where users typed
+ in URLs of the form <code>http://www.abc.dom/whatever</code>) will all be
+ served by the <code>def.com</code> virtual host. To better understand why
+ this happens requires a more in-depth discussion of how Apache matches
+ up incoming requests with the virtual host that will serve it. A rough
+ document describing this <a href="vhosts-in-depth.html"> is available</a>.
+
+ <h3>The "main server" Address</h3>
+
+ <p>The addition of <a href="host.html">non-IP-based virtual host
+ support</a> in Apache 1.1 requires Apache to know the IP address(es) of
+ the host that httpd is running on. To get this address it uses either
+ the global <code>ServerName</code> (if present) or calls the C function
+ <code>gethostname</code> (which should return the same as typing
+ "hostname" at the command prompt). Then it performs a DNS lookup on
+ this address. At present there is no way to avoid this lookup.
+
+ <p>If you fear that this lookup might fail because your DNS server is down
+ then you can insert the hostname in <code>/etc/hosts</code> (where you
+ probably already have it so that the machine can boot properly). Then
+ ensure that your machine is configured to use <code>/etc/hosts</code>
+ in the event that DNS fails. Depending on what OS you are using this
+ might be accomplished by editing <code>/etc/resolv.conf</code>, or maybe
+ <code>/etc/nsswitch.conf</code>.
+
+ <p>If your server doesn't have to perform DNS for any other reason
+ then you might be able to get away with running Apache with the
+ <code>HOSTRESORDER</code> environment variable set to "local". This all
+ depends on what OS and resolver libraries you are using. It also affects
+ CGIs unless you use <a href="mod/mod_env.html"><code>mod_env</code></a>
+ to control the environment. It's best to consult the man pages or FAQs
+ for your OS.
+
+ <h3>The _default_ Address</h3>
+
+ <p>Any address that happens to go to your webserver which doesn't match
+ the ip address of any of the webservers will be served from the "main" or
+ "default" server configurations. The "main" server configuration consists
+ of all those definitions appearing outside of any VirtualHost section.
+ You may want instead to define a <code><VirtualHost _default></code>
+ which returns 403 or 404 for all hits.
+
+ <a name="tips"><h3>Tips to Avoid these problems</h3></a>
+
+ <ul>
+ <li> use ip addresses in <code><VirtualHost></code>
+ <li> use ip addresses in <code>Listen</code>
+ <li> use ip addresses in <code>BindAddress</code>
+ <li> ensure all virtual hosts have an explicit <code>ServerName</code>
+ <li> create a <code><VirtualHost _default_></code> server that
+ has no pages to serve
+ </ul>
+
+ <h3>Appendix: Future Directions</h3>
+
+ <p>The situation regarding DNS is highly undesirable. For Apache
+ 1.2 we've attempted to make the server at least continue booting
+ in the event of failed DNS, but it might not be the best we
+ can do. In any event requiring the use of explicit ip addresses in
+ configuration files is highly undesirable in today's Internet where <a
+ href="http://www.ietf.org/html.charters/pier-charter.html">renumbering
+ </a> is a necessity.
+
+ <p>A possible work around to the theft of service attack described above
+ would be to perform a reverse DNS lookup on the ip address returned by
+ the forward lookup and compare the two names. In the event of a mismatch
+ the virtualhost would be disabled. This would require reverse DNS to be
+ configured properly (which is something that most admins are familiar with
+ because of the common use of "double-reverse" DNS lookups by FTP servers
+ and TCP wrappers).
+
+ <p>In any event it doesn't seem possible to reliably boot a virtual-hosted
+ web server when DNS has failed unless IP addresses are used. Partial
+ solutions such as disabling portions of the configuration might be worse
+ than not booting at all depending on what the webserver is supposed
+ to accomplish.
+
+ <p>As HTTP/1.1 is deployed and browsers and proxies start issuing the
+ <code>Host</code> header it will become possible to avoid the use of
+ ip-based virtual hosts entirely. In this event a webserver has no requirement
+ to do DNS lookups during configuration. But as of March 1997 these
+ features have not been deployed widely enough to be put into use on
+ critical webservers.
+
+ <!--#include virtual="footer.html" -->
+ </BODY>
+ </HTML>
+
diff --new-file -c3 -r -x CVS apache3/htdocs/manual/mod/core.html apache-vhost-cleanup/htdocs/manual/mod/core.html
*** apache3/htdocs/manual/mod/core.html Sat Mar 15 18:29:10 1997
--- apache-vhost-cleanup/htdocs/manual/mod/core.html Sat Mar 15 18:33:19 1997
***************
*** 244,249 ****
--- 244,251 ----
<A HREF="#virtualhost"><VirtualHost></A> sections.
<p><strong>See Also:</strong>
+ <a href="../dns-caveats.html">DNS Issues</a><br>
+ <strong>See Also:</strong>
<a href="../bind.html">Setting which addresses and ports Apache uses</a></p>
<hr>
***************
*** 595,601 ****
interfaces, but only on the port given by the <a href="#port">Port</a>
directive.</p>
! <p><strong>See Also</strong>:
<a href="../bind.html">Setting which addresses and ports Apache uses</a></p>
<hr>
--- 597,605 ----
interfaces, but only on the port given by the <a href="#port">Port</a>
directive.</p>
! <p><strong>See Also:</strong>
! <a href="../dns-caveats.html">DNS Issues</a><br>
! <strong>See Also:</strong>
<a href="../bind.html">Setting which addresses and ports Apache uses</a></p>
<hr>
***************
*** 1053,1060 ****
The ServerAlias directive sets the alternate names for a host, for use
with
<a href="../host.html">Host-header based virtual hosts</a>.
! <p><hr>
<A name="servername"><h2>ServerName directive</h2></A>
<!--%plaintext <?INDEX {\tt ServerName} directive> -->
--- 1057,1066 ----
The ServerAlias directive sets the alternate names for a host, for use
with
<a href="../host.html">Host-header based virtual hosts</a>.
+ <p><strong>See Also</strong>:
+ <a href="../vhosts-in-depth.html">In-depth description of Virtual Host matching</a></p>
! <hr>
<A name="servername"><h2>ServerName directive</h2></A>
<!--%plaintext <?INDEX {\tt ServerName} directive> -->
***************
*** 1068,1074 ****
not work reliably, or may not return the preferred hostname. For example:
<blockquote><code>ServerName www.wibble.com</code></blockquote>
would be used if the canonical (main) name of the actual machine
! were <code>monster.wibble.com</code>.<p><hr>
<A name="serverpath"><h2>ServerPath directive</h2></A>
--- 1074,1083 ----
not work reliably, or may not return the preferred hostname. For example:
<blockquote><code>ServerName www.wibble.com</code></blockquote>
would be used if the canonical (main) name of the actual machine
! were <code>monster.wibble.com</code>.<p>
! <p><strong>See Also</strong>:
! <a href="../dns-caveats.html">DNS Issues</a></p>
! <hr>
<A name="serverpath"><h2>ServerPath directive</h2></A>
***************
*** 1080,1085 ****
--- 1089,1096 ----
The ServerPath directive sets the legacy URL pathname for a host, for
use with <a href="../host.html">Host-header based virtual hosts</a>.
+ <p><strong>See Also</strong>:
+ <a href="../vhosts-in-depth.html">In-depth description of Virtual Host matching</a></p>
<hr>
<A name="serverroot"><h2>ServerRoot directive</h2></A>
***************
*** 1208,1219 ****
<A name="virtualhost"><h2><VirtualHost> directive</h2></A>
<!--%plaintext <?INDEX {\tt VirtualHost} section directive> -->
! <strong>Syntax:</strong> <VirtualHost <em>addr</em>[:<em>port</em>]> ...
</VirtualHost> <br>
<strong>Context:</strong> server config<br>
<strong>Status:</strong> Core.<br>
! <strong>Compatibility:</strong> Non-IP address-based Virtual Hosting is
! only available in Apache 1.2 and later.<p>
<VirtualHost> and </VirtualHost> are used to enclose a group of
directives which will apply only to a particular virtual host.
--- 1219,1232 ----
<A name="virtualhost"><h2><VirtualHost> directive</h2></A>
<!--%plaintext <?INDEX {\tt VirtualHost} section directive> -->
! <strong>Syntax:</strong> <VirtualHost <em>addr</em>[:<em>port</em>] ...> ...
</VirtualHost> <br>
<strong>Context:</strong> server config<br>
<strong>Status:</strong> Core.<br>
! <strong>Compatibility:</strong> Non-IP address-based Virtual Hosting only
! available in Apache 1.1 and later.<br>
! <strong>Compatibility:</strong> Multiple address support only available in
! Apache 1.2 and later.<p>
<VirtualHost> and </VirtualHost> are used to enclose a group of
directives which will apply only to a particular virtual host.
***************
*** 1244,1259 ****
command (if your OS supports it), or with kernel patches like <A
HREF="../misc/vif-info.html">VIF</A> (for SunOS(TM) 4.1.x)).<p>
! SECURITY: See the <A HREF="../misc/security_tips.html">security tips</A>
document for details on why your security could be compromised if
the directory where logfiles are stored is writable by anyone other
than the user that starts the server.
<p><strong>See also:</strong>
<A HREF="../virtual-host.html">Information on Virtual Hosts.
(multihome)</A><br>
<strong>See also:</strong>
! <a href="../host.html">Non-IP address-based Virtual Hosts</a>
</p>
<!--#include virtual="footer.html" -->
--- 1257,1283 ----
command (if your OS supports it), or with kernel patches like <A
HREF="../misc/vif-info.html">VIF</A> (for SunOS(TM) 4.1.x)).<p>
! The special name <code>_default_</code> can be specified in which case
! this virtual host will match any ip address that is not explicitly listed
! in another virtual host. In the absence of any _default_ virtual host
! the "main" server config, consisting of all those definitions outside
! any VirtualHost section, is used when no match occurs.<p>
!
! <strong>SECURITY</strong>: See the
! <A HREF="../misc/security_tips.html">security tips</A>
document for details on why your security could be compromised if
the directory where logfiles are stored is writable by anyone other
than the user that starts the server.
<p><strong>See also:</strong>
+ <A HREF="../dns-caveats.html">Warnings about DNS and Apache</a><br>
+ <strong>See also:</strong>
<A HREF="../virtual-host.html">Information on Virtual Hosts.
(multihome)</A><br>
<strong>See also:</strong>
! <a href="../host.html">Non-IP address-based Virtual Hosts</a><br>
! <strong>See also:</strong>
! <a href="../vhosts-in-depth.html">In-depth description of Virtual Host matching</a>
</p>
<!--#include virtual="footer.html" -->
diff --new-file -c3 -r -x CVS apache3/htdocs/manual/vhosts-in-depth.html apache-vhost-cleanup/htdocs/manual/vhosts-in-depth.html
*** apache3/htdocs/manual/vhosts-in-depth.html Wed Dec 31 16:00:00 1969
--- apache-vhost-cleanup/htdocs/manual/vhosts-in-depth.html Sat Mar 15 18:33:13 1997
***************
*** 0 ****
--- 1,309 ----
+ <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
+ <html><head>
+ <title>An In-Depth Discussion of VirtualHost Matching</title>
+ </head><body>
+
+ <!--#include virtual="header.html" -->
+ <h1>An In-Depth Discussion of VirtualHost Matching</h1>
+
+ <p>This is a very rough document that was probably out of date the moment
+ it was written. It attempts to explain exactly what the code does when
+ deciding what virtual host to serve a hit from. It's provided on the
+ assumption that something is better than nothing. The server version
+ under discussion is Apache 1.2.
+
+ <p>If you just want to "make it work" without understanding how, there's
+ a <a href="#whatworks">What Works</a> section at the bottom.
+
+ <h3>Config File Parsing</h3>
+
+ <p>There is a main_server which consists of all the definitions appearing
+ outside of <code>VirtualHost</code> sections. There are virtual servers,
+ called <i>vhosts</i>, which are defined by <code>VirtualHost</code> sections.
+
+ <p>The directives
+ <code>Port</code>,
+ <code>ServerName</code>,
+ <code>ServerPath</code>, and
+ <code>ServerAlias</code> can appear anywhere within the definition of
+ a server. However each appearance overrides the previous appearance
+ (within that server).
+
+ <p>The default value of the <code>Port</code> field for main_server
+ is 80. The main_server has no default <code>ServerName</code>,
+ <code>ServerPath</code>, or ServerAlias</code>.
+
+ <p>In the absence of any <code>Listen</code> directives, the (final if there
+ are multiple) <code>Port</code> directive in the main_server indicates
+ which port httpd will listen on.
+
+ <p> The <code>Port</code> and <code>ServerName</code> directives for
+ any server main or virtual are used when generating URLs such as during
+ redirects.
+
+ <p> Each address appearing in the <code>VirtualHost</code> directive
+ can have an optional port. If the port is unspecified it defaults to
+ the value of the main_server's most recent <code>Port</code> statement.
+ The special port * indicates a wildcard that matches any port.
+ Collectively the entire set of addresses (including multiple A record
+ results from DNS lookups) are called the vhost's <i>address set</i>.
+
+ <p> The magic <code>_default_</code> address has significance during
+ the matching algorithm. It essentially matches any unspecified address.
+
+ <p> After parsing the <code>VirtualHost</code> directive, the vhost server
+ is given a default <code>Port</code> equal to the port assigned to the
+ first name in its <code>VirtualHost</code> directive. The complete
+ list of names in the <code>VirtualHost</code> directive are treated
+ just like a <code>ServerAlias</code> (but are not overridden by any
+ <code>ServerAlias</code> statement).
+
+ <p>
+ All vhosts are stored in a list which is in the reverse order that
+ they appeared in the config file. For example, if the config file is:
+
+ <blockquote><pre>
+ <VirtualHost A>
+ ...
+ </VirtualHost>
+
+ <VirtualHost B>
+ ...
+ </VirtualHost>
+
+ <VirtualHost C>
+ ...
+ </VirtualHost>
+ </pre></blockquote>
+
+ Then the list will be ordered: main_server, C, B, A. Keep this in mind.
+
+ <p>
+ After parsing has completed, the list of servers is scanned, and various
+ merges and default values are set. In particular:
+
+ <ul>
+ <li>If a vhost has no
+ <code>ServerAdmin</code>,
+ <code>ResourceConf</code>,
+ <code>AccessConf</code>,
+ <code>Timeout</code>,
+ <code>KeepAliveTimeout</code>,
+ <code>KeepAlive</code>,
+ <code>KeepAliveMax</code>, or
+ <code>SendBufferSize</code> directive then the respective value is
+ inherited from the main_server. (That is, inherited from whatever
+ the final setting of that value is in the main_server.)
+
+ <li>The "lookup defaults" that define the default directory permissions
+ for a vhost are merged with those of the main server. This includes
+ any per-directory configuration information for any module.
+
+ <li>The per-server configs for each module from the main_server are
+ merged into the vhost server.
+ </ul>
+
+ Essentially, the main_server is treated as "defaults" or a "base" on
+ which to build each vhost. But the positioning of these main_server
+ definitions in the config file is largely irrellevent -- the entire
+ config of the main_server has been parsed when this final merging occurs.
+ So even if a main_server definition appears after a vhost definition
+ it might affect the vhost definition.
+
+ <p> If the main_server has no <code>ServerName</code> at this point,
+ then the hostname of the machine that httpd is running on is used
+ instead. We will call the <i>main_server address set</i> those ip
+ addresses returned by a DNS lookup on the <code>ServerName</code> of
+ the main_server.
+
+ <p> Now a pass is made through the vhosts to fill in any missing
+ <code>ServerName</code> fields and to classify the vhost as either
+ an <i>ip-based</i> vhost or a <i>name-based</i> vhost. A vhost is an
+ ip-based vhost if none of the vhosts address set overlaps the main_server
+ address set. Otherwise it is considered a name-based vhost.
+
+ <p> For any undefined <code>ServerName</code> fields, a name-based vhost
+ defaults to the address given first in the <code>VirtualHost</code>
+ statement defining the vhost. Any vhost that includes the magic
+ _default_ wildcard is given the same <code>ServerName</code> as
+ the main_server. Otherwise the vhost (which is necessarily an ip-based
+ vhost) is given a <code>ServerName</code> based on the result of a reverse
+ DNS lookup on the first address given in the <code>VirtualHost</code>
+ statement.
+
+ <p>
+
+ <h3>Vhost Matching</h3>
+
+ <p>
+ The process by which vhost a request is for is as follows:
+
+ <p> <code>find_virtual_server</code>: When the connection is first made
+ by the client, the local ip address (the ip address to which the client
+ connected) is looked up in the server list. A vhost is matched if it
+ is an ip-based vhost, and the ip address matches and the port matches
+ (taking into account wildcards).
+
+ <p> If no vhosts are matched then the last occurance, if it appears,
+ of a _default_ address (which if you recall the ordering of the
+ server list mentioned above means that this would be the first occurance
+ of _default_ in the config file) is matched.
+
+ <p> In any event, if nothing above has matched, then the main_server is
+ matched.
+
+ <p> The vhost resulting from the above search is stored with data
+ about the connection. We'll call this the <i>connection vhost</i>.
+ The connection vhost is constant over all requests in a particular TCP/IP
+ session -- that is, over all requests in a KeepAlive/persistent session.
+
+ <p> For each request made on the connection the following sequence of
+ events further determines the actual vhost that will be used to serve
+ the request.
+
+ <p> <code>check_fulluri</code>: If the requestURI is an absoluteURI, that
+ is it includes <code>http://hostname/</code>, then an attempt is made to
+ determine if the hostname's address (and optional port) match that of
+ the connection vhost. If it does then the hostname portion of the uri
+ is saved as the <i>request_hostname</i>. If it does not match, then the
+ uri remains untouched. <b>Note</b>: to achieve this address comparison,
+ the hostname supplied goes through a DNS lookup unless it matches the
+ <code>ServerName</code> or the local ip address of the client's socket.
+
+ <p> <code>parse_uri</code>: If the uri begins with a protocol
+ (i.e. <code>http:</code>, <code>ftp:</code>) then the request is
+ considered a proxy request. Note that even though we may have stripped
+ an <code>http://hostname/</code> in the previous step, this could still
+ be a proxy request.
+
+ <p> <code>read_request</code>: If the request does not have a hostname
+ from the earlier step, then any <code>Host:</code> header sent by the
+ client is used as the request hostname.
+
+ <p> <code>check_hostalias</code>: If the request now has a hostname,
+ then an attempt is made to match for this hostname. The first step
+ of this match is to compare any port, if one was given in the request,
+ against the <code>Port</code> field of the connection vhost. If there's
+ a mismatch then the vhost used for the request is the connection vhost.
+ (This is probably a bug.)
+
+ <p>
+ If the port matches, then httpd scans the list of vhosts starting with
+ the next server <b>after</b> the connection vhost. This scan does not
+ stop if there are any matches, it goes through all possible vhosts,
+ and in the end uses the last match it found. The comparisons performed
+ are as follows:
+
+ <ul>
+ <li> Compare the request hostname:port with the vhost
+ <code>ServerName</code> and <code>Port</code>.
+
+ <li> Compare the request hostname against any and all addresses given in
+ the <code>VirtualHost</code> directive for this vhost. <i>(n.b. this
+ assumes Dean's "VirtualHost confusion" patch is accepted.)</i>
+
+ <li> Compare the request hostname against the <code>ServerAlias</code>
+ given for the vhost.
+ </ul>
+
+ <p>
+ <code>check_serverpath</code>: If the request has no hostname
+ (back up a few paragraphs) then a scan similar to the one
+ in <code>check_hostalias</code> is performed to match any
+ <code>ServerPath</code> directives given in the vhosts. Note that the
+ <b>last match</b> is used regardless (again consider the ordering of
+ the virtual hosts).
+
+ <h3>Observations</h3>
+
+ <ul>
+
+ <li> It is difficult to define an ip-based vhost for the machine's
+ "main ip address". You essentially have to create a bogus
+ <code>ServerName</code> for the main_server that does not match the
+ machine's ips.
+ </p>
+
+ <li> During the scans in both <code>check_hostalias</code> and
+ <code>check_serverpath</code> no check is made that the vhost being
+ scanned is actually a name-based vhost. This means, for example, that
+ it's possible to match an ip-based vhost through another address. But
+ because the scan starts in the vhost list at the first vhost that
+ matched the local ip address of the connection, not all ip-based vhosts
+ can be matched.
+
+ <p>Consider the config file above with three vhosts A, B, C. Suppose
+ that B is a named-based vhost, and A and C are ip-based vhosts. If
+ a request comes in on B or C's address containing a header "Host: A" then
+ it will be served from A's config. If a request comes in on A's
+ address then it will always be served from A's config regardless of
+ any Host: header.
+ </p>
+
+ <li> Unless you have a _default_ vhost,
+ it doesn't matter if you mix name-based vhosts in amongst ip-based
+ vhosts. During the <code>find_virtual_server</code> phase above no
+ named-based vhost will be matched, so the main_server will remain the
+ connection vhost. Then scans will cover all vhosts in the vhost list.
+
+ <p>If you do have a _default_ vhost, then you cannot place
+ named-based vhosts after it in the config. This is because on any
+ connection to the main server ips the connection vhost will always be
+ the _default_ vhost since none of the name-based are considered
+ during <code>find_virtual_server</code>.
+ </p>
+
+ <li> You should never specify DNS names in <code>VirtualHost</code>
+ directives because it will force your server to rely on DNS to boot.
+ Furthermore it poses a security threat if you do not control the
+ DNS for all the domains listed.
+ <a href="dns-caveats.html">
+ There's more information
+ available on this and the next two topics</a>.
+ </p>
+
+ <li> <code>ServerName</code> should always be set for each vhost. Otherwise
+ A DNS lookup is required for each vhost.
+ </p>
+
+ <li> A DNS lookup is always required for the main_server's
+ <code>ServerName</code> (or to generate that if it isn't specified
+ in the config).
+ </p>
+
+ <li> If a <code>ServerPath</code> directive exists which is a prefix of
+ another <code>ServerPath</code> directive that appears later in
+ the configuration file, then the former will always be matched
+ and the latter will never be matched. (That is assuming that no
+ Host header was available to disambiguate the two.)
+
+ </ul>
+
+ <a name="whatworks"><h3>What Works</h3></a>
+
+ <p>In addition to the tips on the <a href="dns-caveats.html#tips">DNS
+ Issues</a> page, here are some further tips:
+
+ <ul>
+
+ <li>Place all main_server definitions before any VirtualHost definitions.
+ (This is to aid the readability of the configuration -- the post-config
+ merging process makes it non-obvious that definitions mixed in around
+ virtualhosts might affect all virtualhosts.)
+
+ <li>Arrange your VirtualHosts such
+ that all name-based virtual hosts come first, followed by ip-based
+ virtual hosts, followed by any _default_ virtual host
+
+ <li>Avoid <code>ServerPaths</code> which are prefixes of other
+ <code>ServerPaths</code>. If you cannot avoid this then you have to
+ ensure that the longer (more specific) prefix vhost appears earlier in
+ the configuration file than the shorter (less specific) prefix. (i.e.
+ "ServerPath /abc" should appear after "ServerPath /abcdef").
+
+ </ul>
+
+ <!--#include virtual="footer.html" -->
+ </BODY>
+ </HTML>
+
diff --new-file -c3 -r -x CVS apache3/src/CHANGES apache-vhost-cleanup/src/CHANGES
*** apache3/src/CHANGES Sat Mar 15 18:29:14 1997
--- apache-vhost-cleanup/src/CHANGES Sat Mar 15 18:38:35 1997
***************
*** 1,5 ****
--- 1,11 ----
Changes with Apache 1.2b8
+ *) Add documentation for DNS issues (reliability and security), and try
+ to explain the virtual host matching process. [Dean Gaudet]
+
+ *) Try to continue gracefully by disabling the vhost if a DNS lookup
+ fails while parsing the configuration file. [Dean Gaudet]
+
*) Workaround to a compiler bug that causes SunOS 4.1.x to panic.
[Roy Fielding]
diff --new-file -c3 -r -x CVS apache3/src/http_config.c apache-vhost-cleanup/src/http_config.c
*** apache3/src/http_config.c Sat Mar 15 18:29:16 1997
--- apache-vhost-cleanup/src/http_config.c Sat Mar 15 18:33:33 1997
***************
*** 902,909 ****
hep = gethostbyname(w);
if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
! fprintf (stderr, "Cannot resolve host name %s --- exiting!\n", w);
! exit(1);
}
for( i = 0; hep->h_addr_list[i]; ++i ) {
--- 902,910 ----
hep = gethostbyname(w);
if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
! fprintf (stderr, "Cannot resolve host name %s --- ignoring!\n", w);
! if (t != NULL) *t = ':';
! return;
}
for( i = 0; hep->h_addr_list[i]; ++i ) {
***************
*** 952,962 ****
}
/* terminate the list */
*addrs = NULL;
! if( s->addrs == NULL ) {
! fprintf( stderr, "virtual host must have at least one address\n" );
! exit(1);
}
- s->port = s->addrs->host_port; /* set them the same, by default */
s->next = NULL;
s->is_virtual = 1;
--- 953,961 ----
}
/* terminate the list */
*addrs = NULL;
! if( s->addrs ) {
! s->port = s->addrs->host_port; /* set them the same, by default */
}
s->next = NULL;
s->is_virtual = 1;
diff --new-file -c3 -r -x CVS apache3/src/http_main.c apache-vhost-cleanup/src/http_main.c
*** apache3/src/http_main.c Sat Mar 15 18:29:17 1997
--- apache-vhost-cleanup/src/http_main.c Sat Mar 15 18:33:33 1997
***************
*** 1437,1443 ****
char *def_hostname;
int n;
server_addr_rec *sar;
! int has_inaddr_any;
int mainport = s->port;
int from_local=0;
--- 1437,1443 ----
char *def_hostname;
int n;
server_addr_rec *sar;
! int has_default_vhost_addr;
int mainport = s->port;
int from_local=0;
***************
*** 1476,1489 ****
for (s = s->next; s; s = s->next) {
/* Check to see if we might be a HTTP/1.1 virtual host - same IP */
! has_inaddr_any = 0;
for (n = 0; n < num_addr; n++) {
for(sar = s->addrs; sar; sar = sar->next) {
if (sar->host_addr.s_addr == main_addr[n].s_addr &&
s->port == mainport)
s->is_virtual = 2;
! if( sar->host_addr.s_addr == htonl(INADDR_ANY) ) {
! has_inaddr_any = 1;
}
}
}
--- 1476,1489 ----
for (s = s->next; s; s = s->next) {
/* Check to see if we might be a HTTP/1.1 virtual host - same IP */
! has_default_vhost_addr = 0;
for (n = 0; n < num_addr; n++) {
for(sar = s->addrs; sar; sar = sar->next) {
if (sar->host_addr.s_addr == main_addr[n].s_addr &&
s->port == mainport)
s->is_virtual = 2;
! if( sar->host_addr.s_addr == DEFAULT_VHOST_ADDR ) {
! has_default_vhost_addr = 1;
}
}
}
***************
*** 1492,1512 ****
the presence of multiple addresses on the <VirtualHost>
directive. It should issue warnings here perhaps. -djg */
if (!s->server_hostname) {
! if (s->is_virtual == 2)
! s->server_hostname = s->addrs->virthost;
! else if (has_inaddr_any)
s->server_hostname = def_hostname;
! else
! {
! h = gethostbyaddr ((char *)&(s->addrs->host_addr),
! sizeof (struct in_addr), AF_INET);
! if (h != NULL)
s->server_hostname = pstrdup (pconf, (char *)h->h_name);
! else
! {
! fprintf(stderr,"Failed to resolve server name for %s (check DNS)\n",inet_ntoa(s->addrs->host_addr));
! exit(0);
}
}
}
}
--- 1492,1524 ----
the presence of multiple addresses on the <VirtualHost>
directive. It should issue warnings here perhaps. -djg */
if (!s->server_hostname) {
! if (s->is_virtual == 2) {
! if (s->addrs) {
! s->server_hostname = s->addrs->virthost;
! } else {
! /* what else can we do? at this point this vhost has
! no configured name, probably because they used
! DNS in the VirtualHost statement. It's disabled
! anyhow by the host matching code. -djg */
! s->server_hostname = "bogus_host_without_forward_dns";
! }
! } else if (has_default_vhost_addr) {
s->server_hostname = def_hostname;
! } else {
! if (s->addrs
! && (h = gethostbyaddr ((char *)&(s->addrs->host_addr),
! sizeof (struct in_addr), AF_INET))) {
s->server_hostname = pstrdup (pconf, (char *)h->h_name);
! } else {
! /* again, what can we do? They didn't specify a
! ServerName, and their DNS isn't working. -djg */
! if (s->addrs) {
! fprintf(stderr, "Failed to resolve server name "
! "for %s (check DNS)\n",
! inet_ntoa(s->addrs->host_addr));
}
+ s->server_hostname = "bogus_host_without_reverse_dns";
+ }
}
}
}
diff --new-file -c3 -r -x CVS apache3/src/http_protocol.c apache-vhost-cleanup/src/http_protocol.c
*** apache3/src/http_protocol.c Sat Mar 15 18:29:17 1997
--- apache-vhost-cleanup/src/http_protocol.c Sat Mar 15 18:33:33 1997
***************
*** 656,661 ****
--- 656,667 ----
const char *names;
server_addr_rec *sar;
+ if (s->addrs == NULL) {
+ /* this server has been disabled because of DNS screwups during
+ configuration */
+ continue;
+ }
+
if ((!strcasecmp(host, s->server_hostname)) && (port == s->port)) {
r->server = r->connection->server = s;
if (r->hostlen && !strncmp(r->uri, "http://", 7)) {
***************
*** 703,709 ****
*/
for (s = r->server->next; s; s = s->next) {
! if (s->path && !strncmp(r->uri, s->path, s->pathlen) &&
(s->path[s->pathlen - 1] == '/' ||
r->uri[s->pathlen] == '/' ||
r->uri[s->pathlen] == '\0'))
--- 709,715 ----
*/
for (s = r->server->next; s; s = s->next) {
! if (s->addrs && s->path && !strncmp(r->uri, s->path, s->pathlen) &&
(s->path[s->pathlen - 1] == '/' ||
r->uri[s->pathlen] == '/' ||
r->uri[s->pathlen] == '\0'))