From 8b463fbc2b8acb500408b62b536dc4aab69cc491 Mon Sep 17 00:00:00 2001 From: eugene Date: Tue, 2 Mar 2021 17:08:31 -0500 Subject: [PATCH] lnd: optionally listen on localhost for better security The --profile flag now accepts both a port and a host:port string. If profile is set to a port, then pprof debugging information will be served over localhost. Otherwise, we will attempt to serve pprof information on the specified host:port (if we are allowed to listen on it.) We default to the safe option as if the port is connectable, anybody can connect and see debugging information. See: https://mmcloughlin.com/posts/your-pprof-is-showing --- config.go | 37 ++++++++++++++++++++++++++++--------- lnd.go | 4 ++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/config.go b/config.go index 80d81ee6..801d0f8f 100644 --- a/config.go +++ b/config.go @@ -239,7 +239,7 @@ type Config struct { CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` - Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65535"` + Profile string `long:"profile" description:"Enable HTTP profiling on either a port or host:port"` UnsafeDisconnect bool `long:"unsafe-disconnect" description:"DEPRECATED: Allows the rpcserver to intentionally disconnect from peers with open channels. THIS FLAG WILL BE REMOVED IN 0.10.0"` UnsafeReplay bool `long:"unsafe-replay" description:"Causes a link to replay the adds on its commitment txn after starting up, this enables testing of the sphinx replay logic."` @@ -1086,15 +1086,34 @@ func ValidateConfig(cfg Config, usageMessage string, cfg.Autopilot.MaxChannelSize = int64(MaxFundingAmount) } - // Validate profile port number. + // Validate profile port or host:port. if cfg.Profile != "" { - profilePort, err := strconv.Atoi(cfg.Profile) - if err != nil || profilePort < 1024 || profilePort > 65535 { - str := "%s: The profile port must be between 1024 and 65535" - err := fmt.Errorf(str, funcName) - _, _ = fmt.Fprintln(os.Stderr, err) - _, _ = fmt.Fprintln(os.Stderr, usageMessage) - return nil, err + str := "%s: The profile port must be between 1024 and 65535" + + // Try to parse Profile as a host:port. + _, hostPort, err := net.SplitHostPort(cfg.Profile) + if err == nil { + // Determine if the port is valid. + profilePort, err := strconv.Atoi(hostPort) + if err != nil || profilePort < 1024 || profilePort > 65535 { + err = fmt.Errorf(str, funcName) + _, _ = fmt.Fprintln(os.Stderr, err) + _, _ = fmt.Fprintln(os.Stderr, usageMessage) + return nil, err + } + } else { + // Try to parse Profile as a port. + profilePort, err := strconv.Atoi(cfg.Profile) + if err != nil || profilePort < 1024 || profilePort > 65535 { + err = fmt.Errorf(str, funcName) + _, _ = fmt.Fprintln(os.Stderr, err) + _, _ = fmt.Fprintln(os.Stderr, usageMessage) + return nil, err + } + + // Since the user just set a port, we will serve debugging + // information over localhost. + cfg.Profile = net.JoinHostPort("127.0.0.1", cfg.Profile) } } diff --git a/lnd.go b/lnd.go index e340a2fd..2b614d8d 100644 --- a/lnd.go +++ b/lnd.go @@ -227,11 +227,11 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error // Enable http profiling server if requested. if cfg.Profile != "" { go func() { - listenAddr := net.JoinHostPort("", cfg.Profile) profileRedirect := http.RedirectHandler("/debug/pprof", http.StatusSeeOther) http.Handle("/", profileRedirect) - fmt.Println(http.ListenAndServe(listenAddr, nil)) + ltndLog.Infof("Pprof listening on %v", cfg.Profile) + fmt.Println(http.ListenAndServe(cfg.Profile, nil)) }() }