You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What does 'go version' print?
go version go1.2 linux/amd64
What steps reproduce the problem?
1. Write simple program on a proxyHost that should forward requests to a targetHost
censored.go: ( http://play.golang.org/p/YXT3zso8Ff )
package main
import (
"log"
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
targetUrl, _ := url.Parse("http://navalny.livejournal.com";)
log.Fatal(http.ListenAndServe(":49200", httputil.NewSingleHostReverseProxy(targetUrl)))
}
2. On a proxyHost (AWS instance in my case)
run go program:
go run censored.go
run tcpDump:
sudo tcpdump -vvvs 1024 -l -A host navalny.livejournal.com
What happened?
The HOST header points to my proxy host instead of a target one
curl -v http://54.228.241.100:49200 > /dev/null
GET / HTTP/1.1
Host: 54.228.241.100:49200
User-Agent: curl/7.30.0
Accept: */*
X-Forwarded-For: 109.188.90.98
Accept-Encoding: gzip
As a result life journal returns HTTP redirect with Location:
http://navalny.livejournal.com (the same target host)
What should have happened instead?
The host header should be set to targetHost, navalny.livejournal.com in this case.
curl -v http://54.228.241.100:49200 > /dev/null
GET / HTTP/1.1
Host: navalny.livejournal.com
User-Agent: curl/7.30.0
Accept: */*
Please provide any additional information below.
fix is simple: the req.Host should explicitly rewrite req.Host in
NewSingleHostReverseProxy
// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
// URLs to the scheme, host, and base path provided in target. If the
// target's path is "/base" and the incoming request was for "/dir",
// the target request will be for /base/dir.
func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
targetQuery := target.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
+ req.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
}
return &ReverseProxy{Director: director}
}
The text was updated successfully, but these errors were encountered:
This is working as intended.
Usually the Host is "correct" because the DNS is set to the reverse proxy, and then the
reverse proxy chooses the backends, passing along the correct hostname.
We can't change this behavior now even if we wanted to.
But NewSingleHostReverseProxy is just a tiny example function, showing how to use
ReverseProxy. You can write your own Director function if you want different behavior.
by vitaly.dvd:
The text was updated successfully, but these errors were encountered: