Merge #14532: Never bind INADDR_ANY by default, and warn when doing so explicitly
27c44ef9c6
rpcbind: Warn about exposing RPC to untrusted networks (Luke Dashjr)d6a1287481
CNetAddr: Add IsBindAny method to check for INADDR_ANY (Luke Dashjr)3615003952
net: Always default rpcbind to localhost, never "all interfaces" (Luke Dashjr) Pull request description: A disturbingly large number of listening nodes appear to be also exposing their RPC server to the public internet. To attempt to mitigate this: * Only ever bind localhost by default, even if `rpcallowip` is specified. (A warning is given if `rpcallowip` is specified without `rpcbind`, since it doesn't really make sense to do.) * Warn about exposing the RPC server to untrusted networks if the user explicitly binds to any INADDR_ANY address. * Include a warning about untrusted networks in the `--help` documentation for `rpcbind`. Tree-SHA512: 755bbca3db416a31393672eccf6675a5ee4d1eb1812cba73ebb4ff8c6b855ecc5df4c692566e9aa7b0f7d4dce6fedb9c0e9f3c265b9663aca36c4a6ba5efdbd4
This commit is contained in:
commit
e77a2258e4
4 changed files with 20 additions and 5 deletions
|
@ -300,9 +300,12 @@ static bool HTTPBindAddresses(struct evhttp* http)
|
|||
std::vector<std::pair<std::string, uint16_t> > endpoints;
|
||||
|
||||
// Determine what addresses to bind to
|
||||
if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs
|
||||
if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs
|
||||
endpoints.push_back(std::make_pair("::1", http_port));
|
||||
endpoints.push_back(std::make_pair("127.0.0.1", http_port));
|
||||
if (gArgs.IsArgSet("-rpcallowip")) {
|
||||
LogPrintf("WARNING: option -rpcallowip was specified without -rpcbind; this doesn't usually make sense\n");
|
||||
}
|
||||
if (gArgs.IsArgSet("-rpcbind")) {
|
||||
LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n");
|
||||
}
|
||||
|
@ -313,9 +316,6 @@ static bool HTTPBindAddresses(struct evhttp* http)
|
|||
SplitHostPort(strRPCBind, port, host);
|
||||
endpoints.push_back(std::make_pair(host, port));
|
||||
}
|
||||
} else { // No specific bind address specified, bind to any
|
||||
endpoints.push_back(std::make_pair("::", http_port));
|
||||
endpoints.push_back(std::make_pair("0.0.0.0", http_port));
|
||||
}
|
||||
|
||||
// Bind addresses
|
||||
|
@ -323,6 +323,10 @@ static bool HTTPBindAddresses(struct evhttp* http)
|
|||
LogPrint(BCLog::HTTP, "Binding RPC on address %s port %i\n", i->first, i->second);
|
||||
evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? nullptr : i->first.c_str(), i->second);
|
||||
if (bind_handle) {
|
||||
CNetAddr addr;
|
||||
if (i->first.empty() || (LookupHost(i->first.c_str(), addr, false) && addr.IsBindAny())) {
|
||||
LogPrintf("WARNING: the RPC server is not safe to expose to untrusted networks such as the public internet\n");
|
||||
}
|
||||
boundSockets.push_back(bind_handle);
|
||||
} else {
|
||||
LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);
|
||||
|
|
|
@ -500,7 +500,7 @@ void SetupServerArgs()
|
|||
gArgs.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcauth=<userpw>", "Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::RPC);
|
||||
|
|
|
@ -83,6 +83,16 @@ unsigned int CNetAddr::GetByte(int n) const
|
|||
return ip[15-n];
|
||||
}
|
||||
|
||||
bool CNetAddr::IsBindAny() const
|
||||
{
|
||||
const int cmplen = IsIPv4() ? 4 : 16;
|
||||
for (int i = 0; i < cmplen; ++i) {
|
||||
if (GetByte(i)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetAddr::IsIPv4() const
|
||||
{
|
||||
return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
|
||||
|
|
|
@ -55,6 +55,7 @@ class CNetAddr
|
|||
bool SetInternal(const std::string& name);
|
||||
|
||||
bool SetSpecial(const std::string &strName); // for Tor addresses
|
||||
bool IsBindAny() const; // INADDR_ANY equivalent
|
||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
|
||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||
|
|
Loading…
Reference in a new issue