From c582782dc7bb19f49710289106589b02728600eb Mon Sep 17 00:00:00 2001 From: evilsocket Date: Sun, 14 Jan 2018 15:53:52 +0100 Subject: [PATCH] refact: refactored proxy specific code in a http proxy base object, preparing for https.proxy module --- main.go | 1 + modules/http_proxy.go | 151 +++------------------------------- modules/http_proxy_base.go | 162 +++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 140 deletions(-) create mode 100644 modules/http_proxy_base.go diff --git a/main.go b/main.go index cd3a634e..69fb411d 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,7 @@ func main() { sess.Register(modules.NewSniffer(sess)) sess.Register(modules.NewHttpServer(sess)) sess.Register(modules.NewHttpProxy(sess)) + // sess.Register(modules.NewHttpsProxy(sess)) sess.Register(modules.NewRestAPI(sess)) if err = sess.Start(); err != nil { diff --git a/modules/http_proxy.go b/modules/http_proxy.go index 81bbbafd..9f1075a7 100644 --- a/modules/http_proxy.go +++ b/modules/http_proxy.go @@ -1,52 +1,18 @@ package modules import ( - "context" - "fmt" - "net/http" - "strings" - "time" - - "github.com/elazarl/goproxy" - - "github.com/evilsocket/bettercap-ng/firewall" - "github.com/evilsocket/bettercap-ng/log" "github.com/evilsocket/bettercap-ng/session" ) type HttpProxy struct { session.SessionModule - - address string - redirection *firewall.Redirection - server http.Server - proxy *goproxy.ProxyHttpServer - script *ProxyScript -} - -func (p *HttpProxy) logAction(req *http.Request, jsres *JSResponse) { - p.Session.Events.Add("http.proxy.spoofed-response", struct { - To string - Method string - Host string - Path string - Size int - }{ - strings.Split(req.RemoteAddr, ":")[0], - req.Method, - req.Host, - req.URL.Path, - len(jsres.Body), - }) + proxy *HTTPProxy } func NewHttpProxy(s *session.Session) *HttpProxy { p := &HttpProxy{ SessionModule: session.NewSessionModule("http.proxy", s), - proxy: nil, - address: "", - redirection: nil, - script: nil, + proxy: NewHTTPProxy(s), } p.AddParam(session.NewIntParameter("http.port", @@ -79,65 +45,9 @@ func NewHttpProxy(s *session.Session) *HttpProxy { return p.Stop() })) - proxy := goproxy.NewProxyHttpServer() - proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if p.doProxy(req) == true { - req.URL.Scheme = "http" - req.URL.Host = req.Host - p.proxy.ServeHTTP(w, req) - } - }) - - proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm) - proxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { - if p.script != nil { - jsres := p.script.OnRequest(req) - if jsres != nil { - p.logAction(req, jsres) - return req, jsres.ToResponse(req) - } - } - return req, nil - }) - - proxy.OnResponse().DoFunc(func(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response { - if p.script != nil { - jsres := p.script.OnResponse(res) - if jsres != nil { - p.logAction(res.Request, jsres) - return jsres.ToResponse(res.Request) - } - } - return res - }) - - p.proxy = proxy - return p } -func (p *HttpProxy) doProxy(req *http.Request) bool { - blacklist := []string{ - "localhost", - "127.0.0.1", - // p.address, - } - - if req.Host == "" { - log.Error("Got request with empty host: %v", req) - return false - } - - for _, blacklisted := range blacklist { - if strings.HasPrefix(req.Host, blacklisted) { - log.Error("Got request with blacklisted host: %s", req.Host) - return false - } - } - - return true -} - func (p *HttpProxy) Name() string { return "http.proxy" } @@ -152,52 +62,28 @@ func (p *HttpProxy) Author() string { func (p *HttpProxy) Configure() error { var err error - var http_port int - var proxy_port int + var address string + var proxyPort int + var httpPort int var scriptPath string - if err, p.address = p.StringParam("http.proxy.address"); err != nil { + if err, address = p.StringParam("http.proxy.address"); err != nil { return err } - if err, proxy_port = p.IntParam("http.proxy.port"); err != nil { + if err, proxyPort = p.IntParam("http.proxy.port"); err != nil { return err } - if err, http_port = p.IntParam("http.port"); err != nil { + if err, httpPort = p.IntParam("http.port"); err != nil { return err } if err, scriptPath = p.StringParam("http.proxy.script"); err != nil { return err - } else if scriptPath != "" { - if err, p.script = LoadProxyScript(scriptPath, p.Session); err != nil { - return err - } else { - log.Debug("Proxy script %s loaded.", scriptPath) - } } - p.server = http.Server{Addr: fmt.Sprintf("%s:%d", p.address, proxy_port), Handler: p.proxy} - - if p.Session.Firewall.IsForwardingEnabled() == false { - log.Info("Enabling forwarding.") - p.Session.Firewall.EnableForwarding(true) - } - - p.redirection = firewall.NewRedirection(p.Session.Interface.Name(), - "TCP", - http_port, - p.address, - proxy_port) - - if err := p.Session.Firewall.EnableRedirection(p.redirection, true); err != nil { - return err - } - - log.Debug("Applied redirection %s", p.redirection.String()) - - return nil + return p.proxy.Configure(address, proxyPort, httpPort, scriptPath) } func (p *HttpProxy) Start() error { @@ -208,12 +94,7 @@ func (p *HttpProxy) Start() error { } p.SetRunning(true) - go func() { - if err := p.server.ListenAndServe(); err != nil { - p.SetRunning(false) - log.Warning("%s", err) - } - }() + p.proxy.Start() return nil } @@ -224,15 +105,5 @@ func (p *HttpProxy) Stop() error { } p.SetRunning(false) - if p.redirection != nil { - log.Debug("Disabling redirection %s", p.redirection.String()) - if err := p.Session.Firewall.EnableRedirection(p.redirection, false); err != nil { - return err - } - p.redirection = nil - } - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - return p.server.Shutdown(ctx) + return p.proxy.Stop() } diff --git a/modules/http_proxy_base.go b/modules/http_proxy_base.go new file mode 100644 index 00000000..b3b5903c --- /dev/null +++ b/modules/http_proxy_base.go @@ -0,0 +1,162 @@ +package modules + +import ( + "context" + "fmt" + "net/http" + "strings" + "time" + + "github.com/evilsocket/bettercap-ng/firewall" + "github.com/evilsocket/bettercap-ng/log" + "github.com/evilsocket/bettercap-ng/session" + + "github.com/elazarl/goproxy" +) + +type HTTPProxy struct { + Address string + Server http.Server + Redirection *firewall.Redirection + Proxy *goproxy.ProxyHttpServer + Script *ProxyScript + + s *session.Session +} + +func NewHTTPProxy(s *session.Session) *HTTPProxy { + p := &HTTPProxy{ + Proxy: goproxy.NewProxyHttpServer(), + s: s, + } + + p.Proxy.NonproxyHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + if p.doProxy(req) == true { + req.URL.Scheme = "http" + req.URL.Host = req.Host + p.Proxy.ServeHTTP(w, req) + } + }) + + p.Proxy.OnRequest().HandleConnect(goproxy.AlwaysMitm) + p.Proxy.OnRequest().DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) { + if p.Script != nil { + jsres := p.Script.OnRequest(req) + if jsres != nil { + p.logAction(req, jsres) + return req, jsres.ToResponse(req) + } + } + return req, nil + }) + + p.Proxy.OnResponse().DoFunc(func(res *http.Response, ctx *goproxy.ProxyCtx) *http.Response { + if p.Script != nil { + jsres := p.Script.OnResponse(res) + if jsres != nil { + p.logAction(res.Request, jsres) + return jsres.ToResponse(res.Request) + } + } + return res + }) + + return p +} + +func (p *HTTPProxy) logAction(req *http.Request, jsres *JSResponse) { + p.s.Events.Add("http.proxy.spoofed-response", struct { + To string + Method string + Host string + Path string + Size int + }{ + strings.Split(req.RemoteAddr, ":")[0], + req.Method, + req.Host, + req.URL.Path, + len(jsres.Body), + }) +} + +func (p *HTTPProxy) doProxy(req *http.Request) bool { + blacklist := []string{ + "localhost", + "127.0.0.1", + } + + if req.Host == "" { + log.Error("Got request with empty host: %v", req) + return false + } + + for _, blacklisted := range blacklist { + if strings.HasPrefix(req.Host, blacklisted) { + log.Error("Got request with blacklisted host: %s", req.Host) + return false + } + } + + return true +} + +func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scriptPath string) error { + var err error + + p.Address = address + + if scriptPath != "" { + if err, p.Script = LoadProxyScript(scriptPath, p.s); err != nil { + return err + } else { + log.Debug("Proxy script %s loaded.", scriptPath) + } + } + + p.Server = http.Server{ + Addr: fmt.Sprintf("%s:%d", p.Address, proxyPort), + Handler: p.Proxy, + } + + if p.s.Firewall.IsForwardingEnabled() == false { + log.Info("Enabling forwarding.") + p.s.Firewall.EnableForwarding(true) + } + + p.Redirection = firewall.NewRedirection(p.s.Interface.Name(), + "TCP", + httpPort, + p.Address, + proxyPort) + + if err := p.s.Firewall.EnableRedirection(p.Redirection, true); err != nil { + return err + } + + log.Debug("Applied redirection %s", p.Redirection.String()) + + return nil +} + +func (p *HTTPProxy) Start() { + go func() { + if err := p.Server.ListenAndServe(); err != nil { + log.Warning("%s", err) + } + }() +} + +func (p *HTTPProxy) Stop() error { + if p.Redirection != nil { + log.Debug("Disabling redirection %s", p.Redirection.String()) + if err := p.s.Firewall.EnableRedirection(p.Redirection, false); err != nil { + return err + } + p.Redirection = nil + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + return p.Server.Shutdown(ctx) +}