Linux - ServerThis forum is for the discussion of Linux Software used in a server related context.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have a problem which might be a bug or it might be expected result i'm not sure and i've not been able to figure it out.
The set-up of web infrastructure is as follows.
websites1 -> Load balencer port 80 -> web server cluster port 80
websites2 -> Different load balencer port 80 -> Same Web server cluster port 81
So from this really basic example it should be obvious enough that we've split our web application/sites by port and that so things still work on the correct ports visibly we use multiple different load balancers so we still have 80 and 443 available to each app/site but it actually interacts with a different app/site underneith on the apache side of things as requests are directed to the correct apache port.
So problem is we have a redirect rule that basically says (in english) "ahh this request says .*/index.html redirect to /"
So that works as expected but when the request comes into apache on port 81 via load balancer websites2 we have un-expected results.. So imagine.. http://www.websites2.com -> Load Balencer (port 80) tcp redirects the request (nothing fancy happening at load balancer at all!) to port 81 on backend web cluster. OK apache answers it hits the re-write rule tries to send back as Location header of http://www.websites2.com:81.
Now :81 on the Location header.. big bad head ache... the port shouldn't be affected as we're using the loadbalencer that can answer port 80 requests not port 81.. why is apache adding port 81 into the redirect? Its not being told to do so etc.
If you use an external redirection rule (R) with a path only, something like
Code:
RewriteRule ^.*/index.html$ / [R]
Apache will prepend the host name and port, if you have UseCanonicalPhysicalPort yes or ServerName yourserver:81 and UseCanonicalName yes in your Apache config.
To avoid that, use a full URL, for example specifying the host name the client used for this request:
Great reply, many thanks. However Apache defaults suggest both UseCanonicalPhysicalPort and UseCanonicalName are Off, and thus Off from what I've read in the documentation is the correct position, that means that Apache should honour the client request Name and port number as such it should be normal. Because the client requests Host www.example.com and not www.example.com:81. Also in the ServerName configs of my VirtalHosts I dont have them set-up as www.example.com:81 anyway, they are set-up as normal ServerName www.example.com and its the Virtual Host directive where I have *:81
But that was a great answer, I was aware I can re-write the rule to include the host and it solves the problem but I really didn't want to have to go changing the mass of places where this situation occurs in our set-up.
Its a loss to me though why apache is honouring the Physical port rather than the client requested port, because the load balancer forwards the request onto 81 instead of 80 is that where its getting lost? I mean the load balancer certainly isn't adding :81 to the Host: header of the request so I dont know how Apache is deciding the port should be :81....
The apache Doc's say this "instead relying on all configured information to construct a valid port number." - but doesn't go on to say what "all configured information" is exactly, so how might I find out what Apache is really looking at here?
However Apache defaults suggest both UseCanonicalPhysicalPort and UseCanonicalName are Off, and thus Off from what I've read in the documentation is the correct position, that means that Apache should honour the client request Name and port number as such it should be normal.
I checked the Apache sources. For mod_alias, i.e. Redirect* directives, if the final URL starts with a slash, the server name will be prepended to it. If the port named in the request headers differs from the port configured for the virtual host, the configured port number will always be included. There is no configuration option to change that behaviour. If you are interested, look at core.c:ap_construct_url() function; it is called by mod_alias.c:translate_alias_redir().
Wow, That's cool. Not something I'd be able to do.
Doesn't that not slightly contradict the documentation when it comes to CanonicalPorts and Name? Where if set to Off then Apache won't use the physical ports, but the ones requested by the client, and the client is merely requesting http and then the load balancer probably NAT rewrites to forward the request to 81 but
Is this only going to happen for a final URL of / then? Why would it not keep to the same methods if final destination was /dir/file? As to me both methods should end up with the same redirect reply (sort of - certainly when talking of the hostname and port number thats replied with)
I looked at the 'Port' option - sounded like it might solve the problem, but shame its not in version 2.x
Also I wondered if things would work correctly if I forced in this case 'ServerName www.example.com:80' Or you say it pulls the details from VirtualHost settings though.
Doesn't that not slightly contradict the documentation when it comes to CanonicalPorts and Name?
Correct. The behaviour does not match the documentation.
The patch to modify the behaviour to match the documentation is pretty much trivial, but I for one don't have the energy to start fighting the developers right now. It is a behavioural change, and most likely their preferred response is to simply modify the documentation, not the behaviour. Especially since the workaround is to name the server explicitly, or to use mod_rewrite.
Even if they did accept the patch, it would take at least half a year (maybe a year for RHEL/CentOS/ScientificLinux et al.) to propagate down into Linux distributions.
Quote:
Originally Posted by helptonewbie
Is this only going to happen for a final URL of / then? Why would it not keep to the same methods if final destination was /dir/file?
This happens whenever the target URL for a Redirect , RedirectTemp, or RedirectMatch directive begins with a slash. It does not need to be a slash only.
Like I wrote earlier, the Redirect* directives are provided by the mod_alias module. One simple workaround is to rewrite the redirections using mod_rewrite, i.e.
because unlike mod_alias, mod_rewrite allows you to use request header values in the target URL. The %{HTTP_HOST} used in the above example is replaced by the host name the client used for the current request.
Quote:
Originally Posted by helptonewbie
Also I wondered if things would work correctly if I forced in this case 'ServerName www.example.com:80' Or you say it pulls the details from VirtualHost settings though.
The source code compares the port specified in the request headers, and the port specified for the VirtualHost. If they differ, the code will put the VirtualHost port into the redirected URL. So, I don't think that ServerName will help.
But, like I said, that only happens when using Redirect* family of directives, with a target URL beginning with a slash. Perhaps the simplest workaround is to just prepend the scheme and host name ( http://your.ser.ver ) to the target URL. Apache will not modify the target URL at all then.
I do realise it is a bit tedious, especially if you have a lot of them, but those seem to be your options for now.
Thanks for a great reply yet again @Nominal Animal
Quote:
Like I wrote earlier, the Redirect* directives are provided by the mod_alias module. One simple workaround is to rewrite the redirections using mod_rewrite, i.e.
Not 100% on what you meant here though, the redirects we're doing were already by mod_rewrite, unless there's a part of mod_rewrite that uses mod_alias or something?
We could add things like (http://%{HTTP_HOST}) scheme and hostname but the problem is we then need to double up everything so we can start catching when the request was via https or http to rewrite the correct schema. But as you say all this work as there are a lot... probably is our only sorry option.
Not 100% on what you meant here though, the redirects we're doing were already by mod_rewrite, unless there's a part of mod_rewrite that uses mod_alias or something?
I assumed you were using mod_alias (Redirect* family of directives) since mod_rewrite (Rewrite* family of directives) does provide useful workarounds.
First, set the proper scheme into an environment variable before any of the RewriteRules are evaluated:
If you use an SSL offloader in your load balancer, configure it to set a custom header for requests using SSL/TLS, and change the RewriteCond above to match. (You can check any request header using %{HTTP:header} in the RewriteCond test string.)
Then, modify those RewriteRules that can cause a redirect to something like
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.