Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Olivier Mehani-5
Hi all,

I have been battling with this issue for far too long, and I am at wits
end.

I have an OpenBSD 5.4 machine, with httpd serving pages successfully
over both HTTP and HTTPS (with a CaCert-issued certificate).  I want to
serve multiple sites on both protocols (the certificate has AltNames for
the various sites).

(Almost) everything works fine, and I do indeed manage to successfully
access all sites over HTTPS as expected. However, the HTTPS environment
variable, which should be set to 'on' for HTTPS sessions, is missing for
all but the first VHost. This is problematic because multiple apps
(mostly php-5.3.27, but also some CGI and Rewrites) inspect this
variable and behave differently depending on whether it is set to 'on'
or anything else.

The relevant bits of my configuration file are as follows (diffed from
the original src/usr.sbin/httpd/conf/httpd.conf from CVS on branch
OPENBSD_5_4):
  938a939,940
  > NameVirtualHost *:80
  > NameVirtualHost *:443
  1024,1025c1026,1027
  < ServerName new.host.name
  < ServerAdmin [hidden email]
  ---
  > #ServerName new.host.name
  > #ServerAdmin [hidden email]
  1121a1124,1125
  >
  > Include /srv/www/conf/sites.d

The ServerName/ServerAdmin/... are all in the <VirtualHost _default_:443>
group. The Include is at the very end of the file.

I reduced my test case to /srv/www/conf/sites.d containing only one
file:
<VirtualHost *:80 *:443>
        ServerName www.domain2.tld
        ServerAdmin [hidden email]
        DocumentRoot /var/www/sites/domain2.tld/www
</VirtualHost>
<Directory "/sites/domain2.tld/www">
        Options MultiViews SymLinksIfOwnerMatch Includes
        AllowOverride FileInfo
        Order allow,deny
        Allow from all
</Directory>
 
Neither /var/www/htdocs nor /var/www/sites/domain2.tld/www contain
.htaccess files.

This is a rather standard setup, and I've had this working on previous
machines (<=5.3). The HTTPD and SSL logs do not show any error nor
warning. I have been trying many combinations of NameVirtualHost,
VirtualHost and ServerName / ServerAlias.

In all (working) cases, the first (_default_) VHost has HTTPS set to
'on', and the other one simply hasn't anything set (as shown through a
phpinfo() page). Swapping the ServerName of the _default_ VHost to
another of the AltName'd names in the certificare sees that particular
domain get the HTTPS variable, and none of the others.

I'm not sure what to try next, if there is indeed anything else. Could
anybody offer some insight/experience about this type of setups? I guess
I'm missing something obvious, but searching the web for hours on end
hasn't yielded anything helpful... Does anybody have any idea what the
problem might be there?

--
Olivier Mehani <[hidden email]>
PGP fingerprint: 4435 CF6A 7C8D DD9B E2DE  F5F9 F012 A6E2 98C6 6655
Confidentiality cannot be guaranteed on emails sent or received unencrypted.

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Philip Guenther-2
On Mon, Feb 17, 2014 at 5:08 AM, Olivier Mehani <[hidden email]> wrote:
> I have an OpenBSD 5.4 machine, with httpd serving pages successfully
> over both HTTP and HTTPS (with a CaCert-issued certificate).  I want to
> serve multiple sites on both protocols (the certificate has AltNames for
> the various sites).
>
> (Almost) everything works fine, and I do indeed manage to successfully
> access all sites over HTTPS as expected. However, the HTTPS environment
> variable, which should be set to 'on' for HTTPS sessions, is missing for
> all but the first VHost. This is problematic because multiple apps
...

I don't have any good suggestions on how to fix or workaround this
apparent bug in httpd (other than "look at the code paths leading to
where HTTPS is added to the environment, sent breakpoints, compare
good/bad runs, use logic, etc").  My more useful suggestion is to test
out switching from httpd to nginx.  nginx was added to base with the
goal of deleting httpd from the tree, so moving now, particularly when
you're affected by a bug in httpd, should be a Good Idea.


Philip Guenther

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Olivier Mehani
Hey Philip,

On February 20, 2014 7:49:17 PM AEDT, Philip Guenther <[hidden email]> wrote:

>> (Almost) everything works fine, and I do indeed manage to
>successfully
>> access all sites over HTTPS as expected. However, the HTTPS
>environment
>> variable, which should be set to 'on' for HTTPS sessions, is missing
>for
>> all but the first VHost.
>I don't have any good suggestions on how to fix or workaround this
>apparent bug in httpd (other than "look at the code paths leading to
>where HTTPS is added to the environment, sent breakpoints, compare
>good/bad runs, use logic, etc").

I had a quick go at that, but I found the mod_ssl code to be rather cryptic.

> My more useful suggestion is to test
>out switching from httpd to nginx.  nginx was added to base with the
>goal of deleting httpd from the tree, so moving now, particularly when
>you're affected by a bug in httpd, should be a Good Idea.

Ah, right. I did try nginx out before switching back to httpd because I had troubles getting a similar setup going (mainly, getting php-fpm to behave across multiple vhosts and UrerDirs without having to duplicate too much configuration snippets). I'm not that familiar with it, but it does sound like one more reason to try it again.

Thanks for the suggestion!

I'm still open to ideas regarding fixing httpd. I'll settle for whichever works satisfactorily first (:


--
Olivier Mehani <[hidden email]>
Sent from my mobile, please excuse my brevity.

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Joel Sing-3
In reply to this post by Olivier Mehani-5
On Tue, 18 Feb 2014, Olivier Mehani wrote:

> Hi all,
>
> I have been battling with this issue for far too long, and I am at wits
> end.
>
> I have an OpenBSD 5.4 machine, with httpd serving pages successfully
> over both HTTP and HTTPS (with a CaCert-issued certificate).  I want to
> serve multiple sites on both protocols (the certificate has AltNames for
> the various sites).
>
> (Almost) everything works fine, and I do indeed manage to successfully
> access all sites over HTTPS as expected. However, the HTTPS environment
> variable, which should be set to 'on' for HTTPS sessions, is missing for
> all but the first VHost. This is problematic because multiple apps
> (mostly php-5.3.27, but also some CGI and Rewrites) inspect this
> variable and behave differently depending on whether it is set to 'on'
> or anything else.
>
> The relevant bits of my configuration file are as follows (diffed from
> the original src/usr.sbin/httpd/conf/httpd.conf from CVS on branch
> OPENBSD_5_4):
>   938a939,940
>
>   > NameVirtualHost *:80
>   > NameVirtualHost *:443
>
>   1024,1025c1026,1027
>   < ServerName new.host.name
>   < ServerAdmin [hidden email]
>   ---
>
>   > #ServerName new.host.name
>   > #ServerAdmin [hidden email]
>
>   1121a1124,1125
>
>   > Include /srv/www/conf/sites.d
>
> The ServerName/ServerAdmin/... are all in the <VirtualHost _default_:443>
> group. The Include is at the very end of the file.
>
> I reduced my test case to /srv/www/conf/sites.d containing only one
> file:
> <VirtualHost *:80 *:443>
>         ServerName www.domain2.tld
>         ServerAdmin [hidden email]
>         DocumentRoot /var/www/sites/domain2.tld/www
> </VirtualHost>
> <Directory "/sites/domain2.tld/www">
>         Options MultiViews SymLinksIfOwnerMatch Includes
>         AllowOverride FileInfo
>         Order allow,deny
>         Allow from all
> </Directory>
>
> Neither /var/www/htdocs nor /var/www/sites/domain2.tld/www contain
> .htaccess files.
>
> This is a rather standard setup, and I've had this working on previous
> machines (<=5.3). The HTTPD and SSL logs do not show any error nor
> warning. I have been trying many combinations of NameVirtualHost,
> VirtualHost and ServerName / ServerAlias.
>
> In all (working) cases, the first (_default_) VHost has HTTPS set to
> 'on', and the other one simply hasn't anything set (as shown through a
> phpinfo() page). Swapping the ServerName of the _default_ VHost to
> another of the AltName'd names in the certificare sees that particular
> domain get the HTTPS variable, and none of the others.
>
> I'm not sure what to try next, if there is indeed anything else. Could
> anybody offer some insight/experience about this type of setups? I guess
> I'm missing something obvious, but searching the web for hours on end
> hasn't yielded anything helpful... Does anybody have any idea what the
> problem might be there?

Name-based virtual hosting and SSL is a can of worms. In short, without SNI
(which AFAICT the base httpd does not support) the server does not know which
virtual server is required until after the SSL session has already been
established. To be honest I am somewhat surprised that this actually works as
well as it does - seemingly once SSL has been negotiated with the
_default_:443 virtual host it will then switch virtual hosts based on the
Host: header (which is how non-SSL name-based virtual hosting works).

In this particular case the lack of HTTPS=on is due to the fact that you do
not actually have SSL enabled in the /srv/www/conf/sites.d/ configuration
snippet. Normally this would have (at minimum) SSLEngine, SSLCertificateFile
and SSLCertificateKeyFile directives in the /srv/www/conf/sites.d/
VirtualHost configuration files (as an aside, if your hosting/application
requires SSL, you probably should consider setting up :80 as a redirect to
https, rather than configuring both *:80 and *:443 on the same virtual host).

Generally speaking, you will likely have fewer challenges if you configure
each HTTPS virtual host using a dedicated IP address (or port). That way the
virtual host selection is made prior to SSL negotitation occurring.
--

    "Action without study is fatal. Study without action is futile."
        -- Mary Ritter Beard

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Markus Wernig
Not sure about the ported httpd, but usually you have to enable the
generation of those environment vars with

SSLOptions +StdEnvVars

as they are off by default.

krgds /m

> On Tue, 18 Feb 2014, Olivier Mehani wrote:

>> (Almost) everything works fine, and I do indeed manage to
>> successfully
>> access all sites over HTTPS as expected. However, the HTTPS
>> environment
>> variable, which should be set to 'on' for HTTPS sessions, is missing
>> for
>> all but the first VHost.

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Stuart Henderson
In reply to this post by Joel Sing-3
On 2014-02-20, Joel Sing <[hidden email]> wrote:
> Name-based virtual hosting and SSL is a can of worms. In short, without SNI
> (which AFAICT the base httpd does not support) the server does not know which
> virtual server is required until after the SSL session has already been
> established.

SNI is only needed in order to choose a suitable server certificate.
If you have a certificate valid for all hostnames you're expecting
(e.g. a wildcard certificate, or one using SAN) then Host: headers
are a reasonable way to switch virtual host.

Reply | Threaded
Open this post in threaded view
|

Re: Oddity with httpd/mod_ssl: missing HTTPS environment variable on non _default_ vhosts

Olivier Mehani
In reply to this post by Joel Sing-3
Hi Joel, all,

On Fri, Feb 21, 2014 at 12:14:28AM +1100, Joel Sing wrote:

> > I have an OpenBSD 5.4 machine, with httpd serving pages successfully
> > over both HTTP and HTTPS (with a CaCert-issued certificate).  I want to
> > serve multiple sites on both protocols (the certificate has AltNames for
> > the various sites).
> > (Almost) everything works fine, and I do indeed manage to successfully
> > access all sites over HTTPS as expected. However, the HTTPS environment
> > variable, which should be set to 'on' for HTTPS sessions, is missing for
> > all but the first VHost. This is problematic because multiple apps
> > (mostly php-5.3.27, but also some CGI and Rewrites) inspect this
> > variable and behave differently depending on whether it is set to 'on'
> > or anything else.
> >   NameVirtualHost *:80
> >   NameVirtualHost *:443
> >   <VirtualHost *:80 *:443>
> >           ServerName www.domain2.tld
> >           ServerAdmin [hidden email]
> >           DocumentRoot /var/www/sites/domain2.tld/www
> >   </VirtualHost>
> >   <Directory "/sites/domain2.tld/www">
> >           Options MultiViews SymLinksIfOwnerMatch Includes
> >           AllowOverride FileInfo
> >           Order allow,deny
> >           Allow from all
> >   </Directory>
> > This is a rather standard setup, and I've had this working on previous
> > machines (<=5.3). The HTTPD and SSL logs do not show any error nor
> > warning. I have been trying many combinations of NameVirtualHost,
> > VirtualHost and ServerName / ServerAlias.
> In this particular case the lack of HTTPS=on is due to the fact that you do
> not actually have SSL enabled in the /srv/www/conf/sites.d/ configuration
> snippet. Normally this would have (at minimum) SSLEngine, SSLCertificateFile
> and SSLCertificateKeyFile directives in the /srv/www/conf/sites.d/
> VirtualHost configuration files (as an aside, if your hosting/application
> requires SSL, you probably should consider setting up :80 as a redirect to
> https, rather than configuring both *:80 and *:443 on the same virtual
host).

Ha! This got me in the right direction. Thanks for your help! I now have
a working setup which is roughly as follows.

   <VirtualHost *:80>
           ServerName www.domain.tld
           ServerAlias domain.tld other.domain.tld
           ServerAdmin [hidden email]
           DocumentRoot /var/www/sites/domain.tld/www
   </VirtualHost>
   <VirtualHost *:443>
           ServerName www.domain.tld
           ServerAlias domain.tld other.domain.tld
           ServerAdmin [hidden email]
           DocumentRoot /var/www/sites/domain.tld/www

           SSLEngine on
           SSLCertificAteFile    /etc/ssl/server.crt
           SSLCertificateKeyFile /etc/ssl/private/server.key
   </VirtualHost>
   <Directory "/sites/domain.tld/www">
           Options MultiViews SymLinksIfOwnerMatch Includes
           AllowOverride FileInfo

           ErrorDocument 404 /404.xhtml

           Order allow,deny
           Allow from all

           # Redirect aliases to the main name
           RewriteEngine On
           RewriteCond %{HTTPS} on
           RewriteRule ^(.*)$ - [env=REQUEST_SCHEME:https]
           RewriteCond %{HTTPS} !^on
           RewriteRule ^(.*)$ - [env=REQUEST_SCHEME:http]
           RewriteCond %{HTTP_HOST}        !^www.domain.tld
           RewriteRule (.*) %{ENV:REQUEST_SCHEME}://www.domain.tld/$1 [R,L]
   </Directory>

Essentially, it does create two VHosts on either port, with the required
SSL machinery for port 443. Then, most of the configuration I initially
had in the VHost (not shown before), has been moved to the DocumentRoot
Directory entry. This allows to avoid most of the configuration
duplication between clear/SSL VHosts, which I was trying to avoid by
having a single one.

As to why it worked in my previous configuration, you ask? Well I did
have exactly that. I just didn't see it when recreating the
configuration...

A note, though, is that using a single VHost for both non-SSL and SSL
ports does work, and the SSL connection is established properly
(provided at least one VHost, probably the first one, on port 443 is
properly configured for SSL with keys and certificates). The only
problem I could find was really in the missing mod_ssl environment
variables.

> Generally speaking, you will likely have fewer challenges if you configure
> each HTTPS virtual host using a dedicated IP address (or port). That way the
> virtual host selection is made prior to SSL negotitation occurring.

I only have a limited set of IPv4s (as in: 1), so I unfortunately cannot
do that.


Thanks again!

--
Olivier Mehani <[hidden email]>
PGP fingerprint: 4435 CF6A 7C8D DD9B E2DE  F5F9 F012 A6E2 98C6 6655
Confidentiality cannot be guaranteed on emails sent or received unencrypted.

[demime 1.01d removed an attachment of type application/pgp-signature which had a name of signature.asc]