Bug 65093

Summary: with UseCanonicalName=Off, the server should still use only known Names
Product: Apache httpd-2 Reporter: Christoph Anton Mitterer <calestyo>
Component: CoreAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: enhancement    
Priority: P2    
Version: 2.5-HEAD   
Target Milestone: ---   
Hardware: All   
OS: All   

Description Christoph Anton Mitterer 2021-01-20 05:12:51 UTC

Probably the following has been already asked somewhere and I just couldn't find it or there's a perfect reason which things are as they are and I'm too dumb to see it ^^ ... if so simply close.

First, on a request(!), the server - as documented in the vhost docs - ignores any Port in the Host: header but instead uses the real port of the connection for selecting the vhost candidates.
Which is fine of course.

Behaviour or documentation is already a bit odd though, cause when using e.g.
<VirtualHost some.domain.name.com:8080>

it would implicitly add some.domain.name.com:8080 (it seems *with* the port) to ServerAliases (as documented) - while ServerAlias doesn't even allow a port?

Nevertheless, that's not the point of this issue:

As the documentation of UseCanonicalName says, a value of "Off", makes httpd really use exactly the client provided Host: [addr|name]:port header for any redirects (and also for generated content like error messages in the response body).
And it would also use it literally (from the client Host: header) for CGI vars and that like

I think it might be an improvement (and in case of poorly written CGIs, even a security improvement) if it would do so only with a certain restriction, namely:

Only use the client's value if it's really a valid hostname and port of the vhost where the request ended up being processed.... and if not... use the vhosts canonical name and the port of the connection.

If one ends up in an IP-based vhost,... and the client's name/port don't match the configured ones of the vhost, use the canonical ServerName of the vhost and the port of the connection.

If one ends up in a name based vhost,... well if it's *not* the default-vhost for a certain name:port combination, one is anyway sure that the client provided value must have matched a ServerName/Alias of the vhost.
But if one ended up in the default (firts listed) vhost, the client might have specified anything for name:port and ended up there.
Anything for the name, because the default vhost would catch it, and anything for the port, because the Host: header port is ignored during vhost matching.

For testing I used a setup like this:
- DNS:
  all pointing to e.g.
- the server listening *.80
- two name based vhosts
  default.example.com (being the first listed one)
- both having this as their ServerName set
- both vhosts listening on the same addr:port like
- mod_dir enabled
- auto index enabled for /123/

Two requests:
a) wget --debug  --content-on-error -4 -O - --header="Host: foo.bar:666" http://example.com/123
b) wget --debug  --content-on-error -4 -O - --header="Host: foo.bar:666" http://example.com/123/

- both will reach the server
- both will end up in the default.example.com vhost as foo.bar is unknown but the connection IP matches the vhost IPs ... and the Host: port is ignored anyway

- (b) having the trailing / won't cause a redirect and show the dir listing
- (a) lacking the trailing / will cause a redirect, with http using foo.bar:666, for which we know it's definitely wrong.
The server can know, that only any valid [addr|name]:port combination for the vhost "default.example.com" would be a valid hostname (canonical or not).
And as such if there is no match, it should use the ServerName of default.example.com and *independently* if there's no match for the port, the port of the connection.

Comment 1 Christoph Anton Mitterer 2021-01-20 05:15:36 UTC
And as a small side note (which I don't quite understand):

If I do in my testing the very same as described above, but with mod_dir disabled it does "work".

That is:
Despite the missing trailing / in the case (a), no redirect is generated and mod_autoindex generates the very same output than in case (b).

From how I had understood the documentation, mod_autoindex shouldn't have done this.