diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-06-21 13:34:36 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-07-09 20:40:14 +0200 |
commit | dc942e6f276b9fabc21f06d11cd16871d4054f82 (patch) | |
tree | 5ccbf11f0aec355fe115a606bb370125bb631d98 /src/net.cpp | |
parent | f3330b40a599615f15f585166ef08f00d06e9616 (diff) |
Introduce whitelisted peers.
This adds a -whitelist option to specify subnet ranges from which peers
that connect are whitelisted. In addition, there is a -whitebind option
which works like -bind, except peers connecting to it are also
whitelisted (allowing a separate listen port for trusted connections).
Being whitelisted has two effects (for now):
* They are immune to DoS disconnection/banning.
* Transactions they broadcast (which are valid) are always relayed,
even if they were already in the mempool. This means that a node
can function as a gateway for a local network, and that rebroadcasts
from the local network will work as expected.
Whitelisting replaces the magic exemption localhost had for DoS
disconnection (local addresses are still never banned, though), which
implied hidden service connects (from a localhost Tor node) were
incorrectly immune to DoS disconnection as well. This old
behaviour is removed for that reason, but can be restored using
-whitelist=127.0.0.1 or -whitelist=::1 can be specified. -whitebind
is safer to use in case non-trusted localhost connections are expected
(like hidden services).
Diffstat (limited to 'src/net.cpp')
-rw-r--r-- | src/net.cpp | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/net.cpp b/src/net.cpp index 6a660dc9bd..6a6d9df6af 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -50,7 +50,16 @@ using namespace std; using namespace boost; -static const int MAX_OUTBOUND_CONNECTIONS = 8; +namespace { + const int MAX_OUTBOUND_CONNECTIONS = 8; + + struct ListenSocket { + SOCKET socket; + bool whitelisted; + + ListenSocket(SOCKET socket, bool whitelisted) : socket(socket), whitelisted(whitelisted) {} + }; +} // // Global state variables @@ -65,7 +74,7 @@ static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; static CNode* pnodeSync = NULL; uint64_t nLocalHostNonce = 0; -static std::vector<SOCKET> vhListenSocket; +static std::vector<ListenSocket> vhListenSocket; CAddrMan addrman; int nMaxConnections = 125; @@ -593,6 +602,24 @@ bool CNode::Ban(const CNetAddr &addr) { return true; } + +std::vector<CSubNet> CNode::vWhitelistedRange; +CCriticalSection CNode::cs_vWhitelistedRange; + +bool CNode::IsWhitelistedRange(const CNetAddr &addr) { + LOCK(cs_vWhitelistedRange); + BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) { + if (subnet.Match(addr)) + return true; + } + return false; +} + +void CNode::AddWhitelistedRange(const CSubNet &subnet) { + LOCK(cs_vWhitelistedRange); + vWhitelistedRange.push_back(subnet); +} + #undef X #define X(name) stats.name = name void CNode::copyStats(CNodeStats &stats) @@ -609,6 +636,7 @@ void CNode::copyStats(CNodeStats &stats) X(nStartingHeight); X(nSendBytes); X(nRecvBytes); + X(fWhitelisted); stats.fSyncNode = (this == pnodeSync); // It is common for nodes with good ping times to suddenly become lagged, @@ -848,9 +876,9 @@ void ThreadSocketHandler() SOCKET hSocketMax = 0; bool have_fds = false; - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { - FD_SET(hListenSocket, &fdsetRecv); - hSocketMax = max(hSocketMax, hListenSocket); + BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) { + FD_SET(hListenSocket.socket, &fdsetRecv); + hSocketMax = max(hSocketMax, hListenSocket.socket); have_fds = true; } @@ -917,13 +945,13 @@ void ThreadSocketHandler() // // Accept new connections // - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) + BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) { - if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) + if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv)) { struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); - SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); + SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len); CAddress addr; int nInbound = 0; @@ -931,6 +959,7 @@ void ThreadSocketHandler() if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) LogPrintf("Warning: Unknown socket family\n"); + bool whitelisted = hListenSocket.whitelisted || CNode::IsWhitelistedRange(addr); { LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) @@ -948,7 +977,7 @@ void ThreadSocketHandler() { closesocket(hSocket); } - else if (CNode::IsBanned(addr)) + else if (CNode::IsBanned(addr) && !whitelisted) { LogPrintf("connection from %s dropped (banned)\n", addr.ToString()); closesocket(hSocket); @@ -957,6 +986,7 @@ void ThreadSocketHandler() { CNode* pnode = new CNode(hSocket, addr, "", true); pnode->AddRef(); + pnode->fWhitelisted = whitelisted; { LOCK(cs_vNodes); @@ -1580,7 +1610,7 @@ void ThreadMessageHandler() -bool BindListenPort(const CService &addrBind, string& strError) +bool BindListenPort(const CService &addrBind, string& strError, bool fWhitelisted) { strError = ""; int nOne = 1; @@ -1661,9 +1691,9 @@ bool BindListenPort(const CService &addrBind, string& strError) return false; } - vhListenSocket.push_back(hListenSocket); + vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted)); - if (addrBind.IsRoutable() && fDiscover) + if (addrBind.IsRoutable() && fDiscover && !fWhitelisted) AddLocal(addrBind, LOCAL_BIND); return true; @@ -1788,9 +1818,9 @@ public: BOOST_FOREACH(CNode* pnode, vNodes) if (pnode->hSocket != INVALID_SOCKET) closesocket(pnode->hSocket); - BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) - if (hListenSocket != INVALID_SOCKET) - if (closesocket(hListenSocket) == SOCKET_ERROR) + BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket) + if (hListenSocket.socket != INVALID_SOCKET) + if (closesocket(hListenSocket.socket) == SOCKET_ERROR) LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); // clean up some globals (to help leak detection) |