From 90a9d1cc0bd12f2acc7987016eb4e81af9902060 Mon Sep 17 00:00:00 2001 From: Frank Schroeder Date: Mon, 23 Oct 2017 16:29:42 +0200 Subject: [PATCH] Issue #369: Do not allow to run fabio as root Fabio 1.5.7 will add recurring warning if fabio is run as root (UID == 0) on UNIX operating systems. It will also add an '-insecure' flag as an override. As of version 1.7 fabio will refuse to start as root without the '-insecure' flag. Fixes #369 --- config/config.go | 1 + config/load.go | 1 + config/load_test.go | 7 ++++++ main.go | 8 +++++++ rootwarn_unix.go | 58 +++++++++++++++++++++++++++++++++++++++++++++ rootwarn_windows.go | 7 ++++++ 6 files changed, 82 insertions(+) create mode 100644 rootwarn_unix.go create mode 100644 rootwarn_windows.go diff --git a/config/config.go b/config/config.go index 58279ae58..4bf32e896 100644 --- a/config/config.go +++ b/config/config.go @@ -16,6 +16,7 @@ type Config struct { Runtime Runtime ProfileMode string ProfilePath string + Insecure bool } type CertSource struct { diff --git a/config/load.go b/config/load.go index 944c625fb..1b42436a9 100644 --- a/config/load.go +++ b/config/load.go @@ -116,6 +116,7 @@ func load(cmdline, environ, envprefix []string, props *properties.Properties) (c var readTimeout, writeTimeout time.Duration var gzipContentTypesValue string + f.BoolVar(&cfg.Insecure, "insecure", defaultConfig.Insecure, "allow fabio to run as root when set to true") f.IntVar(&cfg.Proxy.MaxConn, "proxy.maxconn", defaultConfig.Proxy.MaxConn, "maximum number of cached connections") f.StringVar(&cfg.Proxy.Strategy, "proxy.strategy", defaultConfig.Proxy.Strategy, "load balancing strategy") f.StringVar(&cfg.Proxy.Matcher, "proxy.matcher", defaultConfig.Proxy.Matcher, "path matching algorithm") diff --git a/config/load_test.go b/config/load_test.go index 77e60e312..b0fc6f41f 100644 --- a/config/load_test.go +++ b/config/load_test.go @@ -49,6 +49,13 @@ func TestLoad(t *testing.T) { desc: "default config", cfg: func(cfg *Config) *Config { return cfg }, }, + { + args: []string{"-insecure=true"}, + cfg: func(cfg *Config) *Config { + cfg.Insecure = true + return cfg + }, + }, { args: []string{"-profile.mode", "foo"}, cfg: func(cfg *Config) *Config { diff --git a/main.go b/main.go index 1f4122c64..a8637354e 100644 --- a/main.go +++ b/main.go @@ -71,6 +71,10 @@ func main() { log.Printf("[INFO] Version %s starting", version) log.Printf("[INFO] Go runtime is %s", runtime.Version()) + // warn once so that it is at the beginning of the log + // this will also start the reminder go routine if necessary. + WarnIfRunAsRoot(cfg.Insecure) + // setup profiling if enabled var prof interface { Stop() @@ -125,6 +129,10 @@ func main() { // create proxies after metrics since they use the metrics registry. startServers(cfg) + + // warn again so that it is visible in the terminal + WarnIfRunAsRoot(cfg.Insecure) + exit.Wait() log.Print("[INFO] Down") } diff --git a/rootwarn_unix.go b/rootwarn_unix.go new file mode 100644 index 000000000..a8bbff3fd --- /dev/null +++ b/rootwarn_unix.go @@ -0,0 +1,58 @@ +// +build !windows + +package main + +import ( + "log" + "os" + "sync" + "time" +) + +const interval = time.Hour + +const warnInsecure = ` + + ************************************************************ + You are running fabio as root with the '-insecure' flag + Please check https://fabiolb.net/faq/binding-to-low-ports/ + for alternatives. + ************************************************************ + +` + +const warn17behavior = ` + + ************************************************************ + You are running fabio as root without the '-insecure' flag + This will stop working with fabio 1.7! + ************************************************************ + +` + +var once sync.Once + +func WarnIfRunAsRoot(allowRoot bool) { + isRoot := os.Getuid() == 0 + if !isRoot { + return + } + doWarn(allowRoot) + once.Do(func() { go remind(allowRoot) }) +} + +func doWarn(allowRoot bool) { + warn := warnInsecure + if !allowRoot { + warn = warn17behavior + } + log.Printf("[INFO] Running fabio as UID=%d EUID=%d GID=%d", os.Getuid(), os.Geteuid(), os.Getgid()) + log.Print("[WARN] ", warn) +} + +func remind(allowRoot bool) { + for { + doWarn(allowRoot) + time.Sleep(interval) + } +} diff --git a/rootwarn_windows.go b/rootwarn_windows.go new file mode 100644 index 000000000..771f0b892 --- /dev/null +++ b/rootwarn_windows.go @@ -0,0 +1,7 @@ +// +build windows + +package main + +func CheckInsecure(allowRoot bool) { + // windows not supported +}