From e5c7a0cf9369f39abcd8ef75e6edfb6c2b2b241a Mon Sep 17 00:00:00 2001 From: Olivier Mehani Date: Tue, 9 Feb 2016 10:04:48 +0000 Subject: [PATCH] Enable SSL on standard and well-known HTTP headers Look for the `Forwarded` header with `proto=https`, as specified in RFC7239 (strictly expecting no whitespace around the = sign). This also add similar support for `X-Forwarded-Proto: https`, `Front-End-Https: on` and `X-Forwarded-Ssl: on` (all case-sensitive). Also add some documentation about this, and an NginX configuration example, in INSTALL.txt This should fix #757. Signed-off-by: Olivier Mehani --- INSTALL.txt | 31 ++++++++++++++++++++++++++++++- boot.php | 11 ++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/INSTALL.txt b/INSTALL.txt index 7726bdb0d7..71671af3f1 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -136,8 +136,37 @@ $a->config['system']['addon'] = 'js_upload,poormancron'; and save your changes. +9. (Optional) Reverse-proxying and HTTPS + +Friendica looks for some well-known HTTP headers indicating a reverse-proxy +terminating an HTTPS connection. While the standard from RFC 7239 specifies +the use of the `Forwaded` header. + + Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2 + +Friendica also supports a number on non-standard headers in common use. + + + X-Forwarded-Proto: https + + Front-End-Https: on + + X-Forwarded-Ssl: on + +It is however preferable to use the standard approach if configuring a new server. +In Nginx, this can be done as follows (assuming Friendica runs on port 8080). + + location / { + if ( $scheme != https ) { # Force Redirect to HTTPS + return 302 https://$host$uri; + } + proxy_pass http://localhost:8080; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Forwarded "for=$proxy_add_x_forwarded_for; proto=$scheme"; + } - ##################################################################### If things don't work... diff --git a/boot.php b/boot.php index dd70040c64..6a2acaa35e 100644 --- a/boot.php +++ b/boot.php @@ -582,10 +582,15 @@ class App { $this->scheme = 'http'; - if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) - $this->scheme = 'https'; - elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) + if((x($_SERVER,'HTTPS') && $_SERVER['HTTPS']) || + (x($_SERVER['HTTP_FORWARDED']) && preg_match("/proto=https/", $_SERVER['HTTP_FORWARDED'])) || + (x($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') || + (x($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') || + (x($_SERVER['FRONT_END_HTTPS']) && $_SERVER['FRONT_END_HTTPS'] == 'on') || + (x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443)) // XXX: reasonable assumption, but isn't this hardcoding too much? + ) { $this->scheme = 'https'; + } if(x($_SERVER,'SERVER_NAME')) { $this->hostname = $_SERVER['SERVER_NAME'];