Opened 7 months ago

Closed 6 months ago

#2158 closed enhancement (wontfix)

ngx_stream_core_module Add $preread_server_name from http header.HOST

Reported by: Ivan Owned by:
Priority: minor Milestone:
Component: documentation Version: 1.19.x
Keywords: stream proxy preread_server_name http/2 Cc: Ivan
uname -a: Linux RPi4 5.4.101 #0 SMP Sun Feb 28 23:59:21 2021 aarch64 GNU/Linux
nginx -V: nginx version: nginx/1.19.6 (x86_64-pc-linux-gnu)
built with OpenSSL 1.1.1j 16 Feb 2021
TLS SNI support enabled
configure arguments: --target=aarch64-openwrt-linux --host=aarch64-openwrt-linux --build=x86_64-pc-linux-gnu --program-prefix= --program-suffix= --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --sysconfdir=/etc --datadir=/usr/share --localstatedir=/var --mandir=/usr/man --infodir=/usr/info --disable-nls --crossbuild=Linux::aarch64 --prefix=/usr --conf-path=/etc/nginx/nginx.conf --with-http_ssl_module --with-ipv6 --with-http_stub_status_module --with-http_flv_module --with-http_dav_module --with-http_auth_request_module --with-http_v2_module --with-http_realip_module --with-http_secure_link_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-headers-more --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-naxsi/naxsi_src --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/lua-nginx --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-dav-ext-module --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-brotli --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-rtmp --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-ts --add-module=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6/nginx-ubus-module --error-log-path=stderr --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-cc=aarch64-openwrt-linux-musl-gcc --with-cc-opt='-I/builder/shared-workdir/build/sdk/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/usr/include -I/builder/shared-workdir/build/sdk/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/include/fortify -I/builder/shared-workdir/build/sdk/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/include -I/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libiconv-stub/include -I/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libintl-stub/include -Os -pipe -fno-caller-saves -fno-plt -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -ffile-prefix-map=/builder/shared-workdir/build/sdk/build_dir/target-aarch64_cortex-a72_musl/nginx-all-module/nginx-1.19.6=nginx-1.19.6 -Wformat -Werror=format-security -fstack-protector -D_FORTIFY_SOURCE=1 -Wl,-z,now -Wl,-z,relro -I/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libiconv-stub/include -I/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libintl-stub/include -fvisibility=hidden -ffunction-sections -fdata-sections -DNGX_LUA_NO_BY_LUA_BLOCK' --with-ld-opt='-L/builder/shared-workdir/build/sdk/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/usr/lib -L/builder/shared-workdir/build/sdk/staging_dir/toolchain-aarch64_cortex-a72_gcc-8.4.0_musl/lib -znow -zrelro -L/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libiconv-stub/lib -Wl,-rpath-link=/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libiconv-stub/lib -L/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libintl-stub/lib -Wl,-rpath-link=/builder/shared-workdir/build/sdk/staging_dir/target-aarch64_cortex-a72_musl/usr/lib/libintl-stub/lib -Wl,--gc-sections' --without-http_upstream_zone_module

Description

HTTP/2 Coalescing
Due to the way HTTP/2 clients reuse connections, there can be problems with SNI routing if there is an overlap of server name among the names (Common Name and Subject Alternate Name) in TLS certificate of origin servers.

https://miro.medium.com/max/3840/1*Fk8pDKD0O760WuDqM4ysyA.png

In the above example, since the TLS certificate used by origin server 10.0.3.2 has wildcard name *.example.com, Web Browser can make a TLS connection with server name b.example.com and use the same connection for HTTP/2 requests to a.example.com. This can cause undefined behavior in web sites and applications.

See: https://levelup.gitconnected.com/multiplex-tls-traffic-with-sni-routing-ece1e4e43e56

Many people use a script, but it is difficult to connect it. Difficult compilation required for ARM platform.

Please add a variable $preread_server_name from http headers.

var server_name = '-';

/

  • Read the server name from the HTTP stream. *
  • @param s
  • Stream. */

function read_server_name(s) {

s.on('upload', function (data, flags) {

if (data.length
flags.last) {

s.done();

}

If we can find the Host header.
var n = data.indexOf('\r\nHost: ');
if (n != -1) {

Determine the start of the Host header value and of the next header.
var start_host = n + 8;
var next_header = data.indexOf('\r\n', start_host);

Extract the Host header value.
server_name = data.substr(start_host, next_header - start_host);

Remove the port if given.
var port_start = server_name.indexOf(':');
if (port_start != -1) {

server_name = server_name.substr(0, port_start);

}

}

});

}

function get_server_name(s) {

return server_name;

}

export default {read_server_name, get_server_name}

Attachments (3)

1_Fk8pDKD0O760WuDqM4ysyA.png (55.2 KB ) - added by Ivan 7 months ago.
http_server_name.js (952 bytes ) - added by Ivan 7 months ago.
AfterRefresh.png (91.9 KB ) - added by Ivan 7 months ago.

Download all attachments as: .zip

Change History (6)

by Ivan, 7 months ago

by Ivan, 7 months ago

Attachment: http_server_name.js added

by Ivan, 7 months ago

Attachment: AfterRefresh.png added

comment:1 by Maxim Dounin, 7 months ago

In no particular order:

  • There is a response code 421 which can be used to reject request which cannot be handled by a particular server, see RFC 7540. If you are using HTTP/2 and SNI-based routing, it is a good idea to configure your backend servers to respond with 421 for requests to names they don't know how to handle.
  • Using HTTP header Host is wrong, since the request authority can be provided in a request line instead, see RFC 7230.
  • Using request headers for connection routing is wrong, since these headers only apply to a particular request, not the whole connection. There can be multiple requests in a connection, and it is not guaranteed that all these requests will be to the same server name. While this might not be common in HTTPS requests from browsers, this certainly can easily happen in case of HTTP and/or in non-browser requests. That is, routing based on the first request headers requires very same precautions as HTTP/2 with SNI-based routing: your backends have to be able to properly handle other names.

Overall, if you are able to decrypt SSL traffic on the nginx host, it is much better idea to use the HTTP module to handle and route requests. Obviously, if you are not able to decrypt SSL traffic, SNI-based routing is the only available approach.

comment:2 by maxim, 6 months ago

Milestone: nginx-1.19

Ticket retargeted after milestone closed

comment:3 by Maxim Dounin, 6 months ago

Resolution: wontfix
Status: newclosed

Closing this for reasons explained in comment:1.

Note: See TracTickets for help on using tickets.