If I have a reverse proxy setup like: ProxyPassReverse /foo/ http://mononoke/bar/ Then if the mononoke server returns a cookie with path /bar, then it will be passed back to the client as /bar. On the next request to /foo, the cookie will not be sent by the client, and state tracking through cookies will fail. mod_proxy should convert the cookie path from /bar to /foo, just as it changes Location and other headers.
Created attachment 3373 [details] Against 1.3.26, uses ProxyReversePass setting to rewrite cookies
Created attachment 3456 [details] Patch against 1.3.27 not great but actually works (touch wood)
Cookie path variables do not necessarily have anything to do with the current URL, which is why modifying them along with Location is not necessarily what the administrator might want. (example: the admin might specify path '/' meaning "be sitewide", and proxy might change "/" to "/bar" in the case of ProxyPassReverse /bar http://backend/ where the admin did not want this to happen) A separate configuration parameter is needed for cookies to be modified correctly.
One might want to modify both the domain and the path, so you'd need two directives, right? For instance: ProxyPassReverseCookieDomain foo.com bar.com ProxyPassReverseCookiePath /mailprog / I'm assuming it's original->new, like most apache directives. You'd want to be able to set this on a per-url basis, perhaps in a <Directory proxy:foo> block? This seems pretty essential for flexible proxy/load balancer setup, so if I missed an obvious better implementation, please comment.
ProxyPassReverseCookieDomain and ProxyPassReverseCookiePath seem the right thing to do. I tend to want to limit the creation of new directives if at all possible, but here we specifically need to specify behavior for cookie domains and path. Now all we need is a patch :)
I've just tried porting this for Apache 2. It ports just fine, but it's not adequate: it leaves "domain=foo" strings in a cookie untouched. Is anyone actually using this?
I've created a patch for this against 2.0.49 - testing encouraged. I'll port this (with any bugfixes that turn out necessary) to HEAD in the next few days - someone bug me if I don't:-)
Created attachment 11886 [details] Patch against httpd-2.0.49
Nick, does your patch address Graham's issues?
Bill, yes, it implements ProxyPassReverseCookieDomain and ProxyPassReverseCookiePath Implementation is in line with the ProxyPassReverse stuff, though I was strongly tempted to use a regexp instead (and implement regexps in ProxyPassReverse too).
OK, scrub my patch. It's fine for one cookie, but fails for two or more. Update to follow.
Created attachment 11915 [details] Corrected (deals with multiple cookies) patch against 2.0.49
Created attachment 11916 [details] Documentation patch (URLMapping guide)
Created attachment 11917 [details] Documentation patch (mod_proxy)
Patch available for 2.0.49; fix now committed to HEAD
(In reply to comment #15) > Patch available for 2.0.49; fix now committed to HEAD Why is this still not in, even not in 2.0.53 if it was committed to HEAD?
Created attachment 15543 [details] 2.0.53, mult cookie plus location aware patch to check request uri against location ProxyPassReverseCookiePath/Domain is configured in. This works for me with 2 different java servlet application servers behind the proxy each setting jsessionid with path=/
(In reply to comment #17) > Created an attachment (id=15543) [edit] > 2.0.53, mult cookie plus location aware > > patch to check request uri against location ProxyPassReverseCookiePath/Domain > is configured in. This works for me with 2 different java servlet application > servers behind the proxy each setting jsessionid with path=/ My production server is running Fedora Core 2 with the latest available Apache available, httpd-2.0.51-2.9.i386.rpm. Is there a way I can get a patch for this version or a patched mod_proxy module to drop in as a replacement for the one from the rpm? I've tested your patch on a test FC4 system with 2.0.53 and was able to get perfect results; the persistent login cookie was sent and allowed me to "hide" the dynamic pages from the backend server and virtualize them on my public server. Thanks, Tony
As far as I can tell, this made it to the trunk for Apache 2.1 but not to the 2.0 branch. http://svn.apache.org/viewcvs.cgi/httpd/httpd/trunk/modules/proxy/mod_proxy.c? rev=151248&view=markup http://svn.apache.org/viewcvs.cgi/httpd/httpd/branches/2.0.x/modules/proxy/mod_proxy.c? rev=151405&view=markup It went in here: http://svn.apache.org/viewcvs.cgi?rev=104070&view=rev
I've just posted to dev@httpd.apache.org in support of backporting a fix for this so it actually makes it into future 2.0 releases. So there's an active thread now if anyone wants to discuss it.
Comment on attachment 3373 [details] Against 1.3.26, uses ProxyReversePass setting to rewrite cookies *** proxy_http.c Tue Jun 18 01:59:59 2002 --- proxy_http.c_clean_new Mon Oct 7 12:33:03 2002 *************** *** 137,142 **** --- 137,198 ---- return url; } + /* Take a cooke value and rewrite the path as required by ProxyPassReverse setting. + * Written for tomcat apps that add cookie path by default. NOT heavily tested. + */ + + static const char *proxy_cookie_reverse_map(request_rec *r, const char *cookie_val) + { + proxy_server_conf *conf; + struct proxy_alias *ent; + int i, l1, l2, l3, lreal, lrest; + char *u; + char *real_path; + char *ctmp1,*ctmp2,*ctmp3,*fixed = NULL; + + conf = (proxy_server_conf *)ap_get_module_config(r->server->module_config, &proxy_module); + l1 = strlen(cookie_val); + ent = (struct proxy_alias *)conf->raliases->elts; + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "ProxyPassReverse Original cookie = %s", cookie_val); + for (i = 0; i < conf->raliases->nelts; i++) { + /* Find just the proxy reverse paths for cookie remapping */ + ctmp1 = strstr(ent[i].real, "//"); + /* go passed //, could do this above but simpler here */ + ctmp1 = ctmp1 + 2; + /* find / which should be start of path. We have only a very + * simple url to parse */ + real_path = strstr(ctmp1, "/"); + /* real_path now has real path so swap real in for fake */ + if( ctmp1 = strstr(cookie_val, "path=") ){ + ctmp2 = strstr(ctmp1, ent[i].fake); + if ( !ctmp2 ) continue; + /* go passed path= */ + ctmp1 += 5; + /* go passed fake entry (bit we are rewriting)*/ + ctmp2 += strlen(ent[i].fake); + /* + * ctmp1 is just passed path= and ctmp2 at end of fake bit, + * now add bits together + * l3 = bit up to end "path=" + lenght real + bit at end fake + \0 + */ + lreal = strlen(real_path); + lrest = strlen(ctmp2); + l3 = ((int) (ctmp1 - cookie_val)) + lreal + lrest + 1; + fixed = ap_palloc(r->pool, l3); + strncpy(fixed, cookie_val, (int) (ctmp1 - cookie_val)); + strncpy(&fixed[(int) (ctmp1 - cookie_val)], ctmp1, lreal); + strncpy(&fixed[(int) (ctmp1 - cookie_val + lreal)], ctmp2, lrest); + /* strncpy(&fixed[(int) (ctmp1 - a + lreal + lrest)], '\0', 1); */ + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "ProxyPassReverse Fixed cookie = %s", fixed); + } + } + if( fixed ) return fixed; + return cookie_val; + } + + /* * This handles http:// URLs, and other URLs using a remote proxy over http * If proxyhost is NULL, then contact the server directly, otherwise *************** *** 153,161 **** char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; ! table *req_hdrs, *resp_hdrs; ! array_header *reqhdrs_arr; ! table_entry *reqhdrs_elts; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; --- 209,217 ---- char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; ! table *req_hdrs, *resp_hdrs, *cookie_temp; ! array_header *reqhdrs_arr, *resphdrs_arr; ! table_entry *reqhdrs_elts, *resphdrs_elts; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; *************** *** 555,560 **** --- 611,638 ---- if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr)); + cookie_temp = ap_make_table( r->pool, 2); + resphdrs_arr = ap_table_elts(resp_hdrs); + resphdrs_elts = (table_entry *)resphdrs_arr->elts; + for (i = 0; i < resphdrs_arr->nelts; i++) { + if ( strcmp(resphdrs_elts[i].key, "Set-Cookie") == 0 ){ + ap_table_add( cookie_temp, "Set-Cookie", proxy_cookie_reverse_map(r, resphdrs_elts[i].val) ); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Added cookie Set-Cookie to cookie_temp = %s", proxy_cookie_reverse_map(r, resphdrs_elts[i].val) ); + } + } + + if( ! ap_is_empty_table( cookie_temp ) ){ + ap_table_unset(resp_hdrs, "Set-Cookie"); + resphdrs_arr = ap_table_elts(cookie_temp); + resphdrs_elts = (table_entry *)resphdrs_arr->elts; + for (i = 0; i < resphdrs_arr->nelts; i++) { + ap_table_add(resp_hdrs, "Set-Cookie", resphdrs_elts[i].val); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Added cookie Set-Cookie to resp_hdrs = %s", resphdrs_elts[i].val); + } + } + /* check if NoCache directive on this host */ if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) {
*** proxy_http.c Tue Jun 18 01:59:59 2002 --- proxy_http.c_clean_new Mon Oct 7 12:33:03 2002 *************** *** 137,142 **** --- 137,198 ---- return url; } + /* Take a cooke value and rewrite the path as required by ProxyPassReverse setting. + * Written for tomcat apps that add cookie path by default. NOT heavily tested. + */ + + static const char *proxy_cookie_reverse_map(request_rec *r, const char *cookie_val) + { + proxy_server_conf *conf; + struct proxy_alias *ent; + int i, l1, l2, l3, lreal, lrest; + char *u; + char *real_path; + char *ctmp1,*ctmp2,*ctmp3,*fixed = NULL; + + conf = (proxy_server_conf *)ap_get_module_config(r->server->module_config, &proxy_module); + l1 = strlen(cookie_val); + ent = (struct proxy_alias *)conf->raliases->elts; + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "ProxyPassReverse Original cookie = %s", cookie_val); + for (i = 0; i < conf->raliases->nelts; i++) { + /* Find just the proxy reverse paths for cookie remapping */ + ctmp1 = strstr(ent[i].real, "//"); + /* go passed //, could do this above but simpler here */ + ctmp1 = ctmp1 + 2; + /* find / which should be start of path. We have only a very + * simple url to parse */ + real_path = strstr(ctmp1, "/"); + /* real_path now has real path so swap real in for fake */ + if( ctmp1 = strstr(cookie_val, "path=") ){ + ctmp2 = strstr(ctmp1, ent[i].fake); + if ( !ctmp2 ) continue; + /* go passed path= */ + ctmp1 += 5; + /* go passed fake entry (bit we are rewriting)*/ + ctmp2 += strlen(ent[i].fake); + /* + * ctmp1 is just passed path= and ctmp2 at end of fake bit, + * now add bits together + * l3 = bit up to end "path=" + lenght real + bit at end fake + \0 + */ + lreal = strlen(real_path); + lrest = strlen(ctmp2); + l3 = ((int) (ctmp1 - cookie_val)) + lreal + lrest + 1; + fixed = ap_palloc(r->pool, l3); + strncpy(fixed, cookie_val, (int) (ctmp1 - cookie_val)); + strncpy(&fixed[(int) (ctmp1 - cookie_val)], ctmp1, lreal); + strncpy(&fixed[(int) (ctmp1 - cookie_val + lreal)], ctmp2, lrest); + /* strncpy(&fixed[(int) (ctmp1 - a + lreal + lrest)], '\0', 1); */ + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "ProxyPassReverse Fixed cookie = %s", fixed); + } + } + if( fixed ) return fixed; + return cookie_val; + } + + /* * This handles http:// URLs, and other URLs using a remote proxy over http * If proxyhost is NULL, then contact the server directly, otherwise *************** *** 153,161 **** char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; ! table *req_hdrs, *resp_hdrs; ! array_header *reqhdrs_arr; ! table_entry *reqhdrs_elts; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; --- 209,217 ---- char *strp2; const char *err, *desthost; int i, j, sock,/* len,*/ backasswards; ! table *req_hdrs, *resp_hdrs, *cookie_temp; ! array_header *reqhdrs_arr, *resphdrs_arr; ! table_entry *reqhdrs_elts, *resphdrs_elts; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; *************** *** 555,560 **** --- 611,638 ---- if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL) ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map (r, urlstr)); + cookie_temp = ap_make_table( r->pool, 2); + resphdrs_arr = ap_table_elts(resp_hdrs); + resphdrs_elts = (table_entry *)resphdrs_arr->elts; + for (i = 0; i < resphdrs_arr->nelts; i++) { + if ( strcmp(resphdrs_elts[i].key, "Set-Cookie") == 0 ){ + ap_table_add( cookie_temp, "Set-Cookie", proxy_cookie_reverse_map(r, resphdrs_elts[i].val) ); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Added cookie Set-Cookie to cookie_temp = %s", proxy_cookie_reverse_map(r, resphdrs_elts[i].val) ); + } + } + + if( ! ap_is_empty_table( cookie_temp ) ){ + ap_table_unset(resp_hdrs, "Set-Cookie"); + resphdrs_arr = ap_table_elts(cookie_temp); + resphdrs_elts = (table_entry *)resphdrs_arr->elts; + for (i = 0; i < resphdrs_arr->nelts; i++) { + ap_table_add(resp_hdrs, "Set-Cookie", resphdrs_elts[i].val); + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, + "Added cookie Set-Cookie to resp_hdrs = %s", resphdrs_elts [i].val); + } + } + /* check if NoCache directive on this host */ if (nocache == 0) { for (i = 0; i < conf->nocaches->nelts; i++) {
Created attachment 17430 [details] Updated patch for "2.0.53, mult cookie plus location aware" to 2.0.55 Updated the patch for 2.0.53 so that it applies to 2.0.55, wasnt sure how to produce a patch file so have attached the updated mod_proxy.c mod_proxy.h and proxy_http.c files for mod_proxy 2.0.55. Would be great if this could make it back into the source tree, im sure other users out there need this as well as me...
Created attachment 17438 [details] diff -ur patch for Adam's 2.0.55 update This is just a diff -ur format patch for Adam's update work. This should make it fit the Apache process better and hopefully increase odds of landing. This is still Adam's work, not mine, all I did was run diff.
The 2.0.55 Adam's patch doesn't work Right. I really haven't studied the case. But one of my customers complained about some header variables not propagated to the real server. I know it was with a very large HTTP Header variable. I have made the test by myself today and I could see cleanly that it failed just by being compiled. I tried an unpatched Apache an it worked pretty fine. I think I can make more tests but not today.. This comments is to say to you: don't put that patch in a production environment. ;) Thx
(In reply to comment #25) > The 2.0.55 Adam's patch doesn't work Right. 2.0.55 has new proxy problems (see bug 37145). Upgrade to 2.2 if you want this functionality. Other 2.0 variants (eg 2.0.54) are an option if you want the proxy but don't care about proxied cookies. There's also a patch for 2.0-trunk at http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch
Please, forget my previous message (http://issues.apache.org/bugzilla/show_bug.cgi?id=10722#c25). As I have read the #c26, I realize that I didn't include the #37145 patch at the same time that this patch. So, finally, it was failing because the lack of #37145. As I restored a previous package with it enable, I got it working again. This patch could work perfectly, but I didn't tested it well. No conclusion for me yet.
*** Bug 40492 has been marked as a duplicate of this bug. ***
Is anyone updating patches for the new 2.0 releases for this? I have a case where I need to utilize the ProxyPassReverseCookieDomain and ProxyPassReverseCookiePath in the latest 2.0 tree.
Closing, as this has been fixed in the stable 2.2.x branch. A updated patch for the 2.0.x branch can be found at http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch Also, the 2.0.x patch is up for vote and should be committed soon (missing just one vote).
Is there a patch available for v2.0.61 or v2.0.63? Moving to httpd v2.2.x unfortunately is no option in the environment where I need the patch. Could you help please? http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch only works up to v2.0.59
Do not reopen to request backports. This is an issues tracking database for the code development, not a user support forum