Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add reverse proxy support #1035

Closed

Conversation

herbrechtsmeier
Copy link
Contributor

Add support for a reverse proxy that handles multiple domains via host name
as prefix in the request URI (https://ssl-proxy.tld/domain.tld/).

As the reverse proxy is transparent for the web server the REQUEST_URI and
SCRIPT_NAME need manual adjustments. This patch replace the direct use
of this _SERVER variables with function calls and extend this functions
to detect the proxy and to add the needed prefix. Additionally it adds
a Sabre request backend with extends the Sabre_HTTP_Request to use the
same functions.

Add support for a reverse proxy that handles multiple domains via host name
as prefix in the request URI (https://ssl-proxy.tld/domain.tld/).

As the reverse proxy is transparent for the web server the REQUEST_URI and
SCRIPT_NAME need manual adjustments. This patch replace the direct use
of this _SERVER variables with function calls and extend this functions
to detect the proxy and to add the needed prefix. Additionally it adds
a Sabre request backend with extends the Sabre_HTTP_Request to use the
same functions.
@karlitschek
Copy link
Contributor

Thanks a lot.
A few questions.
Why do you need the reverseproxyhost and reverseproxyprefixssl? Shouldn't it be possible to use the overwritehost and overwriteprotocol ?
Yould you add a examples values to the config variables to show how they should be used?
I'm still not sure about the reverseproxyprefix.

If owncloud is installed on the webserver on foobar.org/owncloudinstallation and the reverse proxy translates this to foobar.org/owncloud. How would you set that? And how would you set that if it's the other way around?
Why not have an overwritewebroot variable?

@herbrechtsmeier
Copy link
Contributor Author

The reverseproxyhost is needed to detect when owncloud is used via reverse proxy (a). It is also possible to use owncloud direct (b) without reverse proxy. In my case the reverse proxy is only used for the https connection, but in both cases onwcloud itself is served via http. The reverseproxyprefix[ssl] is used by the reverse proxy to distinguish between the different host it has to managed. It is possible to use only one prefix if we can assume that they are always the same. The overwrite variables are always overwrite the host and protocol.

Example: Owncloud is installed on a domain.tld without SSL certificate. The web hosting provider has one reverse proxy ssl-proxy.tld with a SSL certificate in the computing centre which allows https connection via the URL https://ssl-proxy.tld/domain.tld/. In both cases the connection to the web server is via http but with the reverse proxy the data are encrypted outside of the computing centre. In order to support both connections owncloud has to use the default behaviour for the direct http connection and it has to use the ssl-proxy.tld host and domain.tld web root prefix for the https connection. The detection of the host and protocol works via HTTP_X_FORWARDED variables. Only the prefix must be set manually and therefor owncloud has to detect the reverse proxy via IP or hostname. The current patch use the later solution.
reverseproxyhost => 'ssl-proxy.tld'
reverseproxyprefix => '/domain.tld'

As your example shows the overwritewebroot variable has an total different use case and the question is if there is really such a setup. For my use case the variable is not enough because it only works via reverse proxy and totally fail if you visit the side without reverse proxy.

@karlitschek
Copy link
Contributor

Well. There are a lot of systems where the webroot is different before and behind the proxy. This is common on HA and load balancer setups.

I'm not sure why you think that ownCloud should support ssl and no ssl connections at the same time. In the scenario where you use a reverse proxy every request should go through the reverse proxy. My does it make sense to access ownCloud sometimes without ssl and the reverse proxy and sometimes with the ssl and the proxy?

/* Host name of a (intransparent) reverse proxies */
"reverseproxyhost" => "",

/* Optinal prefix for the SCRIPT_NAME and REQUEST_URI of a (intransparent) reverse proxy*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optinal -> Optional

@herbrechtsmeier
Copy link
Contributor Author

I'm not familiar with HA or load balancer and don't know their setup.

I keep both connections functional because I don't want to introduce a limitation and I don't know all use cases. Also other projects use a similar solution.

If you prefer a minimal solution I can try the overwritewebroot solution. But this means that it will only work if I enable forcessl but don't set overwriteprotocol as I need it to redirect direct http requests to the reverse proxy. This makes the configuration more error-prone and maybe leads to additional bug reports as it is not obvious that you need to force SSL.

Example:
forcessl => true
overwritehost => 'ssl-proxy.tld'
overwriteprotocol => ''
overwritewebroot => '/domain.tld/owncloud'

Maybe I make sense to check the host name or IP address in the checkSSL function to make sure that owncloud is used via the reverse proxy in the computing centre. The IP address should be the securest solution but maybe requires to support a IP list or a regular expression.

It's up to you what you prefer. I'm not an expert in this field and happy when onwcloud supports my reverse proxy without manual code changes.

@herbrechtsmeier
Copy link
Contributor Author

I have open an additional pull request #1037 with a minimal solution and a real overwritewebroot as described in the last example.

@karlitschek
Copy link
Contributor

👍
But not sure what you mean with forcessl. Shouldn't it be enough to set "overwriteprotocol" to "https" to make it work with reverse proxys?

@herbrechtsmeier
Copy link
Contributor Author

I mean that I have to set the configuration variable forcessl to true. The overwriteprotocol is not needed as the automatic detection works. But I need to redirect the user to the reverse proxy if he use owncloud direct without reverse proxy. Otherwise it sees a ugly page because all paths are wrong. Instead of the forcessl variable I can use a rewrite rule and a RewriteCond for the REMOTE_ADDR not equal the reverse proxy IP address in the htaccess file.

@karlitschek
Copy link
Contributor

I still have problems to understand you usecase ;-)
Is't the whole point of this feature that the automatic detection of the protocol does not work?
So you can manually overwrite the protocol with the config variable?

Sorry. I'm confused.

@herbrechtsmeier
Copy link
Contributor Author

My web space is available direct via http://domain.tld and over a reverse proxy via https://ssl-proxy.tld/domain.tld/. In both cases the website is served via http and only the connection to the reverse proxy is encrypted . The reverse proxy host name and protocol is detectable via $SERVER variable HTTP_X_FORWARDED* but the prefix of the web root (/domain.tld) must be added manual when the website is visit via reverse proxy (https). Therefore we need a conditional manipulation of the web root (Done by this pull request). Instead of supporting both connections we can always manipulate the web root and force the reverse proxy usage but therefore we have to redirect http://domain.tld to https://ssl-proxy.tld/domain.tld/ (Done by the other pull request).

I only want to mention that the later solution is more error-prone as it always overwrite the web root and that it need to redirect all direct access (without reverse proxy) to the reverse proxy. If somebody accidentally set overwriteprotocol the redirect no longer works and the browser shows a website with wrong paths. The same is true if the user don't set overwritehost or don't set forcessl to true. In all cases the usage via reverse proxy works. On the other side maybe the redirect via htaccess file is the best way to go.

Anyway #1037 works but because of the more complex overwrite of the web root somebody with more expert knowledge than me should review the requestUri and scriptName function.

@kill-joy
Copy link

What about the solution from http://forum.owncloud.org/viewtopic.php?f=3&t=3841

@herbrechtsmeier
Copy link
Contributor Author

@kill-joy The solution from the forum change 3rd party software which you should not do. My solution extends the Sabre_HTTP_Request class instead as suggested by the sabre maintainers (http://code.google.com/p/sabredav/issues/detail?id=61). Additional the solution from the forum change the default behaviour as it assume that a reverse proxy change the web root and this is not always true. My solution makes the web root instead configurable via configuration variable. In the end it change the REQUEST_URI with the web root with is also wrong as it removes the path and query string from the request. My solution therefore replace all direct usage of REQUEST_URI and SCRIPT_NAME with functions which returns the adjusted value. Only the manipulation of the .htacess file with the rewrite rule is the same for both solutions.

@karlitschek
Copy link
Contributor

O.K. Let's merge it. 👍
I'm still not sure if it's a common usecase that ownCloud is available under two different urls.
But this is definitely better than before :-)
Thanks a lot for your work

@herbrechtsmeier
Copy link
Contributor Author

@karlitschek Which version you want to merge? I have to update my patch because I miss some replacement of REQUEST_URI.

@herbrechtsmeier
Copy link
Contributor Author

@karlitschek If you like I can also add the reverse proxy detection to the overwritewebroot solution (#1037) via a overwrite condition host name or overwrite condition IP address as regular expression.

@karlitschek
Copy link
Contributor

O.K. let's do it like that. The overwritewebroot solution with an condition as you suggested

@herbrechtsmeier
Copy link
Contributor Author

I have open a new pull request #1099 that really overwrite the web root and continual overwrite the host name, protocol and web root if a regular expression for the remote ip address match.

@lock lock bot locked as resolved and limited conversation to collaborators Aug 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants