mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 21:13:18 -07:00
refact: refactored proxy specific code in a http proxy base object, preparing for https.proxy module
This commit is contained in:
parent
d14bd6fc1c
commit
c582782dc7
3 changed files with 174 additions and 140 deletions
1
main.go
1
main.go
|
@ -31,6 +31,7 @@ func main() {
|
||||||
sess.Register(modules.NewSniffer(sess))
|
sess.Register(modules.NewSniffer(sess))
|
||||||
sess.Register(modules.NewHttpServer(sess))
|
sess.Register(modules.NewHttpServer(sess))
|
||||||
sess.Register(modules.NewHttpProxy(sess))
|
sess.Register(modules.NewHttpProxy(sess))
|
||||||
|
// sess.Register(modules.NewHttpsProxy(sess))
|
||||||
sess.Register(modules.NewRestAPI(sess))
|
sess.Register(modules.NewRestAPI(sess))
|
||||||
|
|
||||||
if err = sess.Start(); err != nil {
|
if err = sess.Start(); err != nil {
|
||||||
|
|
|
@ -1,52 +1,18 @@
|
||||||
package modules
|
package modules
|
||||||
|
|
||||||
import (
|
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"
|
"github.com/evilsocket/bettercap-ng/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpProxy struct {
|
type HttpProxy struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
|
proxy *HTTPProxy
|
||||||
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),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpProxy(s *session.Session) *HttpProxy {
|
func NewHttpProxy(s *session.Session) *HttpProxy {
|
||||||
p := &HttpProxy{
|
p := &HttpProxy{
|
||||||
SessionModule: session.NewSessionModule("http.proxy", s),
|
SessionModule: session.NewSessionModule("http.proxy", s),
|
||||||
proxy: nil,
|
proxy: NewHTTPProxy(s),
|
||||||
address: "",
|
|
||||||
redirection: nil,
|
|
||||||
script: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.AddParam(session.NewIntParameter("http.port",
|
p.AddParam(session.NewIntParameter("http.port",
|
||||||
|
@ -79,65 +45,9 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
|
||||||
return p.Stop()
|
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
|
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 {
|
func (p *HttpProxy) Name() string {
|
||||||
return "http.proxy"
|
return "http.proxy"
|
||||||
}
|
}
|
||||||
|
@ -152,52 +62,28 @@ func (p *HttpProxy) Author() string {
|
||||||
|
|
||||||
func (p *HttpProxy) Configure() error {
|
func (p *HttpProxy) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var http_port int
|
var address string
|
||||||
var proxy_port int
|
var proxyPort int
|
||||||
|
var httpPort int
|
||||||
var scriptPath string
|
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
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, http_port = p.IntParam("http.port"); err != nil {
|
if err, httpPort = p.IntParam("http.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, scriptPath = p.StringParam("http.proxy.script"); err != nil {
|
if err, scriptPath = p.StringParam("http.proxy.script"); err != nil {
|
||||||
return err
|
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}
|
return p.proxy.Configure(address, proxyPort, httpPort, scriptPath)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HttpProxy) Start() error {
|
func (p *HttpProxy) Start() error {
|
||||||
|
@ -208,12 +94,7 @@ func (p *HttpProxy) Start() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.SetRunning(true)
|
p.SetRunning(true)
|
||||||
go func() {
|
p.proxy.Start()
|
||||||
if err := p.server.ListenAndServe(); err != nil {
|
|
||||||
p.SetRunning(false)
|
|
||||||
log.Warning("%s", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -224,15 +105,5 @@ func (p *HttpProxy) Stop() error {
|
||||||
}
|
}
|
||||||
p.SetRunning(false)
|
p.SetRunning(false)
|
||||||
|
|
||||||
if p.redirection != nil {
|
return p.proxy.Stop()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
162
modules/http_proxy_base.go
Normal file
162
modules/http_proxy_base.go
Normal file
|
@ -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)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue