diff options
author | Wladimir J. van der Laan <laanwj@protonmail.com> | 2019-08-14 16:35:54 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@protonmail.com> | 2019-08-14 17:07:12 +0200 |
commit | 67be6d7a177cb14ca8a68b9c6361dfaae9e64f2b (patch) | |
tree | 95eb20cd799ee58fd1a638476d45a777fa7bbf10 /src/net.h | |
parent | a7aa809027633556dd3280c6e29ca98eb3235a3d (diff) | |
parent | c5b404e8f1973afe071a07c63ba1038eefe13f0f (diff) |
Merge #16248: Make whitebind/whitelist permissions more flexible
c5b404e8f1973afe071a07c63ba1038eefe13f0f Add functional tests for flexible whitebind/list (nicolas.dorier)
d541fa391844f658bd7035659b5b16695733dd56 Replace the use of fWhitelisted by permission checks (nicolas.dorier)
ecd5cf7ea4c3644a30092100ffc399e30e193275 Do not disconnect peer for asking mempool if it has NO_BAN permission (nicolas.dorier)
e5b26deaaa6842f7dd7c4537ede000f965ea0189 Make whitebind/whitelist permissions more flexible (nicolas.dorier)
Pull request description:
# Motivation
In 0.19, bloom filter will be disabled by default. I tried to make [a PR](https://github.com/bitcoin/bitcoin/pull/16176) to enable bloom filter for whitelisted peers regardless of `-peerbloomfilters`.
Bloom filter have non existent privacy and server can omit filter's matches. However, both problems are completely irrelevant when you connect to your own node. If you connect to your own node, bloom filters are the most bandwidth efficient way to synchronize your light client without the need of some middleware like Electrum.
It is also a superior alternative to BIP157 as it does not require to maintain an additional index and it would work well on pruned nodes.
When I attempted to allow bloom filters for whitelisted peer, my proposal has been NACKed in favor of [a more flexible approach](https://github.com/bitcoin/bitcoin/pull/16176#issuecomment-500762907) which should allow node operator to set fine grained permissions instead of a global `whitelisted` attribute.
Doing so will also make follow up idea very easy to implement in a backward compatible way.
# Implementation details
The PR propose a new format for `--white{list,bind}`. I added a way to specify permissions granted to inbound connection matching `white{list,bind}`.
The following permissions exists:
* ForceRelay
* Relay
* NoBan
* BloomFilter
* Mempool
Example:
* `-whitelist=bloomfilter@127.0.0.1/32`.
* `-whitebind=bloomfilter,relay,noban@127.0.0.1:10020`.
If no permissions are specified, `NoBan | Mempool` is assumed. (making this PR backward compatible)
When we receive an inbound connection, we calculate the effective permissions for this peer by fetching the permissions granted from `whitelist` and add to it the permissions granted from `whitebind`.
To keep backward compatibility, if no permissions are specified in `white{list,bind}` (e.g. `--whitelist=127.0.0.1`) then parameters `-whitelistforcerelay` and `-whiterelay` will add the permissions `ForceRelay` and `Relay` to the inbound node.
`-whitelistforcerelay` and `-whiterelay` are ignored if the permissions flags are explicitly set in `white{bind,list}`.
# Follow up idea
Based on this PR, other changes become quite easy to code in a trivially review-able, backward compatible way:
* Changing `connect` at rpc and config file level to understand the permissions flags.
* Changing the permissions of a peer at RPC level.
ACKs for top commit:
laanwj:
re-ACK c5b404e8f1973afe071a07c63ba1038eefe13f0f
Tree-SHA512: adfefb373d09e68cae401247c8fc64034e305694cdef104bdcdacb9f1704277bd53b18f52a2427a5cffdbc77bda410d221aed252bc2ece698ffbb9cf1b830577
Diffstat (limited to 'src/net.h')
-rw-r--r-- | src/net.h | 35 |
1 files changed, 22 insertions, 13 deletions
@@ -15,6 +15,7 @@ #include <hash.h> #include <limitedmap.h> #include <netaddress.h> +#include <net_permissions.h> #include <policy/feerate.h> #include <protocol.h> #include <random.h> @@ -138,8 +139,9 @@ public: uint64_t nMaxOutboundLimit = 0; int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT; std::vector<std::string> vSeedNodes; - std::vector<CSubNet> vWhitelistedRange; - std::vector<CService> vBinds, vWhiteBinds; + std::vector<NetWhitelistPermissions> vWhitelistedRange; + std::vector<NetWhitebindPermissions> vWhiteBinds; + std::vector<CService> vBinds; bool m_use_addrman_outgoing = true; std::vector<std::string> m_specified_outgoing; std::vector<std::string> m_added_nodes; @@ -314,15 +316,17 @@ public: private: struct ListenSocket { + public: SOCKET socket; - bool whitelisted; - - ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} + inline void AddSocketPermissionFlags(NetPermissionFlags& flags) const { NetPermissions::AddFlag(flags, m_permissions); } + ListenSocket(SOCKET socket_, NetPermissionFlags permissions_) : socket(socket_), m_permissions(permissions_) {} + private: + NetPermissionFlags m_permissions; }; - bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); - bool Bind(const CService &addr, unsigned int flags); - bool InitBinds(const std::vector<CService>& binds, const std::vector<CService>& whiteBinds); + bool BindListenPort(const CService& bindAddr, std::string& strError, NetPermissionFlags permissions); + bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions); + bool InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds); void ThreadOpenAddedConnections(); void AddOneShot(const std::string& strDest); void ProcessOneShot(); @@ -347,7 +351,7 @@ private: bool AttemptToEvictConnection(); CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, bool manual_connection); - bool IsWhitelistedRange(const CNetAddr &addr); + void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const; void DeleteNode(CNode* pnode); @@ -380,7 +384,7 @@ private: // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). - std::vector<CSubNet> vWhitelistedRange; + std::vector<NetWhitelistPermissions> vWhitelistedRange; unsigned int nSendBufferMaxSize{0}; unsigned int nReceiveFloodSize{0}; @@ -448,7 +452,6 @@ void StartMapPort(); void InterruptMapPort(); void StopMapPort(); unsigned short GetListenPort(); -bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); struct CombinerAll { @@ -555,7 +558,8 @@ public: mapMsgCmdSize mapSendBytesPerMsgCmd; uint64_t nRecvBytes; mapMsgCmdSize mapRecvBytesPerMsgCmd; - bool fWhitelisted; + NetPermissionFlags m_permissionFlags; + bool m_legacyWhitelisted; double dPingTime; double dPingWait; double dMinPing; @@ -657,7 +661,11 @@ public: */ std::string cleanSubVer GUARDED_BY(cs_SubVer){}; bool m_prefer_evict{false}; // This peer is preferred for eviction. - bool fWhitelisted{false}; // This peer can bypass DoS banning. + bool HasPermission(NetPermissionFlags permission) const { + return NetPermissions::HasFlag(m_permissionFlags, permission); + } + // This boolean is unusued in actual processing, only present for backward compatibility at RPC/QT level + bool m_legacyWhitelisted{false}; bool fFeeler{false}; // If true this node is being used as a short lived feeler. bool fOneShot{false}; bool m_manual_connection{false}; @@ -753,6 +761,7 @@ private: const ServiceFlags nLocalServices; const int nMyStartingHeight; int nSendVersion{0}; + NetPermissionFlags m_permissionFlags{ PF_NONE }; std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread mutable CCriticalSection cs_addrName; |