Support custom proxy

This commit is contained in:
gorgiaxx 2018-07-10 16:55:11 +08:00
commit eedf0b66af
3 changed files with 250 additions and 0 deletions

View file

@ -0,0 +1,99 @@
package modules
import (
"github.com/bettercap/bettercap/session"
)
type CustomHttpProxy struct {
session.SessionModule
proxy *CustomProxy
}
func NewCustomHttpProxy(s *session.Session) *CustomHttpProxy {
p := &CustomHttpProxy{
SessionModule: session.NewSessionModule("custom.http.proxy", s),
proxy: NewCustomProxy(s),
}
p.AddParam(session.NewIntParameter("custom.http.port",
"80",
"HTTP port to redirect when the proxy is activated."))
p.AddParam(session.NewStringParameter("custom.http.proxy.address",
session.ParamIfaceAddress,
session.IPv4Validator,
"Address to bind the Custom HTTP proxy to."))
p.AddParam(session.NewIntParameter("custom.http.proxy.port",
"8080",
"Port to bind the Custom HTTP proxy to."))
p.AddParam(session.NewBoolParameter("custom.http.proxy.sslstrip",
"false",
"Enable or disable SSL stripping."))
p.AddHandler(session.NewModuleHandler("custom.http.proxy on", "",
"Start Custom HTTP proxy.",
func(args []string) error {
return p.Start()
}))
p.AddHandler(session.NewModuleHandler("custom.http.proxy off", "",
"Stop Custom HTTP proxy.",
func(args []string) error {
return p.Stop()
}))
return p
}
func (p *CustomHttpProxy) Name() string {
return "custom.http.proxy"
}
func (p *CustomHttpProxy) Description() string {
return "Use a custom HTTP proxy server instead of the builtin one."
}
func (p *CustomHttpProxy) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>"
}
func (p *CustomHttpProxy) Configure() error {
var err error
var address string
var proxyPort int
var httpPort int
var stripSSL bool
if p.Running() {
return session.ErrAlreadyStarted
} else if err, address = p.StringParam("custom.http.proxy.address"); err != nil {
return err
} else if err, proxyPort = p.IntParam("custom.http.proxy.port"); err != nil {
return err
} else if err, httpPort = p.IntParam("custom.http.port"); err != nil {
return err
} else if err, stripSSL = p.BoolParam("custom.http.proxy.sslstrip"); err != nil {
return err
}
return p.proxy.Configure(address, proxyPort, httpPort, stripSSL)
}
func (p *CustomHttpProxy) Start() error {
if err := p.Configure(); err != nil {
return err
}
return p.SetRunning(true, func() {
p.proxy.Start()
})
}
func (p *CustomHttpProxy) Stop() error {
return p.SetRunning(false, func() {
p.proxy.Stop()
})
}

View file

@ -0,0 +1,114 @@
package modules
import (
"net/http"
"github.com/bettercap/bettercap/firewall"
"net"
"github.com/bettercap/bettercap/session"
"strings"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/core"
)
type CustomProxy struct {
Name string
Address string
Redirection *firewall.Redirection
isTLS bool
isRunning bool
stripper *SSLStripper
sniListener net.Listener
sess *session.Session
}
func NewCustomProxy(s *session.Session) *CustomProxy {
p := &CustomProxy{
Name: "custom.proxy",
sess: s,
stripper: NewSSLStripper(s, false),
}
return p
}
func (p *CustomProxy) 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.Split(req.Host, ":")[0] == blacklisted {
log.Error("Got request with blacklisted host: %s", req.Host)
return false
}
}
return true
}
func (p *CustomProxy) stripPort(s string) string {
ix := strings.IndexRune(s, ':')
if ix == -1 {
return s
}
return s[:ix]
}
func (p *CustomProxy) Configure(proxyAddress string, proxyPort int, srcPort int, stripSSL bool) error {
p.stripper.Enable(stripSSL)
p.Address = proxyAddress
if !p.sess.Firewall.IsForwardingEnabled() {
log.Info("Enabling forwarding.")
p.sess.Firewall.EnableForwarding(true)
}
p.Redirection = firewall.NewRedirection(p.sess.Interface.Name(),
"TCP",
srcPort,
p.Address,
proxyPort)
if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil {
return err
}
log.Debug("Applied redirection %s", p.Redirection.String())
return nil
}
func (p *CustomProxy) Start() {
go func() {
var err error
strip := core.Yellow("enabled")
if !p.stripper.Enabled() {
strip = core.Dim("disabled")
}
log.Info("%s started on %s (sslstrip %s)", core.Green(p.Name), p.Address, strip)
if err != nil && err.Error() != "http: Server closed" {
log.Fatal("%s", err)
}
}()
}
func (p *CustomProxy) Stop() error {
if p.Redirection != nil {
log.Debug("Disabling redirection %s", p.Redirection.String())
if err := p.sess.Firewall.EnableRedirection(p.Redirection, false); err != nil {
return err
}
p.Redirection = nil
}
return nil
}

View file

@ -0,0 +1,37 @@
package modules
import (
"net/http"
"testing"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
)
func getScript(src string) *HttpProxyScript {
sess := session.Session{}
sess.Env = session.NewEnvironment(&sess, "")
err, script := LoadHttpProxyScriptSource("", src, &sess)
if err != nil {
log.Fatal("%s", err)
}
return script
}
func getRequest() *http.Request {
req, err := http.NewRequest("GET", "http://www.google.com/", nil)
if err != nil {
log.Fatal("%s", err)
}
return req
}
func BenchmarkOnRequest(b *testing.B) {
script := getScript("function onRequest(req,res){}")
req := getRequest()
for n := 0; n < b.N; n++ {
script.OnRequest(req)
}
}