5

We have a server running seven domains/subdomains. To try to go as minimal as possible here I'll include four of them.

  1. example.com
  2. www.example.com
  3. dwf.example.com
  4. chris.example.com

The server works great 90% of the time, but occasionally we get a larger number of requests and the database server goes down. This then max's out the apache connections, because all the db connections are waiting to timeout. All well and good, we force a restart on the DB, and connections come back up. However, the requests are then coming to the dfw.example.com configuration. That deployment doesn't have our codebase, which is a big issue and I don't understand why that is happening. It also consistently goes to that deployment when this happens and never any of the other 5 we have.

From the documentation I read, I thought Apache read through the httpd.conf file and looked for the first NamedVirtualHost match:

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.

We are running Apache 2.2.15.

Parts I think are relevant from the httpd.conf file:

Listen 80
Listen 255.255.255.255:443

...

ServerName www.example.com

... (this is the exact order, www (https/http), dfw, then all other versions)

NameVirtualHost www.example.com:80
<VirtualHost    www.example.com:80>
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/html/www.example.com
    ServerName www.example.com
    DirectoryIndex index.html
    DirectoryIndex index.php
    LogLevel notice
    ErrorLog /var/log/httpd/www.example.com/error.log
    CustomLog /var/log/httpd/www.example.com/access.log w3c_extended
</VirtualHost>

NameVirtualHost www.example.com:443
<VirtualHost www.example.com:443>
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/html/www.example.com
    ServerName www.example.com
    #certificate stuff
    DirectoryIndex index.html
    DirectoryIndex index.php
    LogLevel notice
    ErrorLog /var/log/httpd/www.example.com/error.log
    CustomLog /var/log/httpd/www.example.com/access.log w3c_extended 
</VirtualHost>

NameVirtualHost dfw.example.com:80
<VirtualHost    dfw.example.com:80>
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/html/dfw.example.com
    ServerName dfw.example.com
    DirectoryIndex index.html
    DirectoryIndex index.php
    LogLevel notice
    ErrorLog /var/log/httpd/dfw.example.com/error.log
    CustomLog /var/log/httpd/dfw.example.com/access.log w3c_extended
</VirtualHost>
NameVirtualHost chris.example.com:443
<VirtualHost    chris.example.com:443>
    ServerAdmin chris.macdonald@example.com
    DocumentRoot /var/www/html/chris.example.com
#cert stuff
    ServerName chris.example.com
    DirectoryIndex index.html
    DirectoryIndex index.php
    LogLevel notice
    ErrorLog  /var/log/httpd/chris.example.com/error.log
    CustomLog /var/log/httpd/chris.example.com/access.log w3c_extended
</VirtualHost>

NameVirtualHost chris.example.com:80
<VirtualHost    chris.example.com:80>
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/html/chris.example.com
    ServerName chris.example.com
    DirectoryIndex index.html
    DirectoryIndex index.php
    LogLevel notice
    RewriteLog /home/chris/writinglog.log
    RewriteLogLevel 8
    ErrorLog /var/log/httpd/chris.example.com/error.log
    CustomLog /var/log/httpd/chris.example.com/access.log w3c_extended
    CheckSpelling on
</VirtualHost>

Doing a sudo service httpd restart gets the correct deployment serving again.

Output from apachectl -S:

VirtualHost configuration:
[IPV6ADDRESS]:443 is a NameVirtualHost
         default server chris.example.com (/etc/httpd/conf/httpd.conf:1077)
         port 443 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1077)
[IPV6ADDRESS]:80 is a NameVirtualHost
         default server chris.example.com (/etc/httpd/conf/httpd.conf:1095)
         port 80 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1095)
         port 80 namevhost cory.example.com (/etc/httpd/conf/httpd.conf:1128)
IPV4Address:80      is a NameVirtualHost
         default server www.example.com (/etc/httpd/conf/httpd.conf:1035)
         port 80 namevhost dfw.example.com (/etc/httpd/conf/httpd.conf:1065)
        port 80 namevhost www.example.com (/etc/httpd/conf/httpd.conf:1035)
         port 80 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1095)
IPV4Address:443     is a NameVirtualHost
         default server www.example.com (/etc/httpd/conf/httpd.conf:1047)
         port 443 namevhost www.example.com (/etc/httpd/conf/httpd.conf:1047)
         port 443 namevhost chris.example.com (/etc/httpd/conf/httpd.conf:1077)
wildcard NameVirtualHosts and _default_ servers:
_default_:443          www.example.com (/etc/httpd/conf.d/ssl.conf:74)
Syntax OK
chris85
  • 81
  • 2
  • 11
  • Can you post the output of apache2ctl -S and are *.example.com all pointing to the same ip address ? – Lazy404 May 31 '16 at 18:13
  • That brings back `apache2ctl: command not found`. `httpd -v` gives `Server version: Apache/2.2.15 (Unix)` The DNS records all point to the same IP. – chris85 May 31 '16 at 18:19
  • please try apachectl -S – Lazy404 May 31 '16 at 18:36
  • 1
    Okay, updated question with the output of that. The IPV6 settings on my domain is because I was fiddling around with getting that running. – chris85 May 31 '16 at 18:52
  • Everything looks OK. I'd capture some client requests to verify they are sending the correct `Host:` header. Also in the definition of dfw.example.com you have `ServerName example.example.com` which seems odd. – Mark Wagner Jun 07 '16 at 00:42
  • Also, does this happen for both port 80 and 443? – Mark Wagner Jun 07 '16 at 00:43
  • @MarkWagner Oh, yea that is just a typo here, guess I pasted example twice there. When I've encountered this it has been on port 80, I have received it by loading `http://www.example.com`, so I think the `Host` would be correct. This doesnt appear to be forged headers, just all requests end up in the DFW configuration. How can I log the incoming headers? – chris85 Jun 07 '16 at 01:03
  • Actually just grepped the access logs and there were no 443 connections going to it. – chris85 Jun 07 '16 at 01:07
  • I'd run a port 80 packet capture on the server. – Mark Wagner Jun 07 '16 at 17:48
  • Does it go back to working once Apache is restarted? – Schrute Jun 07 '16 at 21:45
  • @MarkWagner capturing port 80 isn't really possibly. We have a large amount of traffic and this issue occurs pretty irregularly. – chris85 Jun 07 '16 at 21:46
  • @Schrute Yup, as soon as a restart it server correctly again. – chris85 Jun 07 '16 at 21:46
  • 1
    I would suggest logging the host header in your access log. Add the following to the end of the relevant LogFormat: \"Host: %{Host}i\" Also using host names as the argument in a tags is almost always a bad idea since it means your Apache startup relies on an external service (DNS). I'd also be tempted to remove your default SSL vhost in /etc/httpd/conf.d/ssl.conf as it has the same ServerName as another vhost. – Unbeliever Sep 27 '16 at 07:07

1 Answers1

1

I am not sure if its good that you have multiple NameVirtualHost * directives. As I understand your question, you yust want a pure NAME Virtual Host and you want that all interfaces on all ports are handled by NameVirtual Host.

I would recoment you to create you hosts like this:

# Use Virtual hosts for all interfaces on all ports
NameVirtualHost *


<VirtualHost *>
  ServerName example.com
  # all other settings for this hostname
</VirtualHost>

<VirtualHost *>
  ServerName www.example.com
  # all other settings for this hostname
</VirtualHost>

<VirtualHost *>
  ServerName dfw.example.com
  # all other settings for this hostname
</VirtualHost>

<VirtualHost *>
  chris.example.com
  # all other settings for this hostname
</VirtualHost>



## ssl.conf
<VirtualHost _default_:443>
  ServerName www.example.com
  # all other settings for this hostname
  SSLEngine on
  #certificate stuff
</VirtualHost>

And if you want to use the same settings for multiple hostnames (e.g. example.com and www.example.com) you could simple add ServerAlias directive where all Hostnames are listed (wildcards like "*.example.com" are possible too).

e.g. a virtual host what matches "example.com" and "www.example.com" could be done like this:

<VirtualHost *>
  ServerName example.com
  ServerAlias example.com www.example.com
  # all other settings for this hostname
</VirtualHost>

p.s. Settings like DirectoryIndex or LogLevel you can define once in your global config. Your virtual host will take the global config and you dont need to add the same value to each host.

Only if one host needs a config different to global values, you must add the special settings in this host.

Radon8472
  • 185
  • 8