[Feature Requst] add GRPC support to pritunl-zero

Hi, @zach

We want to put a grpc server behind pritunl-zero, during testing we found the request can pass pritunl-zero, but failed with bellow error:

rpc error: code = Internal desc = server closed the stream without sending trailers

According to the source code looks pritunl-zero is using http transport not http2 - pritunl-zero/proxy/web.go at master · pritunl/pritunl-zero · GitHub

This might be the root cause of the failure.

This is an example of revsere proxying grpc, seems we need to use http2 transport - net/http/httputil: Grpc over Go Proxy brings always connection error (help wanted) · Issue #29928 · golang/go · GitHub

Is it possible to implement grpc support? Thanks.

Support for HTTP/2 which includes gRPC has been added to the repository pritunl/pritunl-zero:e176707. It was tested with gRPC with and without TLS. There is still some uncommited code for the service option to enable/disable HTTP/2 support. This will be included in the next release.

Thanks, @zach for the quick response and kind support.

Do we have an ETA of next release?

Hi, @zach . We still had issue with lastet pritunl-zero.

I’ve verified that we need to include this change to make grpc work end to end.

btw in our setup, the pritunl-zero node is configured with HTTP protocol. I think that’s why we must have h2c.NewHandler.

diff --git a/router/router.go b/router/router.go
index 117cac58..db2a09ed 100644
--- a/router/router.go
+++ b/router/router.go
@@ -6,6 +6,8 @@ import (
 	"crypto/md5"
 	"crypto/tls"
 	"fmt"
+	"golang.org/x/net/http2"
+	"golang.org/x/net/http2/h2c"
 	"io"
 	"math/rand"
 	"net/http"
@@ -248,9 +250,10 @@ func (r *Router) initWeb() (err error) {
 	writeTimeout := time.Duration(settings.Router.WriteTimeout) * time.Second
 	idleTimeout := time.Duration(settings.Router.IdleTimeout) * time.Second

+	h2s := &http2.Server{}
 	r.webServer = &http.Server{
 		Addr:              fmt.Sprintf(":%d", r.port),
-		Handler:           r,
+		Handler:           h2c.NewHandler(r, h2s),
 		ReadTimeout:       readTimeout,
 		ReadHeaderTimeout: headerTimeout,
 		WriteTimeout:      writeTimeout,

Can you review it?