Skip to content
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

net/http/httputil: ReverseProxy does not strip all hop-by-hop headers #16875

Closed
c960657 opened this issue Aug 25, 2016 · 10 comments
Closed

net/http/httputil: ReverseProxy does not strip all hop-by-hop headers #16875

c960657 opened this issue Aug 25, 2016 · 10 comments

Comments

@c960657
Copy link

c960657 commented Aug 25, 2016

  1. What version of Go are you using (go version)?
    1.6
  2. What operating system and processor architecture are you using (go env)?
    GOARCH="amd64"
    GOBIN=""
    GOEXE=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOOS="linux"
    GOPATH="/go"
    GORACE=""
    GOROOT="/usr/local/go"
    GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
    CC="gcc"
    GOGCCFLAGS="-fPIC -m64 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build436466338=/tmp/go-build -gno-record-gcc-switches"
    CXX="g++"
    CGO_ENABLED="0"
  3. What did you do?
    I created a basic reverse proxy:
package main

import (
    "log"
    "net/http"
    "net/http/httputil"
)

func main() {
    log.Fatal(http.ListenAndServe(":80", &httputil.ReverseProxy{
        Director: func(req *http.Request) {
            req.URL.Scheme = "http"
            req.URL.Host = "admin-monolith"
        },
    }))
}

Then I sent this HTTP request to the proxy (based on an example in the HTTP/2 spec):

GET / HTTP/1.1
Host: server.example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: abcdef...
  1. What did you expect to see?
    According to the Connection header, HTTP2-Settings is a hop-by-hop header, so I expected that the proxy would strip this header before forwarding the request.
  2. What did you see instead?
    The HTTP2-Settings header (but not the Upgrade) header was not stripped but was forwarded to the backend server.

Stripping hop-by-hop headers was implemented in #2735, but only headers explicitly mentioned in RFC 2616 are removed.

The relevant quote from RFC 7230, section 6.1 is this:

A proxy or gateway MUST parse a received Connection header field before
a message is forwarded and, for each connection-option in this field,
remove any header field(s) from the message with the same name as the
connection-option, and then remove the Connection header field itself
(or replace it with the intermediary's own connection options for the
forwarded message).

The same requirement was included in RFC 2616, section 14.10.

@bradfitz bradfitz added this to the Go1.8 milestone Aug 25, 2016
@siadat
Copy link
Contributor

siadat commented Aug 28, 2016

Should the values be comma-separated, like your example:

Connection: Upgrade, HTTP2-Settings

Or, space-separated as mentioned in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection#Directives?

@gopherbot
Copy link

CL https://golang.org/cl/27970 mentions this issue.

@c960657
Copy link
Author

c960657 commented Aug 28, 2016

The list should be separated by comma (with optional additional white-space).

The # construct is described in section 7.

@siadat
Copy link
Contributor

siadat commented Aug 28, 2016

Thanks for the link. The above CL assumes the tokens are separated with commas with optional white-space.

@gopherbot
Copy link

CL https://golang.org/cl/27971 mentions this issue.

@tnolli
Copy link

tnolli commented Sep 3, 2016

@siadat @bradfitz shouldn't we copy the headers as the next for loop is doing?

@siadat
Copy link
Contributor

siadat commented Sep 4, 2016

Thanks! Please review this https://golang.org/cl/28493
I also added a check to make sure the original request headers are not modified.

@gopherbot
Copy link

CL https://golang.org/cl/28493 mentions this issue.

@benburkert
Copy link
Contributor

Should these entries be scrubbed from the response headers (like the hop-by-hop headers) as well?

gopherbot pushed a commit that referenced this issue Sep 8, 2016
We were already making a copy of the map before removing
hop-by-hop headers. This commit does the same for proxied
headers mentioned in the "Connection" header.

A test is added to ensure request headers are not modified.

Updates #16875

Change-Id: I85329d212787958d5ad818915eb0538580a4653a
Reviewed-on: https://go-review.googlesource.com/28493
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
@gopherbot
Copy link

CL https://golang.org/cl/28810 mentions this issue.

gopherbot pushed a commit that referenced this issue Sep 8, 2016
…ReverseProxy

Hop-by-hop headers (explicitly mentioned in RFC 2616) were already
removed from the response. This removes the custom hop-by-hop
headers listed in the "Connection" header of the response.

Updates #16875

Change-Id: I6b8f261d38b8d72040722f3ded29755ef0303427
Reviewed-on: https://go-review.googlesource.com/28810
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
@golang golang locked and limited conversation to collaborators Sep 8, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants