You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "William A. Rowe Jr." <wr...@rowe-clan.net> on 2013/12/13 22:54:22 UTC
[PATCH] Re: Behavior of Host: vs. SNI Hostname in proxy CONNECT
requests
On Mon, 25 Nov 2013 15:55:41 -0600
"William A. Rowe Jr." <wr...@rowe-clan.net> wrote:
> It appears that our SNI hostname comparison is invalid for forward
> proxy applications, specifically proxy CONNECT. RFC 2616 states;
>
> 14.23 Host
>
> The Host request-header field specifies the Internet host and port
> number of the resource being requested, as obtained from the
> original URI given by the user or referring resource (generally an
> HTTP URL, as described in section 3.2.2). The Host field value MUST
> represent the naming authority of the origin server or gateway given
> by the original URL. This allows the origin server or gateway to
> differentiate between internally-ambiguous URLs, such as the root
> "/" URL of a server for multiple host names on a single IP address.
>
> I had read this as proxy host's name in forward proxy applications,
> but reading on, it's clear this is ambiguous; from RFC 2817
>
> 5.2 Requesting a Tunnel with CONNECT
>
> A CONNECT method requests that a proxy establish a tunnel
> connection on its behalf. The Request-URI portion of the Request-Line
> is always an 'authority' as defined by URI Generic Syntax [2], which
> is to say the host name and port number destination of the requested
> connection separated by a colon:
>
> CONNECT server.example.com:80 HTTP/1.1
> Host: server.example.com:80
>
> So we have a clear, RFC-approved example of using the final endpoint
> as the Host: header value, not the intermediate proxy.example.com.
>
> In this case, we fail the request because the SNI of the proxy machine
> does not match the Host: of the origin server name.
>
> Ideas for the appropriate patch to httpd? Scope this fix to CONNECT
> requests alone, or all forward proxy requests?
After reading a rather confused and confusing thread on this question,
I've come to the conclusion that the entire block of code below is
wrong;
167 rpluem 757373 if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
168 char *host, *scope_id;
169 apr_port_t port;
170 apr_status_t rv;
171
172 /*
173 * The SNI extension supplied a hostname. So don't accept requests
174 * with either no hostname or a different hostname.
175 */
176 if (!r->hostname) {
177 sf 1209766 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02031)
178 rpluem 757373 "Hostname %s provided via SNI, but no hostname"
179 " provided in HTTP request", servername);
180 return HTTP_BAD_REQUEST;
181 }
This cannot occur for HTTP/1.1 requests as missing Host: is rejected elsewhere.
We have no particular reason to test for or prohibit HTTP/1.0 or 0.9 requests,
AFAICT.
182 rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
183 if (rv != APR_SUCCESS || scope_id) {
184 return HTTP_BAD_REQUEST;
185 }
186 jorton 1082189 if (strcasecmp(host, servername)) {
187 sf 1209766 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
188 rpluem 757373 "Hostname %s provided via SNI and hostname %s provided"
189 " via HTTP are different", servername, host);
190 return HTTP_BAD_REQUEST;
191 }
This occurs in all cases for HTTP CONNECT requests. There seems to be no
justification to test for this condition, since VirtualHost only establishes
a relationship of the HTTP Host: header. Any relationship to TLS/SNI hostnames
is a new (unwise) invention, which has broken a number of facilities in httpd.
Validation of the SNI hostname against ServerName/ServerAlias already occurs
elsewhere. As Yann is pointing out, validation of SSL session requirements
also already occurs elsewhere.
The definition of SNI hostname and HTTP Host: header values were never equal,
only roughly equivalent, and this attempt to make them synonymous has really
been disruptive to httpd stability.
I'm proposing the following patch to drop this foolishness into the very same
SSLStrictSNIVHostCheck ruleset, for those interesting in adding these new,
non-HTTP compliance requirements as HTTP compliance requirements.
Comments?