Page MenuHomePhabricator

Reverse Proxy - cookie issue
Closed, WontfixPublic

Assigned To
Authored By
craig
Mar 24 2015, 1:30 PM
Referenced Files
None
Tokens
"Like" token, awarded by tvl."Doubloon" token, awarded by craig.

Description

version: d0b3f199bb711d11c97557fa18caf7da15bc302a

When configuring phabricator behind a reverse Proxy with a different URL to the host, I get CSRF error on every post.

External url: phab.domain.com
internal url phabricator.int.domain.com

Set "phab.domain.com" to base-uri. but I don't get any session cookies.

Looking through AphrontRequest.php::getCookieDomainURI() It can never set cookie to match the base-uri, only ever the host.

(if base-uri not set then use host) else go through allowed-uri until you find the host and set that otherwise set null

so base-uri never used in cookie domain so reverse proxy (unless it is same domain or a subdomain of the host) doens't work.

Event Timeline

craig raised the priority of this task from to Needs Triage.
craig updated the task description. (Show Details)
craig added a project: Roadmap.
craig added a subscriber: craig.
epriestley added a subscriber: epriestley.

Are you trying to serve Phabricator on two different URIs? For example, so non-VPN'd users connect to phab.domain.com and VPN'd user connect to phabricator.int.domain.com?

That is not necessary, the only domain I am interested in serving from is the external one. internal users can go external to access it.

As a temporary workaround I inserted
return new PhutilURI($base_uri);

around line 375 in AphrontRequest.php and it's working (although clearly not a fix)

I will restrict the internal apache server so it only receives requests from the reverse-proxy

You should simply replace all references to phabricator.int.domain.com with phabricator.domain.com, and forget that phabricator.int.domain.com exists.

The user will connect to Phabricator as phabricator.domain.com.

The reverse proxy will connect to the underlying server as phabricator.domain.com.

Phabricator will set cookies on phabricator.domain.com.

No part of the process needs to involve phabricator.int.domain.com.

the reverse proxy is on a different server. It responds to phabricator.domain.com so if it tries to proxy to that address it will respond itself in a loop and not get to the internal machine.

You should configure the reverse proxy to connect to the underlying host without mutating the "Host" header of the request (this should be the default behavior of most reverse proxies, so I'm surprised it isn't the configured behavior).

For example, suppose your proxy has IP 1.1.1.1 and your application server has IP 2.2.2.2. The flow of the request should be:

  • Client does a DNS lookup for phabricator.domain.com and gets "1.1.1.1".
  • Client connects to "1.1.1.1" and sends an HTTP request with "Host: phabricator.domain.com".
  • The reverse proxy receives the request.
  • The reverse proxy is configured to know that it forwards requests to "2.2.2.2".
  • The reverse proxy forwards the request to "2.2.2.2", with "Host: phabricator.domain.com" intact. It should not be changing the "Host" header to something else.
  • Phabricator receives a request which looks like it came to phabricator.domain.com, which is correct, even though the DNS record for that domain is not the machine ultimately serving the request. It happily sets cookies in the response and everything works.

yeah thats a load balancer style setup I'm just using apache mod_proxy and ProxyPass. (I have about 5 apps going through same proxy so far) I'll have a go at adjusting that behaviour.

ok I added the ProxyPreserveHost directive - reconfigured hosts and all is now good without the workaround.
I struggled to find any doco on this... I will write up some sample configs and explanations and pass back for tidy up and inclusion in your doc as you see fit for others following. Specifically since apache doc recommends against the use of the this directive, it would be good to document it for others.

epriestley claimed this task.

We haven't seen other interest in this kind of configuration, so we'd prefer not to maintain documentation about it. Feel free to publish a blog post or whatever, though. Glad to hear things are working now, let us know if you run into anything else.