From 5ab901bb36bc127e33f2082dbe9609f30d26b75d Mon Sep 17 00:00:00 2001 From: leuc <47371249+leuc@users.noreply.github.com> Date: Tue, 25 May 2021 01:13:49 +0200 Subject: [PATCH] Fix #981 Use -webserverip to set http listen address (#1032) * Fix #981 Use -webserverip to set http listen address * use 0.0.0.0 as default http listen address * add Admin REST API for setting http listen address * full input validation of port and IP --- config/config.go | 3 +++ config/defaults.go | 2 ++ controllers/admin/config.go | 43 ++++++++++++++++++++++++++++--- controllers/admin/serverConfig.go | 2 ++ core/data/config.go | 16 ++++++++++++ main.go | 9 ++++++- router/router.go | 13 ++++++++-- 7 files changed, 82 insertions(+), 6 deletions(-) diff --git a/config/config.go b/config/config.go index 3a50c04cc..33b2e0076 100644 --- a/config/config.go +++ b/config/config.go @@ -21,6 +21,9 @@ var VersionNumber = StaticVersionNumber // WebServerPort is the port for Owncast's webserver that is used for this execution of the service. var WebServerPort = 8080 +// Bind WebServer to this IP address. Be secure by default. +var WebServerIP = "0.0.0.0" + // InternalHLSListenerPort is the port for HLS writes that is used for this execution of the service. var InternalHLSListenerPort = "8927" diff --git a/config/defaults.go b/config/defaults.go index 0570ef604..de71849fd 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -14,6 +14,7 @@ type Defaults struct { DatabaseFilePath string WebServerPort int + WebServerIP string RTMPServerPort int StreamKey string @@ -46,6 +47,7 @@ func GetDefaults() Defaults { YPServer: "https://directory.owncast.online", WebServerPort: 8080, + WebServerIP: "0.0.0.0", RTMPServerPort: 1935, StreamKey: "abc123", diff --git a/controllers/admin/config.go b/controllers/admin/config.go index c6461abfb..8846c1d65 100644 --- a/controllers/admin/config.go +++ b/controllers/admin/config.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "net/http" "path/filepath" "reflect" @@ -293,12 +294,48 @@ func SetWebServerPort(w http.ResponseWriter, r *http.Request) { return } - if err := data.SetHTTPPortNumber(configValue.Value.(float64)); err != nil { - controllers.WriteSimpleResponse(w, false, err.Error()) + if port, ok := configValue.Value.(float64); ok { + if (port < 1) || (port > 65535) { + controllers.WriteSimpleResponse(w, false, "Port number must be between 1 and 65535") + return + } + if err := data.SetHTTPPortNumber(port); err != nil { + controllers.WriteSimpleResponse(w, false, err.Error()) + return + } else { + controllers.WriteSimpleResponse(w, true, "HTTP port set") + return + } + } + controllers.WriteSimpleResponse(w, false, "Invalid type or value, port must be a number") +} + +// SetWebServerIP will handle the web config request to set the server's HTTP listen address. +func SetWebServerIP(w http.ResponseWriter, r *http.Request) { + if !requirePOST(w, r) { return } - controllers.WriteSimpleResponse(w, true, "http port set") + configValue, success := getValueFromRequest(w, r) + if !success { + return + } + + if input, ok := configValue.Value.(string); ok { + if ip := net.ParseIP(input); ip != nil { + if err := data.SetHTTPListenAddress(ip.String()); err != nil { + controllers.WriteSimpleResponse(w, false, err.Error()) + return + } else { + controllers.WriteSimpleResponse(w, true, "HTTP listen address set") + return + } + } else { + controllers.WriteSimpleResponse(w, false, "Invalid IP address") + return + } + } + controllers.WriteSimpleResponse(w, false, "Invalid type or value, IP address must be a string") } // SetRTMPServerPort will handle the web config request to set the inbound RTMP port. diff --git a/controllers/admin/serverConfig.go b/controllers/admin/serverConfig.go index 51fdb0812..8a29c21bc 100644 --- a/controllers/admin/serverConfig.go +++ b/controllers/admin/serverConfig.go @@ -46,6 +46,7 @@ func GetServerConfig(w http.ResponseWriter, r *http.Request) { FFmpegPath: ffmpeg, StreamKey: data.GetStreamKey(), WebServerPort: config.WebServerPort, + WebServerIP: config.WebServerIP, RTMPServerPort: data.GetRTMPPortNumber(), ChatDisabled: data.GetChatDisabled(), VideoSettings: videoSettings{ @@ -75,6 +76,7 @@ type serverConfigAdminResponse struct { FFmpegPath string `json:"ffmpegPath"` StreamKey string `json:"streamKey"` WebServerPort int `json:"webServerPort"` + WebServerIP string `json:"webServerIP"` RTMPServerPort int `json:"rtmpServerPort"` S3 models.S3 `json:"s3"` VideoSettings videoSettings `json:"videoSettings"` diff --git a/core/data/config.go b/core/data/config.go index 161c65e97..c422f9633 100644 --- a/core/data/config.go +++ b/core/data/config.go @@ -22,6 +22,7 @@ const serverWelcomeMessageKey = "server_welcome_message" const serverNameKey = "server_name" const serverURLKey = "server_url" const httpPortNumberKey = "http_port_number" +const httpListenAddressKey = "http_listen_address" const rtmpPortNumberKey = "rtmp_port_number" const serverMetadataTagsKey = "server_metadata_tags" const directoryEnabledKey = "directory_enabled" @@ -191,6 +192,21 @@ func SetHTTPPortNumber(port float64) error { return _datastore.SetNumber(httpPortNumberKey, port) } +// GetHTTPListenAddress will return the HTTP listen address. +func GetHTTPListenAddress() string { + address, err := _datastore.GetString(httpListenAddressKey) + if err != nil { + log.Traceln(httpListenAddressKey, err) + return config.GetDefaults().WebServerIP + } + return string(address) +} + +// SetHTTPListenAddress will set the server HTTP listen address. +func SetHTTPListenAddress(address string) error { + return _datastore.SetString(httpListenAddressKey, address) +} + // GetRTMPPortNumber will return the server RTMP port. func GetRTMPPortNumber() int { port, err := _datastore.GetNumber(rtmpPortNumberKey) diff --git a/main.go b/main.go index 354b1115e..88e622386 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,7 @@ func main() { restoreDatabaseFile := flag.String("restoreDatabase", "", "Restore an Owncast database backup") newStreamKey := flag.String("streamkey", "", "Set your stream key/admin password") webServerPortOverride := flag.String("webserverport", "", "Force the web server to listen on a specific port") + webServerIPOverride := flag.String("webserverip", "", "Force web server to listen on this IP address") rtmpPortOverride := flag.Int("rtmpport", 0, "Set listen port for the RTMP server") flag.Parse() @@ -117,9 +118,15 @@ func main() { log.Println("Saving new web server port number to", portNumber) data.SetHTTPPortNumber(float64(portNumber)) } - config.WebServerPort = data.GetHTTPPortNumber() + // Set the web server ip + if *webServerIPOverride != "" { + log.Println("Saving new web server listen IP address to", *webServerIPOverride) + data.SetHTTPListenAddress(string(*webServerIPOverride)) + } + config.WebServerIP = data.GetHTTPListenAddress() + // Set the rtmp server port if *rtmpPortOverride > 0 { log.Println("Saving new RTMP server port number to", *rtmpPortOverride) diff --git a/router/router.go b/router/router.go index 4745d2b49..e13052245 100644 --- a/router/router.go +++ b/router/router.go @@ -2,6 +2,7 @@ package router import ( "fmt" + "net" "net/http" log "github.com/sirupsen/logrus" @@ -172,6 +173,9 @@ func Start() error { // Server http port http.HandleFunc("/api/admin/config/webserverport", middleware.RequireAdminAuth(admin.SetWebServerPort)) + // Server http listen address + http.HandleFunc("/api/admin/config/webserverip", middleware.RequireAdminAuth(admin.SetWebServerIP)) + // Server rtmp port http.HandleFunc("/api/admin/config/rtmpserverport", middleware.RequireAdminAuth(admin.SetRTMPServerPort)) @@ -206,9 +210,14 @@ func Start() error { http.HandleFunc("/api/admin/config/customstyles", middleware.RequireAdminAuth(admin.SetCustomStyles)) port := config.WebServerPort + ip := config.WebServerIP - log.Infof("Web server is listening on port %d.", port) + ip_addr := net.ParseIP(ip) + if ip_addr == nil { + log.Fatalln("Invalid IP address", ip) + } + log.Infof("Web server is listening on IP %s port %d.", ip_addr.String(), port) log.Infoln("The web admin interface is available at /admin.") - return http.ListenAndServe(fmt.Sprintf(":%d", port), nil) + return http.ListenAndServe(fmt.Sprintf("%s:%d", ip_addr.String(), port), nil) }