Noky
Noky

Reputation: 513

Apache: force HTTPS on when behind SSL-terminating reverse proxy

I am using apache 2.4.57 behind an SSL-terminating reverse-proxy (Traefik in my case). Traefik takes https requests and proxies them to apache port 80 with the following HTTP headers set: X-Forwarded-Proto and X-Forwarded-For.

My problem is that I cannot get apache to recognize that requests are actually using the https scheme. This is problematic because I have a ton of RewriteRule configurations that result in 302 responses which contain an http scheme like this: location: http://myhostname.org/mypath. This sometimes results in MixedContent errors with my application.

Ideally, I'd like to add this to my VirtualHost config:

SetEnvIf X-Forwarded-Proto "https" HTTPS=on

But the HTTPS variable always remains off. In fact, even when I configure SetEnv HTTPS on the HTTPS variable still stays off.

Abbreviated config is something like this:

<VirtualHost *:80>
    SetEnvIf X-Forwarded-Proto "https" HTTPS=on
    RewriteEngine On

    # Debug: Show X-Forwarded-Proto header and HTTPS variable
    RewriteRule ^/debug$ /debug?xfp=%{HTTP:X-Forwarded-Proto}&https=%{HTTPS} [R,L]

    # Lots of other RewriteRules below...
</VirtualHost>

When I try a test with curl I get:

curl -v https://myhostname.org/debug 2>&1 |grep location
< location: http://myhostname.org/debug?xfp=https&https=off

Why doesn't this work? How do I force HTTPS on and make all my RewriteRules return a location with https?

UPDATE

I ended up using a modified version of the answer provided by @VonC. Note that SetEnvIf works to set a user environment variable, it apparently just can't be used to override the built-in apache variable HTTPS. This solution unfortunately required me to manually change all my RewriteRule stanzas.

SetEnvIf X-Forwarded-Proto https HTTP_SCHEME=https
SetEnvIf HTTP_SCHEME ^$ HTTP_SCHEME=http

# prepend scheme/host to substitution portion of each RewriteRule 
RewriteRule ^/foo$ %{ENV:HTTP_SCHEME}://%{HTTP_HOST}/bar [R,L]

In the future, I'm hoping that apache/httpd PR 191 provides an easier way to address this issue.

Upvotes: 3

Views: 2017

Answers (1)

Mo Beigi
Mo Beigi

Reputation: 1765

I had the exact same issue and found a great solution.

You want to set a https:// prefixed ServerName and all Apache features will then detect this and work well.

<VirtualHost *:80>
  ServerName https://example.com
</VirtualHost>

Based on this extend answer:
https://wordpress.stackexchange.com/a/426382/15509

Upvotes: 1

Related Questions