Search code examples
apachevirtualhostdocument-root

VirtualHosts ONLY no default?


I have a debian setup with Apache. I disabled the 'default' site and added a single one for now.

I want to disable access to everything except that which is under the various vhosts.

<VirtualHost *:80>
  DocumentRoot /var/www/mycompany/websites/corporate
  <Directory /var/www/mycompany/websites/corporate>
    Order deny,allow
    Allow from all
    Options FollowSymLinks
  </Directory>
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot /var/www/mycompany/websites/leisure
  <Directory /var/www/mycompany/websites/leisure>
    Order deny,allow
    Allow from all
    Options FollowSymLinks
  </Directory>
</VirtualHost>

This has no effect. The problem is when I access the webserver via the IP address, the default scripts run, which is not desired. I want the IP address to show a custom 404 or something.

EDIT | I have re-enabled the 'default' site with the hopes of blocking all access -- excluding of course each of the virtual hosts and their docroots and children.

How would I accomplish this goal???


Solution

  • Your virtualhosts lacks the ServerName which would allow the HTTP request hostname<->Virtualhost mapping.

    So, first, add the right Servername on the Virtualhosts.

    Then if you want all other names to render a 404 you absolutely need a default virtualhost. This default virtualhost will catch any request using an unrecognized Host header in the HTTP request (so IP based access, or other DNS associated with your IP, or faked host headers).

    The default Virtualhost is the first one loaded in the apache configuration, in debian-like systems the included file is prefixed by a 00 and included dirs are loaded in alphabetical order to enforce this status. you can always check which Virtualhost is the default one by using the -S option.

    # debian-like
    apachectl -S
    # redhat like
    httpd -S
    

    Then if you want all these access to the default Virtualhost to render a 404 you simply need to make this Virtualhost like a very simple one (always a good idea to remove all the default crap there) with a 404 response for eveything:

    <Virtualhost *:80>
      ServerName _default
      # do not set that docroot as a parent of real doc root
      # you do not want to let access to /var/www/mycompany as /company
      # so create that directory
      DocumentRoot /var/www/default
      ErrorLog /var/log/apache2/error.log
      CustomLog /var/log/apache2/access-default.log combined
      <Directory />
        Options FollowSymLinks
        AllowOverride None
        # apache<2.3 syntax
        Order allow,deny
        allow from all
      </Directory>
    
      # Now catch everything and throw a 404
      # you'll need mod_alias for that (usually already there)
      RedirectMatch 404 ^(.*)
    
    </Virtualhost>
    

    This is not an absolute protection against HTTP request Host headers manipulation (they're still strange ways to match your Virtualhost with absolute URI and faked hosts headers) but that's a very good start.

    If you want to ensure the HOST header of the HTTP request reaching your Virtualhost is the one defined in the Virtualhost (and only that one) you can add a mod_rewrite check on the final Virtualhost.

    So in you example, for the directory leisure, let's say the ServerName should be www.leisure.com. In the Directory I would add this:

    <Directory /var/www/mycompany/websites/leisure>
        Order deny,allow
        Allow from all
        Options FollowSymLinks
        # not the right domain? -> 403
        RewriteEngine On
        RewriteCond %{HTTP_HOST} !^www\.leisure\.com [NC]
        RewriteRule .* - [F,L]
    </Directory>