Nginx HTTP/2 over TLS 访问报 400,有熟悉的同学吗?

2019-01-28 15:00:07 +08:00
 gansteed

最近在写一个 HTTP/2 的代理。如果是不带 TLS 的话,是可以正常工作的,

    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" "-"

加证书之后:

    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 "-" "-" "-"

有同学遇到同样的问题吗?

此外,可以写一个简单的 demo 复现问题:

package main

import (
	"crypto/tls"
	"log"
)

func main() {
	backendConn, err := tls.Dial("tcp", "127.0.0.1:8443", &tls.Config{InsecureSkipVerify: true})
	if err != nil {
		log.Printf("failed to dial: %s", err)
	}

	if _, err := backendConn.Write([]byte("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")); err != nil {
		log.Printf("failed to write: %s", err)
	}

	b := make([]byte, 4096)
	if _, err := backendConn.Read(b); err != nil {
		log.Printf("failed to read: %s", err)
	}

	log.Printf("result: %s", b)
}

结果:

$ go run main.go
2019/01/28 14:59:50 result: HTTP/1.1 400 Bad Request
Server: nginx/1.15.8
Date: Mon, 28 Jan 2019 06:59:50 GMT
Content-Type: text/html
Content-Length: 157
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.15.8</center>
</body>
</html>
3236 次点击
所在节点    问与答
3 条回复
justfly
2019-01-28 15:24:01 +08:00
很迷,你给的配置 nginx 监听的 8443 端口,log 里面却是连接 2019 端口。demo 里面去访问一个 http/2 服务,http/2 是二进制协议,你在 tls 连接上直接给的是纯文本协议。。。
gansteed
2019-01-28 16:32:01 +08:00
popstk
2019-01-29 17:33:14 +08:00
https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing
试试配下证书->
<code>
certificate, err := credentials.NewServerTLSFromFile(crtFile, keyFile)
if err != nil {
log.Fatalf("can not load certificate: %v", err)
}
conn, err := grpc.Dial(address, grpc.WithTransportCredentials(certificate))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
</code>

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/531250

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX