Check if IP:port combinations are possible before returning OK on /install/configure

This commit is contained in:
Eugene Bujak 2019-02-01 19:25:04 +03:00
parent f2b3c3a14c
commit daae040f9c
3 changed files with 35 additions and 12 deletions

16
app.go
View File

@ -116,14 +116,16 @@ func run(args options) {
log.Fatal(err) log.Fatal(err)
} }
err = startDNSServer() if !config.firstRun {
if err != nil { err = startDNSServer()
log.Fatal(err) if err != nil {
} log.Fatal(err)
}
err = startDHCPServer() err = startDHCPServer()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
}
} }
// Update filters we've just loaded right away, don't wait for periodic update timer // Update filters we've just loaded right away, don't wait for periodic update timer

View File

@ -723,7 +723,7 @@ func handleInstallGetAddresses(w http.ResponseWriter, r *http.Request) {
// fill out the fields // fill out the fields
// find out if port 80 is available -- if not, fall back to 3000 // find out if port 80 is available -- if not, fall back to 3000
if checkPortAvailable(80) { if checkPortAvailable("", 80) {
data.Web.Port = 80 data.Web.Port = 80
} else { } else {
data.Web.Port = 3000 data.Web.Port = 3000
@ -731,7 +731,7 @@ func handleInstallGetAddresses(w http.ResponseWriter, r *http.Request) {
// find out if port 53 is available -- if not, show a big warning // find out if port 53 is available -- if not, show a big warning
data.DNS.Port = 53 data.DNS.Port = 53
if !checkPortAvailable(53) { if !checkPacketPortAvailable("", 53) {
data.DNS.Warning = "Port 53 is not available for binding -- this will make DNS clients unable to contact AdGuard Home." data.DNS.Warning = "Port 53 is not available for binding -- this will make DNS clients unable to contact AdGuard Home."
} }
@ -764,7 +764,18 @@ func handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
} }
spew.Dump(newSettings) spew.Dump(newSettings)
// TODO: validate that hosts and ports are bindable // validate that hosts and ports are bindable
if !checkPortAvailable(newSettings.Web.IP, newSettings.Web.Port) {
httpError(w, http.StatusBadRequest, "Impossible to listen on IP:port %s:%d", newSettings.Web.IP, newSettings.Web.Port)
return
}
if !checkPacketPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) {
httpError(w, http.StatusBadRequest, "Impossible to listen on IP:port %s:%d", newSettings.DNS.IP, newSettings.DNS.Port)
return
}
config.firstRun = false config.firstRun = false
config.BindHost = newSettings.Web.IP config.BindHost = newSettings.Web.IP
config.BindPort = newSettings.Web.Port config.BindPort = newSettings.Web.Port

View File

@ -12,6 +12,7 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv"
"strings" "strings"
"github.com/hmage/golibs/log" "github.com/hmage/golibs/log"
@ -259,8 +260,17 @@ func findIPv4IfaceAddr(ifaces []netInterface) string {
} }
// checkPortAvailable is not a cheap test to see if the port is bindable, because it's actually doing the bind momentarily // checkPortAvailable is not a cheap test to see if the port is bindable, because it's actually doing the bind momentarily
func checkPortAvailable(port int) bool { func checkPortAvailable(host string, port int) bool {
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) ln, err := net.Listen("tcp", net.JoinHostPort(host, strconv.Itoa(port)))
if err != nil {
return false
}
ln.Close()
return true
}
func checkPacketPortAvailable(host string, port int) bool {
ln, err := net.ListenPacket("udp", net.JoinHostPort(host, strconv.Itoa(port)))
if err != nil { if err != nil {
return false return false
} }