如何找出Nginx用作http / 2负载平衡器时为何返回400?

时间:2019-01-28 03:57:01

标签: nginx grpc http2

我自己实现了一个http / 2代理,并且使用Nginx作为负载均衡器。

当我将Nginx用作h2c负载平衡器时,它会起作用:

server {
    listen 8443 http2;

    location / {
        error_log /Users/jiajun/nginx_error_log.log debug;
        grpc_pass grpc://127.0.0.1:2017;
    }
}

运行它:

$ go run example/grpc_client/main.go
calling to 127.0.0.1:2019
2019/01/28 11:50:46 gonna call c.SayHello...
2019/01/28 11:50:46 Greeting: Hello world

Nginx访问日志为:

127.0.0.1 - - [28/Jan/2019:11:50:46 +0800] "POST /helloworld.Greeter/SayHello HTTP/2.0" 200 18 "-" "grpc-go/1.16.0" "-"

但是当我在SSL下提供它时,它不起作用:

server {
    listen 8443 ssl http2;
    ssl_certificate     /Users/jiajun/127.0.0.1.crt;
    ssl_certificate_key /Users/jiajun/127.0.0.1.key;

    location / {
        error_log /Users/jiajun/nginx_error_log.log debug;
        grpc_pass grpc://127.0.0.1:2017;
    }
}

运行它:

$ go run example/grpc_client/main.go
calling to 127.0.0.1:2019
2019/01/28 11:53:06 gonna call c.SayHello...
2019/01/28 11:53:06 could not greet: rpc error: code = Unavailable desc = transport is closing
exit status 1

而且,Nginx访问日志是:

127.0.0.1 - - [28/Jan/2019:11:53:06 +0800] "PRI * HTTP/2.0" 400 157 "-" "-" "-"

因此,我试图找出为什么在使用SSL时返回400的原因。但是,即使我已将日志级别设置为debug(并且它已使用--with-debug选项进行了编译),Nginx也不会在错误日志中记录该过程。

是否有调试的好主意?

1 个答案:

答案 0 :(得分:0)

看起来像Nginx并不认为它正在使用HTTP / 2,因为go客户端正在发送Nginx认为是真实消息的连接序言消息("PRI * HTTP/2.0")。

可能的问题是Nginx在SSL / TLS握手中没有声明它通过ALPN(或更旧的NPN)支持HTTP / 2。 Nginx使用哪个版本的OpenSSL(或等效版本)?运行nginx -V以查看此内容。理想情况下,您希望1.0.2或更高版本支持ALPN。

还要检查您的SSL / TLS密码是否未使用one of the ciphers forbidden for HTTP/2。像下面的配置(generated by the Mozilla SSL config generator)应该确保首选正确的密码:

# modern configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;