1

I run a web server with multiple users. The machine provides Apache-based virtual hosts to a bunch of users, who can serve static content or use PHP. No other forms of server-side scripting are available.

Here's how a typical request is handled:

Flow chart of request handling

HTTPS traffic has its SSL stripped by Pound, which acts as a reverse proxy and forwards the request on to Varnish, which also acts as a reverse proxy, finally forwarding the request on to Apache.

By the time the HTTPS traffic reaches Apache, the protocol, port, and full URL have changed from, say, https://example.com:443/ to http://example.com:8443/. This is a result of all the proxies before Apache.

Is there a way I can trick the PHP scripts into thinking the request came from the original URL, port, and protocol, without modifying the PHP code?

This is important because the users will wish to run Joomla, WordPress, and other PHP-based CMSes which detect the URL and cause trouble with redirects, links, etc.

I could probably patch mod_php and build it from source with the necessary changes for my specific scenario, but is there a better way to give the PHP scripts fake environmental variables, perhaps via some setting in php.ini?

Tom Marthenal
  • 2,116
  • 7
  • 25
  • 37
  • Is this really a big problem? If the PHP-Based CMS is configured to return relative urls you should not have a problem. Alternatively you can just set the site url in the CMS config. – Krist van Besien Apr 02 '13 at 10:07
  • @KristvanBesien yes, unfortunately. Not all CMSes return relative URLs all the time (also note that, for example, the Location HTTP header is only supposed to return absolute URLs per the RFC). Additionally, not all support a "site URL" or support it completely (e.g. Joomla). – Tom Marthenal Apr 02 '13 at 19:32

1 Answers1

0

The easiest way I can find to do this is by dropping mod_php and using a CGI script instead. This allows you to call php-cgi (a CGI-targeted version of the PHP interpreter) from a shell script which is executed on page load.

Here is an example bash script which sets the SERVER_PORT and HTTPS environment variables based on the X-Forwarded-Proto header, and then calls php-cgi:

#!/bin/bash
# HTTPS fix (WARNING: THIS HEADER CAN BE FAKED BY THE CLIENT)
if [[ "$HTTP_X_FORWARDED_PROTO" == "https" ]]; then
        export SERVER_PORT=443
        export HTTPS="on"
else
        export SERVER_PORT=80
fi

php-cgi

Of course, you must be careful because the X-Forwarded-Proto header can be sent by the client, so unless you have something sitting between Apache and the client sanitizing that header, you should not trust it! (you probably also want to firewall off Apache, or better yet, have it only listen on loopback)

All you need to do is have Apache use this bash script for every file with a .php extension (mod_cgi and mod_actions let you do this).

Tom Marthenal
  • 2,116
  • 7
  • 25
  • 37
  • It's worth noting that performance is absolutely abysmal here. It would probably be a lot better to write the script using a faster shell, or even as a small C program. It probably also makes sense to look into PHP's FastCGI features. – Tom Marthenal Apr 02 '13 at 07:23