Skip to content

x/net/http2: support http2 proxy connections #26479

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
iaguis opened this issue Jul 19, 2018 · 11 comments
Open

x/net/http2: support http2 proxy connections #26479

iaguis opened this issue Jul 19, 2018 · 11 comments
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal.
Milestone

Comments

@iaguis
Copy link

iaguis commented Jul 19, 2018

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.10.3 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOCACHE="..."
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="..."
GORACE=""
GOROOT="/usr/lib/go"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build612803013=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I have an HTTP/2 proxy (I tested a custom one and https://github.com/caddyserver/forwardproxy) and when trying to connect through it from a client using HTTP/2 I get an error. This does not happen if I don't use HTTP/2.

Here's my code:

package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"

	"golang.org/x/net/http2"
)

func main() {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		Proxy:           http.ProxyFromEnvironment,
	}

	if err := http2.ConfigureTransport(tr); err != nil {
		fmt.Fprintf(os.Stderr, "error configuring transport: %v\n", err)
		os.Exit(1)
	}

	client := &http.Client{Transport: tr}
	rsp, err := client.Get("https://google.com")
	if err != nil {
		fmt.Fprintf(os.Stderr, "error getting: %v\n", err)
		os.Exit(1)
	}
	defer rsp.Body.Close()

	buf, err := ioutil.ReadAll(rsp.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading response: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("Response: %s\n", string(buf))
}

If I comment out the http2.ConfigureTransport() call (so it will use HTTP/1.1) it works fine.

What did you expect to see?

A successful connection.

What did you see instead?

On the proxy server:

2018/07/19 18:30:25 http2: server connection from 127.0.0.1:54850 on 0xc420174b60
2018/07/19 18:30:25 http2: server: error reading preface from client 127.0.0.1:54850: bogus greeting "CONNECT google.com:443 H"

On the client:

2018/07/19 18:30:25 http2: Transport failed to get client conn for google.com:443: http2: no cached connection was available
error getting: Get https://google.com: malformed HTTP response "\x00\x00\x18\x04\x00\x00\x00\x00\x00\x00\x05\x00\x10\x00\x00\x00\x03\x00\x00\x00\xfa\x00\x06\x00\x10\x01@\x00\x04\x00\x10\x00\x00"
@agnivade
Copy link
Contributor

Seems like a duplicate of #21336 ?

/cc @bradfitz

@bradfitz
Copy link
Contributor

I think they're different bugs.

This is more of a documentation or feature request to support http2 proxies. We only support http1 proxies currently.

@agnivade agnivade changed the title net/http: http2 connections to a proxy don't seem to work x/net/http2: support http2 proxy connections Jul 19, 2018
@agnivade agnivade added the FeatureRequest Issues asking for a new feature that does not need a proposal. label Jul 19, 2018
@agnivade agnivade added this to the Unplanned milestone Jul 19, 2018
@shivakumargn
Copy link
Contributor

Is there any plan to support http2 proxy?

@crowfrog
Copy link

same question about plan for this feature. :)

@g00nix
Copy link

g00nix commented Mar 21, 2021

Currently most people implement HTTPS proxies in Go with http.Hijacker which does not support http2, which mostly means you have to disable http2 completely with TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)).

We can start to do some tricks and hack our way into getting it working, but official support from GoLang into this direction would be a lot better for everybody.

@anupamasok
Copy link

Currently most people implement HTTPS proxies in Go with http.Hijacker which does not support http2, which mostly means you have to disable http2 completely with TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)).

We can start to do some tricks and hack our way into getting it working, but official support from GoLang into this direction would be a lot better for everybody.

I was looking for a way to Achieve HTTP2 with proxy added. Details. Could you elaborate the "We can start to do some tricks and hack our way into getting it working" @g00nix

@g00nix
Copy link

g00nix commented Jun 11, 2021

I was looking for a way to Achieve HTTP2 with proxy added. Details. Could you elaborate the "We can start to do some tricks and hack our way into getting it working" @g00nix

We should be able to get a http2 proxy working by avoiding net/http completely and just going at a lower level to create the TCP connection and the TLS handshake. I managed to get it working for a transparent proxy, but never invested the time to get this done for a normal proxy.

However it would be better if this was just supported by the official lib, than having to completely rewrite the proxy functionality of net/http.

@chew351
Copy link

chew351 commented Sep 15, 2021

Is there any plan to support http2 proxy?

Guys, Is there any plan to support http2 proxy?
It’s helpfull for using net/http2 in a cluster

Thanks
zcy

@elgohr
Copy link

elgohr commented Jan 5, 2022

I guess this dialer would be a good workaround for now https://github.com/mwitkow/go-http-dialer

@fbuetler
Copy link

This is still an issue with go 1.21. What is the roadmap for this feature? Is it a tricky one to implement?

We should be able to get a http2 proxy working by avoiding net/http completely and just going at a lower level to create the TCP connection and the TLS handshake.

We did the same for an explicit forward proxy.

@renuka-fernando
Copy link

hi @iaguis, @fbuetler and all,

I've tried this and this is working now.

$ go version     
go version go1.22.2 darwin/arm64

I've written a simple HTTP2 go server which prints the HTTP version and points the client to this server.

server.go

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
)

func main() {
	// Define a handler function for the root route
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// Log the protocol being used
		log.Printf("Server: Request received using protocol: %s\n", r.Proto)

		// Read the request body
		body, err := io.ReadAll(r.Body)
		if err != nil {
			log.Printf("Failed to read request body: %v", err)
			return
		}
		defer r.Body.Close()

		// Log the request body
		log.Printf("Server: Request body: %s\n", string(body))

		// Respond to the client
		fmt.Fprintf(w, "Hello, this is an HTTP/2 server!")
	})

	// Start the HTTP/2 server on port 8443
	log.Println("Starting HTTP/2 server on https://localhost:8443")
	err := http.ListenAndServeTLS(":8443", "server.crt", "server.key", nil)
	if err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}

HTTP/2

With the following code

	if err := http2.ConfigureTransport(tr); err != nil {
		fmt.Fprintf(os.Stderr, "error configuring transport: %v\n", err)
		os.Exit(1)
	}

my go server prints the following

2025/02/05 09:00:50 Server: Request received using protocol: HTTP/2.0
2025/02/05 09:00:50 Server: Request body:

HTTP/1.1

Without the above code, my go server prints the following

2025/02/05 09:01:46 Server: Request received using protocol: HTTP/1.1
2025/02/05 09:01:46 Server: Request body:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal.
Projects
None yet
Development

No branches or pull requests