43

I have a reverse proxy that does HTTPS on the outside, but HTTP on the inside.

This means that by default in-app URLs will have HTTP as the scheme, as this is the way it's being contacted.

How can the proxy tell the backend that HTTPS should be used?

Chris Wesseling
  • 6,226
  • 2
  • 36
  • 72

3 Answers3

41

The proxy can add extra (or overwrite) headers to requests it receives and passes through to the back-end. These can be used to communicate information to the back-end.

So far I've seen a couple used for forcing the use of https in URL scheme:

X-Forwarded-Protocol: https
X-Forwarded-Ssl: on
X-Url-Scheme: https

And wikipedia also mentions:

# a de facto standard:
X-Forwarded-Proto: https
# Non-standard header used by Microsoft applications and load-balancers:
Front-End-Https: on

This what you should add to the VirtualHost on : other proxies should have similar functionality

RequestHeader set X-FORWARDED-PROTOCOL https
RequestHeader set X-Forwarded-Ssl on
# etc.

I think it's best to set them all, or set one that works and remove the other known ones. To prevent evil clients messing with them.

Chris Wesseling
  • 6,226
  • 2
  • 36
  • 72
  • 5
    It's X-Forwarded-Proto, not X-Forwarded-Protocol, right? – mmoya Aug 05 '14 at 10:19
  • 2
    @mmoya I've seen them both. The latter even wins in a [googlebattle](http://www.googlebattle.com/?domain=x-forwarded-proto&domain2=x-forwarded-protocol&submit=Go%21). – Chris Wesseling Aug 06 '14 at 00:11
  • 4
    @mmoya ooh, shiny new RFC... june 2014, mint condition. ;-) – Chris Wesseling Aug 06 '14 at 14:58
  • 4
    For anyone who runs into this, you likely want X-Forwarded-Proto rather than X-Forwarded-Protocol. Protocol is non-standard, whereas AWS, RFC 7239, docker nginx-proxy, and many others use Proto. (Also, a googlebattle actually shows Proto winning by a large margin if you quote the search terms.) – Ryan Pendleton Feb 08 '17 at 09:10
3

It took me several hours of googling to find the magic setting for my environment. I have a SSL httpd Apache reverse proxy in front of a jetty app server and an apache2 http server. This answer actually gave me the information that worked. For me, adding:

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}

to the site conf file was enough for the destination to use https instead of http as the protocol when building links in the response. I tried the X-FORWARDED-PROTOCOL above, but that didn't work. Hopefully this will help in future Google searches!

MrWhite
  • 43,179
  • 8
  • 60
  • 84
Bryan
  • 295
  • 1
  • 2
  • 9
0

I've been fighting with this for a couple of days trying to setup a self-hosted GitLab Community Edition app. The rest of the app worked fine with SSL such as accessing Apache's default public directory and getting to GitLab's login page, but after logging in to GitLab would give an 'Error 422'.

Maybe this could help someone else who has a similar setup as mine.

Setup

  • Hardware: Linux 3.10.0-1160.6.1.el7.x86_64 x86_64 (cloud-hosted instance somewhere)
  • OS: CentOS Linux release 7.9.2009 (Core)
  • GitLab: "version":"15.9.3"
  • Apache: Server version: Apache/2.4.6 (CentOS), Server built: Jan 27 2023 17:36:29
  • Installed mod_ssl with dnf -y install mod_ssl and configured it (probably not a good idea for me to share how I configured that because I'm not sure about the security regarding that one, so good luck on that if you haven't already)

Goals

  • Ignore all requests on port 80
  • Only accept HTTPS requests
  • Access GitLab through port 8081 via proxy
  • Access Apache's default directory when not specifying port 8081 in the URL

Solution

  • All I had to do was add RequestHeader set X-Forwarded-Ssl on to my existing /etc/httpd/conf/[MY_SITE].conf file.

Here are my configs, minus my IP's and such.

  • /etc/httpd/conf/httpd.conf
...snip...
#Listen 80
Listen 8081
...snip...
  • /etc/httpd/conf/[MY_SITE].conf
<VirtualHost [redacted]:8081>
  ServerName [redacted]
  ServerSignature Off
  ProxyPreserveHost On

  SSLEngine on
  SSLCertificateFile [redacted]
  SSLCertificateKeyFile [redacted]
  RequestHeader set X-Forwarded-Ssl on

  AllowEncodedSlashes NoDecode

  <Location />
    Require all granted
    ProxyPassReverse http://[redacted]
    ProxyPassReverse http://[redacted]
  </Location>

  RewriteEngine on

  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
  RewriteCond %{REQUEST_URI} ^/uploads/.*
  RewriteRule .* http://[redacted]

  DocumentRoot /opt/gitlab/embedded/service/gitlab-rails/public

  ErrorDocument 404 /404.html
  ErrorDocument 422 /422.html
  ErrorDocument 500 /500.html
  ErrorDocument 502 /502.html
  ErrorDocument 503 /503.html

  LogFormat [redacted]
  CustomLog [redacted]

  SSLCipherSuite EECDH+AESGCM:EDH+AESGCM
  SSLProtocol -all +TLSv1.2
  SSLHonorCipherOrder On
  Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains"   
  SSLCompression off
  SSLUseStapling on
</VirtualHost>

SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
wmcooper2
  • 11
  • 3