new: splitted http.server and https.server in order to be able to use both from a single instance (closes #433)

This commit is contained in:
evilsocket 2019-02-05 11:15:08 +01:00
parent 402bf77a31
commit 23f340d8eb
No known key found for this signature in database
GPG key ID: 1564D7F30393A456
3 changed files with 178 additions and 65 deletions

View file

@ -52,6 +52,7 @@ func main() {
sess.Register(modules.NewHttpProxy(sess)) sess.Register(modules.NewHttpProxy(sess))
sess.Register(modules.NewHttpsProxy(sess)) sess.Register(modules.NewHttpsProxy(sess))
sess.Register(modules.NewHttpServer(sess)) sess.Register(modules.NewHttpServer(sess))
sess.Register(modules.NewHttpsServer(sess))
sess.Register(modules.NewRestAPI(sess)) sess.Register(modules.NewRestAPI(sess))
sess.Register(modules.NewWOL(sess)) sess.Register(modules.NewWOL(sess))
sess.Register(modules.NewWiFiModule(sess)) sess.Register(modules.NewWiFiModule(sess))

View file

@ -9,17 +9,13 @@ import (
"github.com/bettercap/bettercap/log" "github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session" "github.com/bettercap/bettercap/session"
"github.com/bettercap/bettercap/tls"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/tui" "github.com/evilsocket/islazy/tui"
) )
type HttpServer struct { type HttpServer struct {
session.SessionModule session.SessionModule
server *http.Server server *http.Server
certFile string
keyFile string
} }
func NewHttpServer(s *session.Session) *HttpServer { func NewHttpServer(s *session.Session) *HttpServer {
@ -42,18 +38,6 @@ func NewHttpServer(s *session.Session) *HttpServer {
"80", "80",
"Port to bind the http server to.")) "Port to bind the http server to."))
httpd.AddParam(session.NewStringParameter("http.server.certificate",
"",
"",
"TLS certificate file, if not empty will configure this as a HTTPS server (will be auto generated if filled but not existing)."))
httpd.AddParam(session.NewStringParameter("http.server.key",
"",
"",
"TLS key file, if not empty will configure this as a HTTPS server (will be auto generated if filled but not existing)."))
tls.CertConfigToModule("http.server", &httpd.SessionModule, tls.DefaultLegitConfig)
httpd.AddHandler(session.NewModuleHandler("http.server on", "", httpd.AddHandler(session.NewModuleHandler("http.server on", "",
"Start httpd server.", "Start httpd server.",
func(args []string) error { func(args []string) error {
@ -81,17 +65,11 @@ func (httpd *HttpServer) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>" return "Simone Margaritelli <evilsocket@protonmail.com>"
} }
func (httpd *HttpServer) isTLS() bool {
return httpd.certFile != "" && httpd.keyFile != ""
}
func (httpd *HttpServer) Configure() error { func (httpd *HttpServer) Configure() error {
var err error var err error
var path string var path string
var address string var address string
var port int var port int
var certFile string
var keyFile string
if httpd.Running() { if httpd.Running() {
return session.ErrAlreadyStarted return session.ErrAlreadyStarted
@ -121,40 +99,6 @@ func (httpd *HttpServer) Configure() error {
httpd.server.Addr = fmt.Sprintf("%s:%d", address, port) httpd.server.Addr = fmt.Sprintf("%s:%d", address, port)
if err, certFile = httpd.StringParam("http.server.certificate"); err != nil {
return err
} else if certFile, err = fs.Expand(certFile); err != nil {
return err
}
if err, keyFile = httpd.StringParam("http.server.key"); err != nil {
return err
} else if keyFile, err = fs.Expand(keyFile); err != nil {
return err
}
if certFile != "" && keyFile != "" {
if !fs.Exists(certFile) || !fs.Exists(keyFile) {
err, cfg := tls.CertConfigFromModule("http.server", httpd.SessionModule)
if err != nil {
return err
}
log.Debug("%+v", cfg)
log.Info("Generating server TLS key to %s", keyFile)
log.Info("Generating server TLS certificate to %s", certFile)
if err := tls.Generate(cfg, certFile, keyFile); err != nil {
return err
}
} else {
log.Info("loading server TLS key from %s", keyFile)
log.Info("loading server TLS certificate from %s", certFile)
}
}
httpd.certFile = certFile
httpd.keyFile = keyFile
return nil return nil
} }
@ -165,14 +109,8 @@ func (httpd *HttpServer) Start() error {
return httpd.SetRunning(true, func() { return httpd.SetRunning(true, func() {
var err error var err error
if httpd.isTLS() { log.Info("HTTP server starting on http://%s", httpd.server.Addr)
log.Info("HTTPS server starting on https://%s", httpd.server.Addr) if err = httpd.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
err = httpd.server.ListenAndServeTLS(httpd.certFile, httpd.keyFile)
} else {
log.Info("HTTP server starting on http://%s", httpd.server.Addr)
err = httpd.server.ListenAndServe()
}
if err != nil && err != http.ErrServerClosed {
panic(err) panic(err)
} }
}) })

174
modules/https_server.go Normal file
View file

@ -0,0 +1,174 @@
package modules
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/bettercap/bettercap/log"
"github.com/bettercap/bettercap/session"
"github.com/bettercap/bettercap/tls"
"github.com/evilsocket/islazy/fs"
"github.com/evilsocket/islazy/tui"
)
type HttpsServer struct {
session.SessionModule
server *http.Server
certFile string
keyFile string
}
func NewHttpsServer(s *session.Session) *HttpsServer {
httpd := &HttpsServer{
SessionModule: session.NewSessionModule("https.server", s),
server: &http.Server{},
}
httpd.AddParam(session.NewStringParameter("https.server.path",
".",
"",
"Server folder."))
httpd.AddParam(session.NewStringParameter("https.server.address",
session.ParamIfaceAddress,
session.IPv4Validator,
"Address to bind the http server to."))
httpd.AddParam(session.NewIntParameter("https.server.port",
"443",
"Port to bind the http server to."))
httpd.AddParam(session.NewStringParameter("https.server.certificate",
"~/.bettercap-https.cert.pem",
"",
"TLS certificate file (will be auto generated if filled but not existing)."))
httpd.AddParam(session.NewStringParameter("https.server.key",
"~/.bettercap-https.key.pem",
"",
"TLS key file (will be auto generated if filled but not existing)."))
tls.CertConfigToModule("https.server", &httpd.SessionModule, tls.DefaultLegitConfig)
httpd.AddHandler(session.NewModuleHandler("https.server on", "",
"Start https server.",
func(args []string) error {
return httpd.Start()
}))
httpd.AddHandler(session.NewModuleHandler("https.server off", "",
"Stop https server.",
func(args []string) error {
return httpd.Stop()
}))
return httpd
}
func (httpd *HttpsServer) Name() string {
return "https.server"
}
func (httpd *HttpsServer) Description() string {
return "A simple HTTPS server, to be used to serve files and scripts across the network."
}
func (httpd *HttpsServer) Author() string {
return "Simone Margaritelli <evilsocket@protonmail.com>"
}
func (httpd *HttpsServer) Configure() error {
var err error
var path string
var address string
var port int
var certFile string
var keyFile string
if httpd.Running() {
return session.ErrAlreadyStarted
}
if err, path = httpd.StringParam("https.server.path"); err != nil {
return err
}
router := http.NewServeMux()
fileServer := http.FileServer(http.Dir(path))
router.HandleFunc("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Info("(%s) %s %s %s%s", tui.Green("https"), tui.Bold(strings.Split(r.RemoteAddr, ":")[0]), r.Method, r.Host, r.URL.Path)
fileServer.ServeHTTP(w, r)
}))
httpd.server.Handler = router
if err, address = httpd.StringParam("https.server.address"); err != nil {
return err
}
if err, port = httpd.IntParam("https.server.port"); err != nil {
return err
}
httpd.server.Addr = fmt.Sprintf("%s:%d", address, port)
if err, certFile = httpd.StringParam("https.server.certificate"); err != nil {
return err
} else if certFile, err = fs.Expand(certFile); err != nil {
return err
}
if err, keyFile = httpd.StringParam("https.server.key"); err != nil {
return err
} else if keyFile, err = fs.Expand(keyFile); err != nil {
return err
}
if !fs.Exists(certFile) || !fs.Exists(keyFile) {
err, cfg := tls.CertConfigFromModule("https.server", httpd.SessionModule)
if err != nil {
return err
}
log.Debug("%+v", cfg)
log.Info("generating server TLS key to %s", keyFile)
log.Info("generating server TLS certificate to %s", certFile)
if err := tls.Generate(cfg, certFile, keyFile); err != nil {
return err
}
} else {
log.Info("loading server TLS key from %s", keyFile)
log.Info("loading server TLS certificate from %s", certFile)
}
httpd.certFile = certFile
httpd.keyFile = keyFile
return nil
}
func (httpd *HttpsServer) Start() error {
if err := httpd.Configure(); err != nil {
return err
}
return httpd.SetRunning(true, func() {
log.Info("HTTPS server starting on https://%s", httpd.server.Addr)
if err := httpd.server.ListenAndServeTLS(httpd.certFile, httpd.keyFile); err != nil && err != http.ErrServerClosed {
panic(err)
}
})
}
func (httpd *HttpsServer) Stop() error {
return httpd.SetRunning(false, func() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
httpd.server.Shutdown(ctx)
})
}