Allow disabling RPC server TLS for localhost only.

This commit introduces a new flag, --notls, which can be used to disable
TLS for the RPC server.  However, the flag can only be used when the RPC
server is bound to localhost interfaces.  This is intended to prevent the
situation where someone decides they want to expose the RPC server to the
web for remote management/access, but forgot they have TLS disabled.
This commit is contained in:
Dave Collins 2014-12-20 18:04:07 -06:00
parent e0fce5fe50
commit 04d47de262
4 changed files with 63 additions and 19 deletions

View file

@ -82,6 +82,7 @@ type config struct {
RPCMaxClients int `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"`
RPCMaxWebsockets int `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"`
DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass is specified"`
DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"`
DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"`
ExternalIPs []string `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"`
Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"`
@ -540,7 +541,6 @@ func loadConfig() (*config, []string, error) {
addr = net.JoinHostPort(addr, activeNetParams.rpcPort)
cfg.RPCListeners = append(cfg.RPCListeners, addr)
}
}
// Limit the max block size to a sane value.
@ -624,6 +624,36 @@ func loadConfig() (*config, []string, error) {
cfg.RPCListeners = normalizeAddresses(cfg.RPCListeners,
activeNetParams.rpcPort)
// Only allow TLS to be disabled if the RPC is bound to localhost
// addresses.
if !cfg.DisableRPC && cfg.DisableTLS {
allowedTLSListeners := map[string]struct{}{
"localhost": struct{}{},
"127.0.0.1": struct{}{},
"::1": struct{}{},
}
for _, addr := range cfg.RPCListeners {
host, _, err := net.SplitHostPort(addr)
if err != nil {
str := "%s: RPC listen interface '%s' is " +
"invalid: %v"
err := fmt.Errorf(str, funcName, addr, err)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
if _, ok := allowedTLSListeners[host]; !ok {
str := "%s: the --notls option may not be used " +
"when binding RPC to non localhost " +
"addresses: %s"
err := fmt.Errorf(str, funcName, addr)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
}
}
// Add default port to all added peer addresses if needed and remove
// duplicate addresses.
cfg.AddPeers = normalizeAddresses(cfg.AddPeers,

2
doc.go
View file

@ -48,6 +48,8 @@ Application Options:
--norpc Disable built-in RPC server -- NOTE: The RPC server
is disabled by default if no rpcuser/rpcpass is
specified
--notls Disable TLS for the RPC server -- NOTE: This is only
allowed if the RPC server is bound to localhost
--nodnsseed Disable DNS seeding for peers
--externalip: Add an ip to the list of local addresses we claim to
listen on to peers

View file

@ -524,22 +524,31 @@ func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) {
}
rpc.ntfnMgr = newWsNotificationManager(&rpc)
// check for existence of cert file and key file
if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
// if both files do not exist, we generate them.
err := genCertPair(cfg.RPCCert, cfg.RPCKey)
// Setup TLS if not disabled.
listenFunc := net.Listen
if !cfg.DisableTLS {
// Generate the TLS cert and key file if both don't already
// exist.
if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
err := genCertPair(cfg.RPCCert, cfg.RPCKey)
if err != nil {
return nil, err
}
}
keypair, err := tls.LoadX509KeyPair(cfg.RPCCert, cfg.RPCKey)
if err != nil {
return nil, err
}
}
keypair, err := tls.LoadX509KeyPair(cfg.RPCCert, cfg.RPCKey)
if err != nil {
return nil, err
}
tlsConfig := tls.Config{
Certificates: []tls.Certificate{keypair},
MinVersion: tls.VersionTLS12,
tlsConfig := tls.Config{
Certificates: []tls.Certificate{keypair},
MinVersion: tls.VersionTLS12,
}
// Change the standard net.Listen function to the tls one.
listenFunc = func(net string, laddr string) (net.Listener, error) {
return tls.Listen(net, laddr, &tlsConfig)
}
}
// TODO(oga) this code is similar to that in server, should be
@ -551,20 +560,18 @@ func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) {
listeners := make([]net.Listener, 0,
len(ipv6ListenAddrs)+len(ipv4ListenAddrs))
for _, addr := range ipv4ListenAddrs {
listener, err := tls.Listen("tcp4", addr, &tlsConfig)
listener, err := listenFunc("tcp4", addr)
if err != nil {
rpcsLog.Warnf("Can't listen on %s: %v", addr,
err)
rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
continue
}
listeners = append(listeners, listener)
}
for _, addr := range ipv6ListenAddrs {
listener, err := tls.Listen("tcp6", addr, &tlsConfig)
listener, err := listenFunc("tcp6", addr)
if err != nil {
rpcsLog.Warnf("Can't listen on %s: %v", addr,
err)
rpcsLog.Warnf("Can't listen on %s: %v", addr, err)
continue
}
listeners = append(listeners, listener)

View file

@ -193,6 +193,11 @@
; server without having to remove credentials from the config file.
; norpc=1
; Use the following setting to disable TLS for the RPC server. NOTE: This
; option only works if the RPC server is bound to localhost interfaces (which is
; the default).
; notls=1
; ------------------------------------------------------------------------------
; Coin Generation (Mining) Settings - The following options control the