I'm runnning a default nginx package on Debian Bookworm. Normally I'm just using the HTTPS connections to that service and everything is fine. Default for HTTP port 80 is a redirect to the HTTPS protocol.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_tokens off;
return 301 https://$host$request_uri;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log error;
}
// vhosts with listen 443 configs omited here, they work
I've an IoT client, that doesnt speak HTTPS. So, I configured it to use HTTP to send sensor data to a hook url on the Nginx server. I added a VHost for that local domain xyz, that doesn't forward the request to HTTPS but processed it with plain HTTP.
server {
listen 80;
listen [::]:80;
server_name xyz;
server_tokens off;
location / {
root /var/www/html/;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log error;
}
// vhosts with listen 443 configs omited here, they work
But that request is never processed by the Nginx.
Using curl
, I'm getting this response
# curl -v http://localhost/
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
* Received HTTP/0.9 when not allowed
* Closing connection 0
curl: (1) Received HTTP/0.9 when not allowed
(Info: Nginx is listening on all devices, no firewall is active, when I stop the service, the port is closed in Linux...).
There is no error log message neither in journald, nor in nginx access or error logs.
Then I tried hardcore telnet
to port 80 and got a more strange result:
# telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Connection closed by foreign host.
To be clear, I've entered GET / HTTP/1.1\n
without a second empty line, only one "enter". When I enter something not HTTP conform, like a random string, the server responses with ??
.
So, right after the first line, Nginx is closing the connection (the HTTP/0.9 response comes from curl itself).
Because I could not set the Host:
header in the telnet request, this request never checks any virtual host configuration and I asume the curl client has the same issue. It tries to send all the headers to the socket, but the Nginx response is already there.
I don't have an idea, what is wrong. The server should at least wait for the Host-header before closing the connection. The /etc/nginx/nginx.conf
is not changed.
According to nginx -t
the configuration is ok, the server responses normal on curl -v https://localhost/
. The SSL configuration etc. is omitted here. It's working.
When there is no log message at all, there is another option to find the problem. We know, that a plain Nginx works. So, remove ALL virtual host configurations from nginx and start with a simple default setup.
By doing that, I can see, that Nginx is responding as expected.
Then add the earlier virtual host configurations one by one.
The problem was in another virtualhost configuration, that uses the http2 directive in the plain http socket.
(older nginx package (1.22.1) on Debian Bookworm doesnt yet support
http2 on;
configuration)When this
http2
directive is removed, the nginx / curl / telnet / IoT is working as expected.I could not find a reason, why Nginx is not working properly, when one non-ssl virtual host uses the HTTP/2 directive. But I could reproduce it on several other systems.
The documentation says: