ProxyPassReverse dropping HTTPS

Patrick Tucci picture Patrick Tucci · Jun 22, 2014 · Viewed 14.4k times · Source

On my home network, I have a web server and a DNS server. I have various other application servers that I have added redirects for so I can simply visit sites like myapplication.domain.com or www.domain.com/application to get to my various services. I have a Subsonic server running on another server, and my goal is to be able to visit https://subsonic.domain.com and get my Subsonic traffic served over SSL on my web server. Eventually I hope to access this from outside the home, which is why it's important to proxy the non-secured HTTP traffic over HTTPS, but for right now, I'm just trying to get it working at home.

When I visit https://subsonic.domain.com, I end up getting an "unable to connect" error. The address I appear to be redirected to is subsonic.domain.com/login.view. If I tack HTTPS onto the front of that URL, I get the login page I'm looking for. Once I log in again, however, the URL changes, I'm redirected, and I end up losing the HTTPS again an have to keep re-adding it. Obviously I am doing something wrong.

I have set up a VirtualHost for subsonic.domain.com and am trying to use ProxyPass and ProxyPassReverse to get the traffic redirected in the way I want. Here is my VirtualHost for this site:

    <VirtualHost subsonic.domain.com:443>

        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^(.*[^/])$ /$1/ [L,R=301]

        ProxyRequests Off
        ProxyErrorOverride Off
        ProxyPreserveHost On

        ServerAdmin webmaster@localhost

        ProxyPass / http://192.168.1.5:4040/
        ProxyPassReverse / http://192.168.1.5:4040/

        SSLEngine on

        SSLCertificateFile      /etc/apache2/ssl/apache.crt
        SSLCertificateKeyFile   /etc/apache2/ssl/apache.key

    </VirtualHost>

SSL is definitely up and running with no problem. I have another identical virtualhost for another directory that works fine (redirects on https://www.domain.com/directory), so I'm not sure what the problem is here. After the ProxyPassReverse, the URL just seems to be losing the https:// part. If I add it in, the site works fine until I visit another page and https:// is lost again. If I visit the application server directly at http://192.168.1.5:4040, I have no issues whatsoever.

Any advice would be most welcome.

EDIT

A little clarification on what I'm trying to do. I want to have my Apache server doing all of my redirecting and handling all of my SSL requests. Basically, from the browser to the Apache server is HTTPS, the ProxyPass from the Apache server to the application server us unencrypted HTTP (which is fine, this is my internal network), the ProxyPassReverse from the application server to the Apache server is plain HTTP, then the Apache server sends out the traffic as HTTPS.

Here's another VirtualHost that does what I want for a different subdomain. This is tested and works 100%. I connect to my Apache server via HTTPS, the Apache server contacts my ownCloud server in plain old HTTP, the response to my Apache server is plain HTTP, then the Apache server returns the request in HTTPS to the browser:

<VirtualHost www.domain.com:443>

            RewriteCond %{REQUEST_FILENAME} !-d
            RewriteCond %{REQUEST_FILENAME} !-f
            RewriteRule ^(.*[^/])$ /$1/ [L,R=301]

            ProxyRequests Off
            ProxyErrorOverride Off
            ProxyPreserveHost On

            ServerAdmin webmaster@localhost

            ProxyPass /owncloud/ http://192.168.1.251/owncloud/
            ProxyPassReverse /owncloud/ http://192.168.1.251/owncloud/

            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined

            SSLEngine on

            SSLCertificateFile      /etc/apache2/ssl/apache.crt
            SSLCertificateKeyFile   /etc/apache2/ssl/apache.key

</VirtualHost>

Answer

Jason Kincl picture Jason Kincl · Nov 26, 2014

So I ran into this problem as well and while commenting out ProxyPreserveHost fixes the problem with the configuration above, there is a better way.

The ProxyPass1 statement tells Apache to take an incoming request on the URI and pass it through to the specified host. With ProxyPreserveHost On, Apache does not change the Host: HTTP header and passes the request unmodified. (By default it changes it to match the backend host specified in the ProxyPass statement).

The ProxyPassReverse2 statement tells Apache to match the host specified with the Host: header on the outgoing response and if it matches to adjust the Location:, Content-Location:, and URI: headers to match the VirtualHost or more specifically what Apache thinks is the canonical name.

So with the following configuration:

<VirtualHost subsonic.domain.com:443>
    ProxyPreserveHost On

    ProxyPass / http://192.168.1.5:4040/
    ProxyPassReverse / http://192.168.1.5:4040/
</VirtualHost>

This is taking a request:

https://subsonic.domain.com/ -> http://192.168.1.5:4040/

but since ProxyPreserveHost is on, it is leaving the Host: header in the request intact as subsonic.domain.com

Your web application is most likely sending a response from subsonic.domain.com but that does not match the ProxyPassReverse rule you have specified:

http://subsonic.domain.com/ <- http://subsonic.domain.com/

So the configuration:

<VirtualHost subsonic.domain.com:443>
    ProxyPreserveHost On

    ProxyPass / http://192.168.1.5:4040/
    ProxyPassReverse / http://subsonic.domain.com/ # Changed to match canonical host
</VirtualHost>

This rule should match the replies coming from the proxy host.