diff --git a/modules/any_proxy/any_proxy.go b/modules/any_proxy/any_proxy.go index a8977d27..4f917f3c 100644 --- a/modules/any_proxy/any_proxy.go +++ b/modules/any_proxy/any_proxy.go @@ -1,13 +1,19 @@ package any_proxy import ( + "fmt" "github.com/bettercap/bettercap/firewall" "github.com/bettercap/bettercap/session" + "github.com/evilsocket/islazy/str" + "strconv" + "strings" ) type AnyProxy struct { session.SessionModule - Redirection *firewall.Redirection + // not using map[int]*firewall.Redirection to preserve order + ports []int + redirections []*firewall.Redirection } func NewAnyProxy(s *session.Session) *AnyProxy { @@ -25,9 +31,11 @@ func NewAnyProxy(s *session.Session) *AnyProxy { "(TCP|UDP)", "Proxy protocol.")) - mod.AddParam(session.NewIntParameter("any.proxy.src_port", + mod.AddParam(session.NewStringParameter("any.proxy.src_port", "80", - "Remote port to redirect when the module is activated.")) + "", + "Remote port to redirect when the module is activated, "+ + "also supported a comma separated list of ports and/or port-ranges.")) mod.AddParam(session.NewStringParameter("any.proxy.src_address", "", @@ -72,7 +80,7 @@ func (mod *AnyProxy) Author() string { func (mod *AnyProxy) Configure() error { var err error - var srcPort int + var srcPorts string var dstPort int var iface string var protocol string @@ -85,8 +93,6 @@ func (mod *AnyProxy) Configure() error { return err } else if err, protocol = mod.StringParam("any.proxy.protocol"); err != nil { return err - } else if err, srcPort = mod.IntParam("any.proxy.src_port"); err != nil { - return err } else if err, dstPort = mod.IntParam("any.proxy.dst_port"); err != nil { return err } else if err, srcAddress = mod.StringParam("any.proxy.src_address"); err != nil { @@ -95,27 +101,71 @@ func (mod *AnyProxy) Configure() error { return err } + if err, srcPorts = mod.StringParam("any.proxy.src_port"); err != nil { + return err + } else { + var ports []int + // srcPorts can be a single port, a list of ports or a list of ranges, or a mix. + for _, token := range str.Comma(str.Trim(srcPorts)) { + if p, err := strconv.Atoi(token); err == nil { + // simple case, integer port + ports = append(ports, p) + } else if strings.Contains(token, "-") { + // port range + if parts := strings.Split(token, "-"); len(parts) == 2 { + if from, err := strconv.Atoi(str.Trim(parts[0])); err != nil { + return fmt.Errorf("invalid start port %s: %s", parts[0], err) + } else if from < 1 || from > 65535 { + return fmt.Errorf("port %s out of valid range", parts[0]) + } else if to, err := strconv.Atoi(str.Trim(parts[1])); err != nil { + return fmt.Errorf("invalid end port %s: %s", parts[1], err) + } else if to < 1 || to > 65535 { + return fmt.Errorf("port %s out of valid range", parts[1]) + } else if from > to { + return fmt.Errorf("start port should be lower than end port") + } else { + for p := from; p <= to; p++ { + ports = append(ports, p) + } + } + } else { + return fmt.Errorf("can't parse '%s' as range", token) + } + } else { + return fmt.Errorf("can't parse '%s' as port or range", token) + } + } + + // after parsing and validation, create a redirection per source port + mod.ports = ports + mod.redirections = nil + for _, port := range mod.ports { + redir := firewall.NewRedirection(iface, + protocol, + port, + dstAddress, + dstPort) + + if srcAddress != "" { + redir.SrcAddress = srcAddress + } + + mod.redirections = append(mod.redirections, redir) + } + } + if !mod.Session.Firewall.IsForwardingEnabled() { mod.Info("Enabling forwarding.") mod.Session.Firewall.EnableForwarding(true) } - mod.Redirection = firewall.NewRedirection(iface, - protocol, - srcPort, - dstAddress, - dstPort) - - if srcAddress != "" { - mod.Redirection.SrcAddress = srcAddress + for _, redir := range mod.redirections { + if err := mod.Session.Firewall.EnableRedirection(redir, true); err != nil { + return err + } + mod.Info("applied redirection %s", redir.String()) } - if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, true); err != nil { - return err - } - - mod.Info("Applied redirection %s", mod.Redirection.String()) - return nil } @@ -128,13 +178,11 @@ func (mod *AnyProxy) Start() error { } func (mod *AnyProxy) Stop() error { - if mod.Redirection != nil { - mod.Info("Disabling redirection %s", mod.Redirection.String()) - if err := mod.Session.Firewall.EnableRedirection(mod.Redirection, false); err != nil { + for _, redir := range mod.redirections { + mod.Info("disabling redirection %s", redir.String()) + if err := mod.Session.Firewall.EnableRedirection(redir, false); err != nil { return err } - mod.Redirection = nil } - return mod.SetRunning(false, func() {}) }