Bug 63504 - Invalid port in redirects behing load balancer
Summary: Invalid port in redirects behing load balancer
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: Core (show other bugs)
Version: 2.5-HEAD
Hardware: PC All
: P2 minor (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-06-14 20:38 UTC by Julien Trolet
Modified: 2019-06-14 21:26 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julien Trolet 2019-06-14 20:38:59 UTC
When I use a load balancer on the default port (http/80, https/443) that routes request to an httpd instance listening on a non default port, httpd builds redirects that include the load balancer's hostname but the port of the httpd virtual host.

UseCanonicalName is turned off.

I've looked at the code in vhost.c that handles the Host header and the code in core.c that builds the absolute URI used for the Location header in redirects and my understanding is that when the absolute URI is computed the absence of a port in the Host header of the request is treated as if there was no Host header at all.
r->parsed_uri.port_str ? r->parsed_uri.port : ...
And parsed_uri.port_str is only set if there is a port in the Host header.

A workaround that I've come to use in multiple installations is to set the ServerName with the default port inside the <VirtualHost> since this sets the SERVER_PORT.

I've reproduced the issue with a very basic setup.
Listen 4080
<VirtualHost *:4080>
</VirtualHost>
And an empty test/ folder in the DocumentRoot.

When I call with an explicit port in the Host header everything works as expected (I can supply any hostname it is echoed back in the Location header)

GET /test HTTP/1.1
Host: whatever:80

HTTP/1.1 301 Moved Permanently
Date: Fri, 14 Jun 2019 20:35:07 GMT
Server: Apache/2.5.1-dev (Unix)
Location: http://whatever/test/

When I call without a port in the Host header the Location header in the response contains the server port but the hostname part of the Host header is echoed back

GET /test HTTP/1.1
Host: whatever

HTTP/1.1 301 Moved Permanently
Date: Fri, 14 Jun 2019 20:35:09 GMT
Server: Apache/2.5.1-dev (Unix)
Location: http://whatever:4080/test/

I've reproduced the issue on httpd 2.2.8, 2.4.37 and a build from a fresh checkout from 2.5-HEAD.
Comment 1 Eric Covener 2019-06-14 21:05:12 UTC
Since `ServerName foo` and not the ugly `ServerName foo:80` is sufficient I'm not sure it's even worth documenting.  Maybe a warning about not omitting the ServerName completely from a virtualhost under e.g.

https://httpd.apache.org/docs/2.4/mod/core.html#usecanonicalphysicalport
Comment 2 Julien Trolet 2019-06-14 21:26:49 UTC
When you specify the Listen port (or any other non standard port) in the ServerName directive you also get the same issue, requests with a port in the Host header will get valid responses since the port from the Host header will be echoed back, but requests without a port in the Host header will have the server port in the response.
The workaround works fine but requires that you set the ServerName to a value that either does not contain a port or contains the default port, I just felt it at least needed to be reported since I have been using it for some time.