Andrey Kulikov
May 23, 2023 06:08PM
Hello,

Observed nginx's version 1.22.1 questionable behaviour with two virtual
hosts, one with H2 - enabled, second without http2 support.
Both on the same IP and port, with different domain names/server names.
When browsers make requests to a second domain, h2 being ALPN-negotiated,
and data transferred via HTTP/2, in spite of http2 was not configured on
that virtual host.

Sample config snippet:

http {
....
server {
listen 1985 http2 ssl;
server_name 'mavr.cp.eu';

ssl_certificate domain.cer;
ssl_certificate_key domain.key;

location / {
return 302 https://zavr.cp.eu:1985$request_uri;
}
}

server {
listen 1985 ssl; # NO h2!
server_name 'zavr.cp.eu';

ssl_certificate domain.cer;
ssl_certificate_key domain.key;

location / {
# Doesn't really matter what's here, for simplicity I've used
ngx_lua_module.
echo "Server protocol: $server_protocol H2 connection: $http2
..";
}
}
....
}

When I type https://mavr.cp.eu:1985 in browser I see:

1. Browser negotiates h2 ALPN with the server with SNI mavr.cp.eu ;
2. Server replied with 302 redirect to https://zavr.cp.eu:1985 (expected)
3. Browser makes NEW TCP-connection with the server with SNI zavr.cp.eu;
(expected)
4. Server replied with h2 ALPN (unexpected)
5. Browser shows "Server protocol: HTTP/2.0 H2 connection: h2 ."

When I browsed source code, I spotted following line:
http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l460

#if (NGX_HTTP_V2)
<http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l459>
if (hc->addr_conf->http2) {
<http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l460>
srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO
NGX_HTTP_ALPN_PROTOS;
<http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l461>
srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) -
1; <http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l462>
} else <http://hg.nginx.org/nginx/file/tip/src/http/modules/ngx_http_ssl_module.c#l463>#endif


My assumption (could be wrong) that it means, when http2 is enabled on the
address, related to (possibly) many virtual hosts, we always add h2 ALPN.
Regardless of negotiated SNI.
At least I see that ngx_http_find_virtual_server() being called here:
http://hg.nginx.org/nginx/file/tip/src/http/ngx_http_request.c#l2236
on already established http(s) connection, not during TLS handshake.

This behaviour caused some pain in my neck today, so could please someone be
so kind to enlighten me, is it like it supposed to be, or is it possible to
change this in the way, so http1 and http2 virtual hosts could be served on
the same IP:port?
Is it a bug, feature, or just not needed by anyone?
Quick Googling did not reveal that anyone had complained about it too much.

If one will manage to implement a patch, correcting this behaviour, will it
be even considered to review?

--
Andrey

P.S. Under "Browser" here I meant Chrome, Chromium, and Firefox on Windows.
But, according to unconfirmed information, "some", yet unidentified,
browsers do NOT make a second TCP-connection to another domain after
redirection in the provided example.
And put a second request to the same h2 connection, despite the fact that
it was negotiated for different SNI.
Shame on them.
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

Q: http2 and http1 virtual hosts both works via HTTP/2 - bug of feature?

Andrey Kulikov 244 May 23, 2023 06:08PM

Re: Q: http2 and http1 virtual hosts both works via HTTP/2 - bug of feature?

Maxim Dounin 108 May 24, 2023 10:40AM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 141
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready