go-grpc-http1 icon indicating copy to clipboard operation
go-grpc-http1 copied to clipboard

Add support for forward proxy/MitM proxy for gRPC-Web mode

Open ofirc opened this issue 1 year ago • 2 comments

Hi, Does the gRPC-Web mode honour the https_proxy env vars for TLS targets? The question is for both forward proxy and man-in-the-middle proxies listening on HTTP ports (not HTTPS). Not sure if it's tested / supported. Saw this related PR: https://github.com/stackrox/go-grpc-http1/pull/163

Thanks! Ofir

ofirc avatar Dec 19 '24 22:12 ofirc

That's the code I used but the traffic doesn't get routed to the proxy and I don't see any logs on the proxy end. Wondering if the client.ConnectWithProxy and other functions need to be modified to support a proxy server.

package main

import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"time"

	"github.com/ofirc/grpc-http1/hello"
	"golang.stackrox.io/grpc-http1/client"
)

func main() {
	//grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(os.Stdout, os.Stderr, os.Stderr, 99))

	// Load the server certificate
	certFile := "cert.pem"
	certPool := x509.NewCertPool()
	cert, err := ioutil.ReadFile(certFile)
	if err != nil {
		log.Fatalf("Failed to read certificate: %v", err)
	}
	if !certPool.AppendCertsFromPEM(cert) {
		log.Fatalf("Failed to append server certificate")
	}

	// Create TLS configuration for the client
	tlsClientConfig := &tls.Config{
		RootCAs:            certPool,
		ServerName:         "localhost",          // Match the server's certificate
		InsecureSkipVerify: false,                // Ensure proper server validation
		NextProtos:         []string{"http/1.1"}, // Explicitly set ALPN to "http/1.1"
	}

	// Connect to the server with grpc-http1 over HTTP/1.1
	conn, err := client.ConnectViaProxy(context.Background(), "localhost:8443", tlsClientConfig)
	if err != nil {
		log.Fatalf("Failed to connect: %v", err)
	}
	defer conn.Close()

	fmt.Println(os.Getenv("http_proxy"))
	fmt.Println(os.Getenv("HTTP_PROXY"))
	fmt.Println(os.Getenv("https_proxy"))
	fmt.Println(os.Getenv("HTTPS_PROXY"))

	// Create a HelloService client
	client := hello.NewHelloServiceClient(conn)

	// Call the SayHello RPC
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	req := &hello.HelloRequest{Name: "World"}
	resp, err := client.SayHello(ctx, req)
	if err != nil {
		log.Fatalf("Failed to call SayHello: %v", err)
	}
	log.Println("Response:", resp.Message)
}

ofirc avatar Dec 19 '24 22:12 ofirc

Hi @ofirc , thanks for raising the issue. There is no motion in #163 . Would you have capacity to pick it up and finish it (or write it from scratch)?

vikin91 avatar Jan 31 '25 15:01 vikin91