Symfony in nginx https + varnish + apache http = redirect loop or - symfony

I have configuration
Symfony in nginx https + varnish + apache http = redirect loop
i put schemes for routing to get links https : ['https']
but get redirect loop why ?
it look that symfony not just create links with https but return redirect if get http - i need http pages for cache in varnish but links https.
Update 1
When i put no schema in routing and run page over https almost everything work - without
1 fos routing it create absolute http links
2 liip imagine same situation

If you are getting a redirect to https despite using https when visiting the page, then the original protocol is not being forwarded to the backend that handles the response.
There is a header X-Forwarded-Proto which should be set to contain the original protocol before it was passed through any proxies. Symfony should respect this header and accept that the request is secure and not redirect (and also set all links to https:// urls if appropriate)
You need to configure Apache (which I assume is terminating the https connection and has the certificates) to set this header to match the original request protocol.
It looks like you might need to trust the proxies before Symfony will obey the headers Symfony Docs for proxies
// public/index.php
// ...
$request = Request::createFromGlobals();
// tell Symfony about your reverse proxy
Request::setTrustedProxies(
// the IP address (or range) of your proxy
['192.0.0.1', '10.0.0.0/8'],
// trust *all* "X-Forwarded-*" headers
Request::HEADER_X_FORWARDED_ALL
);

Related

How can I redirect HTTPS to HTTP with uWSGI internal routing?

For some reasons, I need to force HTTP for my whole site.
At first, I thought that i could simply interchange key-parameters such as those shown in
uwsgi-docs.readthedocs.io#Force HTTPS
How can I redirect HTTP to HTTPS with uWSGI internal routing?
leading me to do:
plugins = router_redirect
route-if-not = equal:${HTTP};on redirect-permanent:http://${HTTP_HOST}${REQUEST_URI}
which does not work. Hence the following question: How can I redirect HTTPS to HTTP with uWSGI internal routing?
Note that the (commonly wanted) redirection from HTTP to HTTPS perfectly works within my environment, i.e., doing
plugins = router_redirect
route-if-not = equal:${HTTPS};on redirect-permanent:https://${HTTP_HOST}${REQUEST_URI}
works.
I'm guessing that you'd want this:
plugins = router_redirect
route-if = equal:${HTTPS};on redirect-permanent:http://${HTTP_HOST}${REQUEST_URI}
(...although some browsers may then change the URL back to https.)

Determine current page url when using off box SSL termination

How can you determine the current request URL if using off box SSL termination?
E.g.
Browser has url httpS://yourserver/
SSL Termination decrypts and sends onto http://yourserver
IIS/ASP.NET receives request at http://yourserver
At (3) if you use Context.Request.Url, Page.Request.Url or Page.Request.RawUrl it show a url with a http protocol and not httpS
How do get the public httpS URL that was origionally used at (1) in this case?
The convention used for Microsoft Products is to add a header at the reverse proxy.
Front-End-Https : On
So you know the http url is really https.
You could also add in your own header containing the original URL if you did something like URL translation (e.g. something like "Original-Uri").
This page shows how to do this using IIS AAR as the reverse proxy, though in my testing I could only get headers to pass through if they are prefixed with HTTP_ (which is later stripped out).

How to Reproduce sendRedirect issue - HTTPS change to HTTP

I am using response.sendRedirect() to redirect the user to Home page, once the user gets authenticated successfully. This is to avoid the "Login redirect vulnerability".
However, because of above change, One of my customer is facing issue where his HTTPS request are getting converted to HTTP (with ip address in the URL). The reason for the same is explained here
http://geekexplains.blogspot.in/2008/06/https-becoming-http-in-case-of.html
Now, How can i reproduce the issue (or setup the environment) so that I can verify my fix. I thought I could reproduce by setting up Apache server infront of tomcat but I am not able to reproduce above mentioned issue.
In Apache httpd.conf i have below entries
ProxyPass /myconsole ajp://localhost:8009/myconsole
ProxyPassReverse /myconsole ajp://localhost:8009/myconsole
Accessed the application like,
http://myapacheserver/myconsole/Login.jsp
After the successful login, I am getting redirected to
http://myapacheserver/myconsole/Home.jsp
I am expecting to redirect to the IP address. something like http://10.32.24.14:8080/myconsole/Home.jsp.
In the customer environment he is getting redirected to the ip address of App server (tomcat).
Any pointer would be helpful.
Thanks
Note:
For those interested, I am building the full URL by getting the first part of URI from the configuration file.
//Get the LB URI part. Eg: https://dev.loadbalancer.com/
String loadBalancerURI = getConfig().getLoadBalancerRequestURI();
String redirectURL = request.getContextPath() + "/Home.jsp";
//Prepend the LoadBalancer URI with redirect URI
if(loadBalancerURI != null)
{
redirectURL = loadBalancerURI + "/" + redirectURL;
}
//redirect to home page
response.sendRedirect(redirectURL);
return;
Edit: More info on the setup. The customer has F5 load balancer where the SSL traffic stops and then there is a Apache Reverse Proxy servers which proxy to pool of tomcat servers. The issue is when we do redirect the redirect URL is for Tomcat Servers. What we are expecting is to have the load balancer URL in the redirect URL.
Is it possible to do some change in the Apache server which will rewrite the URL in the HTTP header in the response send by Tomcat?
I'm not sure if you're really using a load balancer or if you just called one of your methods getLoadBalancerRequestURI, but where you only have one server, just use :
response.sendRedirect("./Home.jsp");
Its not necessary to specify the full url.
But if you do need to build the full url as you are doing, you can use something like this to check if its https://
String protocol = "https";
if( request.getRequestURL().toString().toLowerCase().startsWith("http://" ) )
{
protocol = "http";
}
Then make sure to build the url with the proper protocol.
See this link ..
So when an https request redirect happens, the target server has no clue what's the original request's protocol. It only receives an http request. Thus, the response for that would be an http response.
http://www.hoitikwong.com/2013/03/the-mystery-case-of-https-becoming-http.html
I was able to reproduce the issue (when HTTP-HTTPS redirect) which my customer was facing.
The communication from Apache (HTTPD server) to Tomcat (Web container) generally happens by using one of the following connectors (may be some other way as well).
mod_jk
mod_proxy_ajp
mod_proxy_http
mod_rewrite
I am able to reproduce the issue only when i use the mod_rewrite. If i use either mod_jk or mod_proxy_ajp or mod_proxy_http approach then the redirect works fine. But when i use mod_rewrite then when the redirect happens I am able to observe the HTTPS-HTTP conversion.

Caching with Varnish & Varying over custom-set HTTP headers

I'm developing your standard high traffic ecommerce website and want to setup caching with Varnish. The particular thing on this setup is that the application will return different content depending on the user's particular location.
So my plans are these:
Setup Nginx with GeoIP module, so I can get a X-Country: XX header on all the requests going to the app backends.
Configure the Rails application to always return a "Vary: X-Country" response header.
Put the Varnish server behind the Nginx and the app backends, so it can cache multiple versions of the objects served by Rails, and serve them based on the request headers set by Nginx (not the client browser)
Does anyone have experience with a setup like this? Anything I should be aware of?
If GeoIP lookup is slow, and/or you want to enable people to override the country setting, you could use a country cookie and have the front-end Varnish check for it.
If there is no country cookie, forward the request to your nginx back-end for GeoIP lookup. Nginx serves a redirect with a Set-Cookie: country=us header. If you want to avoid redirects and support cookie-refusing clients/robots, ngingx can forward it to Rails and still try to set the country cookie in the response. Or Varnish can capture the redirect response and do a "restart" with the newly set cookie and go to the back-end
If you have already have a country cookie, use this in your Varnish hash
If Rails can do GeoIP resolving, you don't need Ngingx, except when you use it to serve files...

How to make nginx(proxy) cache the actual content instead of just the headers when a http 302/301 response is received by the proxy_pass server?

I'm trying to use nginx as a temporary http cache in order to minimize requests to content. My content is on multiple servers so I can't use a static proxy_pass parameter to the direct location but instead of that I use a rewrite to a php script:
rewrite /([^/]+\.jpg) /index.php?file=$1 break;
proxy_pass http://www.phpserver.com;
The php script(that would be http://www.phpserver.com/index.php) then returns a redirect with http code 301 to the actual file location(like http://www.contentserver1.com/filepath/file.jpg).
The problem is that nginx returns the redirect headers instead of retrieving,caching and returning the actual content.
So how do I make it to get the content from the actual server instead of just caching the headers?
Nginx can work only as proxy. It doesn't know anything about logic of you application (site), it's just proxies requests, and can put to cache responses.
For make this schema work, you must remove rewrite section from nginx, and move this logic to phpserver.com. phpserver must download this file and output it to nginx. Even if it very hard operation, nginx would cache this response and when next request will be received, nginx will give response direct from his cache.

Resources