HowTo: Curl applications that are usually behind reverse proxies with TLS termination without the application redirecting to https schema

Posted . Visible to the public.

A lot of web applications require being called over https, which is a good thing. It's possible to configure this requirement at the web- or proxy server level, where nginx or apache will just redirect every request on http to https. Some applications additionally detect if the URL they've been called with contains the http or the https scheme and issue their own redirect response (usually 301 or 302) to https. This card is for the later kind.

The Problem

When you want to test your application directly on the VM it's running and usually it's the proxy server or webserver that does handles SSL, the port where the application is running is often times only responding to http requests without SSL. However the application will still redirect to https URLs which might not work for testing directly on the VM.

$ curl -v http://localhost:12345
*   Trying 127.0.0.1:12345...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 12345 (#0)
> GET / HTTP/1.1
> Host: localhost:12345
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Date: Wed, 26 Apr 2023 06:38:09 GMT
< Server: Apache
< Location: https://localhost:12345/
< Content-Length: 0
< Status: 301 Moved Permanently
< Connection: close
< Content-Type: text/html
< 
* Closing connection 0
$ curl -v https://localhost:12345
*   Trying 127.0.0.1:12345...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 12345 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* error:1408F10B:SSL routines:ssl3_get_record:wrong version number
* Closing connection 0
curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number

We've manually followed the 301 redirect here and ended up expecting https traffic on a port that only responds with unencrypted http traffic, hence the not so obvious error message.

The Solution

Most applications respect the "X-Forwarded-Proto: https" header that most reverse proxies set when handling SSL on their end and forwarding requests to the application. This is how the proxy server tells the application which schema the client used when calling the URL in the first place.

$ curl -IH "X-Forwarded-Proto: https" http://localhost:12345
HTTP/1.1 200 OK
#[…] rest of the regular http response truncated
Florian Heinle
Last edit
Florian Heinle
License
Source code in this card is licensed under the MIT License.