Update elazarl/goproxy

This commit is contained in:
Mikkel Oscar Lyderik Larsen
2017-04-05 23:29:15 +02:00
parent dbcfdb378d
commit b5ce698a68
7 changed files with 186 additions and 76 deletions

View File

@@ -10,8 +10,10 @@ import (
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"sync"
"sync/atomic"
)
@@ -23,6 +25,7 @@ const (
ConnectMitm
ConnectHijack
ConnectHTTPMitm
ConnectProxyAuthHijack
)
var (
@@ -30,6 +33,7 @@ var (
MitmConnect = &ConnectAction{Action: ConnectMitm, TLSConfig: TLSConfigFromCA(&GoproxyCa)}
HTTPMitmConnect = &ConnectAction{Action: ConnectHTTPMitm, TLSConfig: TLSConfigFromCA(&GoproxyCa)}
RejectConnect = &ConnectAction{Action: ConnectReject, TLSConfig: TLSConfigFromCA(&GoproxyCa)}
httpsRegexp = regexp.MustCompile(`^https:\/\/`)
)
type ConnectAction struct {
@@ -97,8 +101,25 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
}
ctx.Logf("Accepting CONNECT to %s", host)
proxyClient.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
go copyAndClose(ctx, targetSiteCon, proxyClient)
go copyAndClose(ctx, proxyClient, targetSiteCon)
targetTCP, targetOK := targetSiteCon.(*net.TCPConn)
proxyClientTCP, clientOK := proxyClient.(*net.TCPConn)
if targetOK && clientOK {
go copyAndClose(ctx, targetTCP, proxyClientTCP)
go copyAndClose(ctx, proxyClientTCP, targetTCP)
} else {
go func() {
var wg sync.WaitGroup
wg.Add(2)
go copyOrWarn(ctx, targetSiteCon, proxyClient, &wg)
go copyOrWarn(ctx, proxyClient, targetSiteCon, &wg)
wg.Wait()
proxyClient.Close()
targetSiteCon.Close()
}()
}
case ConnectHijack:
ctx.Logf("Hijacking CONNECT to %s", host)
proxyClient.Write([]byte("HTTP/1.0 200 OK\r\n\r\n"))
@@ -132,6 +153,7 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
httpError(proxyClient, ctx, err)
return
}
defer resp.Body.Close()
}
resp = proxy.filterResponse(resp, ctx)
if err := resp.Write(proxyClient); err != nil {
@@ -166,6 +188,7 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
clientTlsReader := bufio.NewReader(rawClientTls)
for !isEof(clientTlsReader) {
req, err := http.ReadRequest(clientTlsReader)
var ctx = &ProxyCtx{Req: req, Session: atomic.AddInt64(&proxy.sess, 1), proxy: proxy}
if err != nil && err != io.EOF {
return
}
@@ -175,7 +198,10 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
}
req.RemoteAddr = r.RemoteAddr // since we're converting the request, need to carry over the original connecting IP as well
ctx.Logf("req %v", r.Host)
req.URL, err = url.Parse("https://" + r.Host + req.URL.String())
if !httpsRegexp.MatchString(req.URL.String()) {
req.URL, err = url.Parse("https://" + r.Host + req.URL.String())
}
// Bug fix which goproxy fails to provide request
// information URL in the context when does HTTPS MITM
@@ -196,6 +222,8 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
ctx.Logf("resp %v", resp.Status)
}
resp = proxy.filterResponse(resp, ctx)
defer resp.Body.Close()
text := resp.Status
statusCode := strconv.Itoa(resp.StatusCode) + " "
if strings.HasPrefix(text, statusCode) {
@@ -234,6 +262,9 @@ func (proxy *ProxyHttpServer) handleHttps(w http.ResponseWriter, r *http.Request
}
ctx.Logf("Exiting on EOF")
}()
case ConnectProxyAuthHijack:
proxyClient.Write([]byte("HTTP/1.1 407 Proxy Authentication Required\r\n"))
todo.Hijack(r, proxyClient, ctx)
case ConnectReject:
if ctx.Resp != nil {
if err := ctx.Resp.Write(proxyClient); err != nil {
@@ -253,15 +284,20 @@ func httpError(w io.WriteCloser, ctx *ProxyCtx, err error) {
}
}
func copyAndClose(ctx *ProxyCtx, w, r net.Conn) {
connOk := true
if _, err := io.Copy(w, r); err != nil {
connOk = false
func copyOrWarn(ctx *ProxyCtx, dst io.Writer, src io.Reader, wg *sync.WaitGroup) {
if _, err := io.Copy(dst, src); err != nil {
ctx.Warnf("Error copying to client: %s", err)
}
if err := r.Close(); err != nil && connOk {
ctx.Warnf("Error closing: %s", err)
wg.Done()
}
func copyAndClose(ctx *ProxyCtx, dst, src *net.TCPConn) {
if _, err := io.Copy(dst, src); err != nil {
ctx.Warnf("Error copying to client: %s", err)
}
dst.CloseWrite()
src.CloseRead()
}
func dialerFromEnv(proxy *ProxyHttpServer) func(network, addr string) (net.Conn, error) {
@@ -305,8 +341,12 @@ func (proxy *ProxyHttpServer) NewConnectDialToProxy(https_proxy string) func(net
c.Close()
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
resp, _ := ioutil.ReadAll(resp.Body)
resp, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
c.Close()
return nil, errors.New("proxy refused connection" + string(resp))
}
@@ -339,9 +379,12 @@ func (proxy *ProxyHttpServer) NewConnectDialToProxy(https_proxy string) func(net
c.Close()
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
body, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 500))
resp.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 500))
if err != nil {
return nil, err
}
c.Close()
return nil, errors.New("proxy refused connection" + string(body))
}