any_proxy.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package any_proxy
  2. import (
  3. "fmt"
  4. "github.com/bettercap/bettercap/firewall"
  5. "github.com/bettercap/bettercap/session"
  6. "github.com/evilsocket/islazy/str"
  7. "strconv"
  8. "strings"
  9. )
  10. type AnyProxy struct {
  11. session.SessionModule
  12. // not using map[int]*firewall.Redirection to preserve order
  13. ports []int
  14. redirections []*firewall.Redirection
  15. }
  16. func NewAnyProxy(s *session.Session) *AnyProxy {
  17. mod := &AnyProxy{
  18. SessionModule: session.NewSessionModule("any.proxy", s),
  19. }
  20. mod.AddParam(session.NewStringParameter("any.proxy.iface",
  21. session.ParamIfaceName,
  22. "",
  23. "Interface to redirect packets from."))
  24. mod.AddParam(session.NewStringParameter("any.proxy.protocol",
  25. "TCP",
  26. "(TCP|UDP)",
  27. "Proxy protocol."))
  28. mod.AddParam(session.NewStringParameter("any.proxy.src_port",
  29. "80",
  30. "",
  31. "Remote port to redirect when the module is activated, "+
  32. "also supported a comma separated list of ports and/or port-ranges."))
  33. mod.AddParam(session.NewStringParameter("any.proxy.src_address",
  34. "",
  35. "",
  36. "Leave empty to intercept any source address."))
  37. mod.AddParam(session.NewStringParameter("any.proxy.dst_address",
  38. session.ParamIfaceAddress,
  39. "",
  40. "Address where the proxy is listening."))
  41. mod.AddParam(session.NewIntParameter("any.proxy.dst_port",
  42. "8080",
  43. "Port where the proxy is listening."))
  44. mod.AddHandler(session.NewModuleHandler("any.proxy on", "",
  45. "Start the custom proxy redirection.",
  46. func(args []string) error {
  47. return mod.Start()
  48. }))
  49. mod.AddHandler(session.NewModuleHandler("any.proxy off", "",
  50. "Stop the custom proxy redirection.",
  51. func(args []string) error {
  52. return mod.Stop()
  53. }))
  54. return mod
  55. }
  56. func (mod *AnyProxy) Name() string {
  57. return "any.proxy"
  58. }
  59. func (mod *AnyProxy) Description() string {
  60. return "A firewall redirection to any custom proxy."
  61. }
  62. func (mod *AnyProxy) Author() string {
  63. return "Simone Margaritelli <evilsocket@gmail.com>"
  64. }
  65. func (mod *AnyProxy) Configure() error {
  66. var err error
  67. var srcPorts string
  68. var dstPort int
  69. var iface string
  70. var protocol string
  71. var srcAddress string
  72. var dstAddress string
  73. if mod.Running() {
  74. return session.ErrAlreadyStarted(mod.Name())
  75. } else if err, iface = mod.StringParam("any.proxy.iface"); err != nil {
  76. return err
  77. } else if err, protocol = mod.StringParam("any.proxy.protocol"); err != nil {
  78. return err
  79. } else if err, dstPort = mod.IntParam("any.proxy.dst_port"); err != nil {
  80. return err
  81. } else if err, srcAddress = mod.StringParam("any.proxy.src_address"); err != nil {
  82. return err
  83. } else if err, dstAddress = mod.StringParam("any.proxy.dst_address"); err != nil {
  84. return err
  85. }
  86. if err, srcPorts = mod.StringParam("any.proxy.src_port"); err != nil {
  87. return err
  88. } else {
  89. var ports []int
  90. // srcPorts can be a single port, a list of ports or a list of ranges, or a mix.
  91. for _, token := range str.Comma(str.Trim(srcPorts)) {
  92. if p, err := strconv.Atoi(token); err == nil {
  93. // simple case, integer port
  94. ports = append(ports, p)
  95. } else if strings.Contains(token, "-") {
  96. // port range
  97. if parts := strings.Split(token, "-"); len(parts) == 2 {
  98. if from, err := strconv.Atoi(str.Trim(parts[0])); err != nil {
  99. return fmt.Errorf("invalid start port %s: %s", parts[0], err)
  100. } else if from < 1 || from > 65535 {
  101. return fmt.Errorf("port %s out of valid range", parts[0])
  102. } else if to, err := strconv.Atoi(str.Trim(parts[1])); err != nil {
  103. return fmt.Errorf("invalid end port %s: %s", parts[1], err)
  104. } else if to < 1 || to > 65535 {
  105. return fmt.Errorf("port %s out of valid range", parts[1])
  106. } else if from > to {
  107. return fmt.Errorf("start port should be lower than end port")
  108. } else {
  109. for p := from; p <= to; p++ {
  110. ports = append(ports, p)
  111. }
  112. }
  113. } else {
  114. return fmt.Errorf("can't parse '%s' as range", token)
  115. }
  116. } else {
  117. return fmt.Errorf("can't parse '%s' as port or range", token)
  118. }
  119. }
  120. // after parsing and validation, create a redirection per source port
  121. mod.ports = ports
  122. mod.redirections = nil
  123. for _, port := range mod.ports {
  124. redir := firewall.NewRedirection(iface,
  125. protocol,
  126. port,
  127. dstAddress,
  128. dstPort)
  129. if srcAddress != "" {
  130. redir.SrcAddress = srcAddress
  131. }
  132. mod.redirections = append(mod.redirections, redir)
  133. }
  134. }
  135. if !mod.Session.Firewall.IsForwardingEnabled() {
  136. mod.Info("Enabling forwarding.")
  137. mod.Session.Firewall.EnableForwarding(true)
  138. }
  139. for _, redir := range mod.redirections {
  140. if err := mod.Session.Firewall.EnableRedirection(redir, true); err != nil {
  141. return err
  142. }
  143. mod.Info("applied redirection %s", redir.String())
  144. }
  145. return nil
  146. }
  147. func (mod *AnyProxy) Start() error {
  148. if err := mod.Configure(); err != nil {
  149. return err
  150. }
  151. return mod.SetRunning(true, func() {})
  152. }
  153. func (mod *AnyProxy) Stop() error {
  154. for _, redir := range mod.redirections {
  155. mod.Info("disabling redirection %s", redir.String())
  156. if err := mod.Session.Firewall.EnableRedirection(redir, false); err != nil {
  157. return err
  158. }
  159. }
  160. return mod.SetRunning(false, func() {})
  161. }