mirror of
https://github.com/bettercap/bettercap
synced 2025-08-22 22:34:22 -07:00
Merge b1d3e36960
into 9e393e5bf4
This commit is contained in:
commit
6854e0eaf4
11 changed files with 283 additions and 20 deletions
|
@ -74,7 +74,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
|
||||||
action, "PREROUTING",
|
action, "PREROUTING",
|
||||||
"-i", r.Interface,
|
"-i", r.Interface,
|
||||||
"-p", r.Protocol,
|
"-p", r.Protocol,
|
||||||
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
"--dport", fmt.Sprintf("%s", r.SrcPort),
|
||||||
"-j", "DNAT",
|
"-j", "DNAT",
|
||||||
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []
|
||||||
"-i", r.Interface,
|
"-i", r.Interface,
|
||||||
"-p", r.Protocol,
|
"-p", r.Protocol,
|
||||||
"-d", r.SrcAddress,
|
"-d", r.SrcAddress,
|
||||||
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
"--dport", fmt.Sprintf("%s", r.SrcPort),
|
||||||
"-j", "DNAT",
|
"-j", "DNAT",
|
||||||
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
package firewall
|
package firewall
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
type Redirection struct {
|
type Redirection struct {
|
||||||
Interface string
|
Interface string
|
||||||
Protocol string
|
Protocol string
|
||||||
SrcAddress string
|
SrcAddress string
|
||||||
SrcPort int
|
SrcPort string
|
||||||
DstAddress string
|
DstAddress string
|
||||||
DstPort int
|
DstPort int
|
||||||
|
MultiPort bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRedirection(iface string, proto string, port_from int, addr_to string, port_to int) *Redirection {
|
func NewRedirection(iface string, proto string, port_from string, addr_to string, port_to int) *Redirection {
|
||||||
|
_, err := strconv.Atoi(port_from)
|
||||||
|
multi_port := false
|
||||||
|
if err != nil {
|
||||||
|
multi_port = true
|
||||||
|
} else {
|
||||||
|
multi_port = false
|
||||||
|
}
|
||||||
return &Redirection{
|
return &Redirection{
|
||||||
Interface: iface,
|
Interface: iface,
|
||||||
Protocol: proto,
|
Protocol: proto,
|
||||||
|
@ -19,6 +30,7 @@ func NewRedirection(iface string, proto string, port_from int, addr_to string, p
|
||||||
SrcPort: port_from,
|
SrcPort: port_from,
|
||||||
DstAddress: addr_to,
|
DstAddress: addr_to,
|
||||||
DstPort: port_to,
|
DstPort: port_to,
|
||||||
|
MultiPort: multi_port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
main.go
1
main.go
|
@ -45,6 +45,7 @@ func main() {
|
||||||
sess.Register(modules.NewTcpProxy(sess))
|
sess.Register(modules.NewTcpProxy(sess))
|
||||||
sess.Register(modules.NewHttpProxy(sess))
|
sess.Register(modules.NewHttpProxy(sess))
|
||||||
sess.Register(modules.NewHttpsProxy(sess))
|
sess.Register(modules.NewHttpsProxy(sess))
|
||||||
|
sess.Register(modules.NewCustomHttpProxy(sess))
|
||||||
sess.Register(modules.NewHttpServer(sess))
|
sess.Register(modules.NewHttpServer(sess))
|
||||||
sess.Register(modules.NewRestAPI(sess))
|
sess.Register(modules.NewRestAPI(sess))
|
||||||
sess.Register(modules.NewWOL(sess))
|
sess.Register(modules.NewWOL(sess))
|
||||||
|
|
99
modules/custom_http_proxy.go
Normal file
99
modules/custom_http_proxy.go
Normal 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.NewStringParameter("custom.http.port",
|
||||||
|
"80", session.PortsValidator,
|
||||||
|
"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 string
|
||||||
|
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.StringParam("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()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
114
modules/custom_proxy_base.go
Normal file
114
modules/custom_proxy_base.go
Normal 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 string, 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
|
||||||
|
}
|
|
@ -15,8 +15,8 @@ func NewHttpProxy(s *session.Session) *HttpProxy {
|
||||||
proxy: NewHTTPProxy(s),
|
proxy: NewHTTPProxy(s),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.AddParam(session.NewIntParameter("http.port",
|
p.AddParam(session.NewStringParameter("http.port",
|
||||||
"80",
|
"80", session.PortsValidator,
|
||||||
"HTTP port to redirect when the proxy is activated."))
|
"HTTP port to redirect when the proxy is activated."))
|
||||||
|
|
||||||
p.AddParam(session.NewStringParameter("http.proxy.address",
|
p.AddParam(session.NewStringParameter("http.proxy.address",
|
||||||
|
@ -68,7 +68,7 @@ func (p *HttpProxy) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var address string
|
var address string
|
||||||
var proxyPort int
|
var proxyPort int
|
||||||
var httpPort int
|
var httpPort string
|
||||||
var scriptPath string
|
var scriptPath string
|
||||||
var stripSSL bool
|
var stripSSL bool
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ func (p *HttpProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, proxyPort = p.IntParam("http.proxy.port"); err != nil {
|
} else if err, proxyPort = p.IntParam("http.proxy.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, httpPort = p.IntParam("http.port"); err != nil {
|
} else if err, httpPort = p.StringParam("http.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil {
|
} else if err, scriptPath = p.StringParam("http.proxy.script"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -106,7 +106,7 @@ func (p *HTTPProxy) doProxy(req *http.Request) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scriptPath string, stripSSL bool) error {
|
func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort string, scriptPath string, stripSSL bool) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
p.stripper.Enable(stripSSL)
|
p.stripper.Enable(stripSSL)
|
||||||
|
@ -141,7 +141,6 @@ func (p *HTTPProxy) Configure(address string, proxyPort int, httpPort int, scrip
|
||||||
if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil {
|
if err := p.sess.Firewall.EnableRedirection(p.Redirection, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("Applied redirection %s", p.Redirection.String())
|
log.Debug("Applied redirection %s", p.Redirection.String())
|
||||||
|
|
||||||
p.sess.UnkCmdCallback = func(cmd string) bool {
|
p.sess.UnkCmdCallback = func(cmd string) bool {
|
||||||
|
@ -187,7 +186,7 @@ func TLSConfigFromCA(ca *tls.Certificate) func(host string, ctx *goproxy.ProxyCt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort int, scriptPath string, certFile string, keyFile string, stripSSL bool) (err error) {
|
func (p *HTTPProxy) ConfigureTLS(address string, proxyPort int, httpPort string, scriptPath string, certFile string, keyFile string, stripSSL bool) (err error) {
|
||||||
if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil {
|
if p.Configure(address, proxyPort, httpPort, scriptPath, stripSSL); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
37
modules/http_proxy_script_test.go
Normal file
37
modules/http_proxy_script_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,8 +18,8 @@ func NewHttpsProxy(s *session.Session) *HttpsProxy {
|
||||||
proxy: NewHTTPProxy(s),
|
proxy: NewHTTPProxy(s),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.AddParam(session.NewIntParameter("https.port",
|
p.AddParam(session.NewStringParameter("https.port",
|
||||||
"443",
|
"443", session.PortsValidator,
|
||||||
"HTTPS port to redirect when the proxy is activated."))
|
"HTTPS port to redirect when the proxy is activated."))
|
||||||
|
|
||||||
p.AddParam(session.NewStringParameter("https.proxy.address",
|
p.AddParam(session.NewStringParameter("https.proxy.address",
|
||||||
|
@ -81,7 +81,7 @@ func (p *HttpsProxy) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var address string
|
var address string
|
||||||
var proxyPort int
|
var proxyPort int
|
||||||
var httpPort int
|
var httpsPort string
|
||||||
var scriptPath string
|
var scriptPath string
|
||||||
var certFile string
|
var certFile string
|
||||||
var keyFile string
|
var keyFile string
|
||||||
|
@ -93,7 +93,7 @@ func (p *HttpsProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil {
|
} else if err, proxyPort = p.IntParam("https.proxy.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, httpPort = p.IntParam("https.port"); err != nil {
|
} else if err, httpsPort = p.StringParam("https.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil {
|
} else if err, stripSSL = p.BoolParam("https.proxy.sslstrip"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -120,7 +120,7 @@ func (p *HttpsProxy) Configure() error {
|
||||||
log.Info("Loading proxy certification authority TLS certificate from %s", certFile)
|
log.Info("Loading proxy certification authority TLS certificate from %s", certFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.proxy.ConfigureTLS(address, proxyPort, httpPort, scriptPath, certFile, keyFile, stripSSL)
|
return p.proxy.ConfigureTLS(address, proxyPort, httpsPort, scriptPath, certFile, keyFile, stripSSL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *HttpsProxy) Start() error {
|
func (p *HttpsProxy) Start() error {
|
||||||
|
|
|
@ -87,7 +87,7 @@ func (p *TcpProxy) Author() string {
|
||||||
|
|
||||||
func (p *TcpProxy) Configure() error {
|
func (p *TcpProxy) Configure() error {
|
||||||
var err error
|
var err error
|
||||||
var port int
|
var port string
|
||||||
var proxyPort int
|
var proxyPort int
|
||||||
var address string
|
var address string
|
||||||
var proxyAddress string
|
var proxyAddress string
|
||||||
|
@ -103,7 +103,7 @@ func (p *TcpProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if err, proxyPort = p.IntParam("tcp.proxy.port"); err != nil {
|
} else if err, proxyPort = p.IntParam("tcp.proxy.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, port = p.IntParam("tcp.port"); err != nil {
|
} else if err, port = p.StringParam("tcp.port"); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err, tunnelAddress = p.StringParam("tcp.tunnel.address"); err != nil {
|
} else if err, tunnelAddress = p.StringParam("tcp.tunnel.address"); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -113,7 +113,7 @@ func (p *TcpProxy) Configure() error {
|
||||||
return err
|
return err
|
||||||
} else if p.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil {
|
} else if p.localAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", proxyAddress, proxyPort)); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if p.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", address, port)); err != nil {
|
} else if p.remoteAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", address, port)); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if p.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil {
|
} else if p.tunnelAddr, err = net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", tunnelAddress, tunnelPort)); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`
|
const IPv4Validator = `^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$`
|
||||||
|
const PortsValidator = `^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+[,]+)*(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+)$|^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+):(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])+)$`
|
||||||
|
|
||||||
type ModuleHandler struct {
|
type ModuleHandler struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue