我在 Debian Bookworm 上运行默认的 nginx 包。通常我只使用 HTTPS 连接该服务,一切正常。HTTP 端口 80 的默认重定向到 HTTPS 协议。
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
我有一个不支持 HTTPS 的 IoT 客户端。因此,我将其配置为使用 HTTP 将传感器数据发送到 Nginx 服务器上的挂钩 URL。我为该本地域 xyz 添加了 VHost,它不会将请求转发到 HTTPS,而是使用纯 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
但是该请求从未被 Nginx 处理。
使用curl
,我得到了这个回应
# 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
(Nginx 正在监听所有设备,没有防火墙处于活动状态,当我停止服务时,端口被关闭……)。
journald 中、nginx 访问或错误日志中都没有错误日志消息。
然后我尝试硬核telnet
访问 80 端口,得到了更奇怪的结果:
# telnet localhost 80
Trying ::1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Connection closed by foreign host.
(要清楚,我输入时GET / HTTP/1.1\n
没有第二个空行,只有一个“输入”,当我输入一些不符合 HTTP 规范的内容时,比如随机字符串,服务器会响应??
)
因此,在第一行之后,Nginx 就关闭了连接(HTTP/0.9 响应来自 curl 本身)。
因为我无法Host:
在请求中设置标头,所以此请求永远不会检查任何虚拟主机配置。
我不知道哪里出了问题。服务器至少应该等待 Host-header 才能关闭连接。/etc/nginx/nginx.conf
没有改变。
根据nginx -t
配置,服务器在 上响应正常curl -v https://localhost/
。SSL 配置等这里就省略了。它正在工作。
6
最佳答案
1
如果根本没有日志消息,还有另一种方法可以找到问题。我们知道,普通的 Nginx 就可以正常工作。因此,从 nginx 中删除所有虚拟主机配置,然后从简单的默认设置开始。
通过这样做,我可以看到 Nginx 正在按预期做出响应。
然后将刚才的虚拟主机配置逐一添加。
问题出在另一个虚拟主机配置中,它在纯 http 套接字中使用了 http2 指令。
server {
listen 80 http2;
listen [::]:80 http2;
server_name abc;
server_tokens off;
return 301 https://$host$request_uri;
}
(Debian Bookworm 上的旧 nginx 包(1.22.1)尚不支持http2 on;
配置)
http2
当删除此指令时,nginx / curl / telnet / IoT 将按预期工作。
当一个非 SSL 虚拟主机使用 HTTP/2 指令时,我找不到 Nginx 无法正常工作的原因。但我可以在其他几个系统上重现它。
文档:
http2 参数 (1.9.5) 配置端口以接受 HTTP/2 连接。通常,要使其正常工作,还应指定 ssl 参数,但也可以配置 nginx 以接受没有 SSL 的 HTTP/2 连接。
4
-
哦,我明白了。listen 指令上的标志对于端口号来说是全局的,因此所有监听端口 80 的服务器都将使用 http2。这不是一个显而易见的知识。
– -
无论如何,没有 ssl 的 http2 几乎毫无意义,没有真正的浏览器支持它。
– -
真的吗?所以一个 listen 443 ssl 就足够了,其他所有 listen 443 都需要设置 SSL,即使没有该指令也是如此。哦。我还以为 http2 指令向后兼容 http1。
– -
是的,普通端口上的 http2 不向后兼容。它在 https 上兼容,因为浏览器和服务器可以在 http 之前使用 ALPN 协商协议。
–
|
–
–
Because I could not set the Host: header in the request
– 是的,你打了电话localhost
。–
GET / HTTP/1.1\n
。–
GET
在行后立即关闭连接–
|