From 36b61e058077c6374a74d9b73c5f0b37e3160ffc Mon Sep 17 00:00:00 2001 From: "rui.zheng" Date: Wed, 2 Aug 2017 23:39:32 +0800 Subject: [PATCH] add http request forwarding support for http handler --- gost/http.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++----- gost/http2.go | 6 +++--- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/gost/http.go b/gost/http.go index df41f22..24eb067 100644 --- a/gost/http.go +++ b/gost/http.go @@ -9,6 +9,7 @@ import ( "net/http/httputil" "net/url" "strings" + "time" "github.com/go-log/log" ) @@ -118,13 +119,14 @@ func (h *httpHandler) Handle(conn net.Conn) { } req.Header.Del("Proxy-Authorization") + req.Header.Del("Proxy-Connection") // forward http request - //lastNode := s.Base.Chain.lastNode - //if lastNode != nil && lastNode.Transport == "" && (lastNode.Protocol == "http" || lastNode.Protocol == "") { - // s.forwardRequest(req) - // return - //} + lastNode := h.options.Chain.LastNode() + if req.Method != http.MethodConnect && lastNode.Protocol == "http" { + h.forwardRequest(conn, req) + return + } // if !s.Base.Node.Can("tcp", req.Host) { // glog.Errorf("Unauthorized to tcp connect to %s", req.Host) @@ -170,6 +172,48 @@ func (h *httpHandler) Handle(conn net.Conn) { log.Logf("[http] %s >-< %s", conn.RemoteAddr(), req.Host) } +func (h *httpHandler) forwardRequest(conn net.Conn, req *http.Request) { + if h.options.Chain.IsEmpty() { + return + } + lastNode := h.options.Chain.LastNode() + + cc, err := h.options.Chain.Conn() + if err != nil { + log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), lastNode.Addr, err) + + b := []byte("HTTP/1.1 503 Service unavailable\r\n" + + "Proxy-Agent: gost/" + Version + "\r\n\r\n") + if Debug { + log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), lastNode.Addr, string(b)) + } + conn.Write(b) + return + } + defer cc.Close() + + if lastNode.User != nil { + s := lastNode.User.String() + if _, set := lastNode.User.Password(); !set { + s += ":" + } + req.Header.Set("Proxy-Authorization", + "Basic "+base64.StdEncoding.EncodeToString([]byte(s))) + } + + cc.SetWriteDeadline(time.Now().Add(WriteTimeout)) + if err = req.WriteProxy(cc); err != nil { + log.Logf("[http] %s -> %s : %s", conn.RemoteAddr(), req.Host, err) + return + } + cc.SetWriteDeadline(time.Time{}) + + log.Logf("[http] %s <-> %s", conn.RemoteAddr(), req.Host) + transport(conn, cc) + log.Logf("[http] %s >-< %s", conn.RemoteAddr(), req.Host) + return +} + func basicProxyAuth(proxyAuth string) (username, password string, ok bool) { if proxyAuth == "" { return diff --git a/gost/http2.go b/gost/http2.go index f1b3f64..763e6cb 100644 --- a/gost/http2.go +++ b/gost/http2.go @@ -318,8 +318,6 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { } defer cc.Close() - log.Logf("[http2] %s <-> %s", r.RemoteAddr, target) - if r.Method == http.MethodConnect { w.WriteHeader(http.StatusOK) if fw, ok := w.(http.Flusher); ok { @@ -337,12 +335,13 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { } defer conn.Close() - log.Logf("[http2] %s -> %s : downgrade to HTTP/1.1", r.RemoteAddr, target) + log.Logf("[http2] %s <-> %s : downgrade to HTTP/1.1", r.RemoteAddr, target) transport(conn, cc) log.Logf("[http2] %s >-< %s", r.RemoteAddr, target) return } + log.Logf("[http2] %s <-> %s", r.RemoteAddr, target) errc := make(chan error, 2) go func() { _, err := io.Copy(cc, r.Body) @@ -361,6 +360,7 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { return } + log.Logf("[http2] %s <-> %s", r.RemoteAddr, target) if err = r.Write(cc); err != nil { log.Logf("[http2] %s -> %s : %s", r.RemoteAddr, target, err) return