User:Gmaxwell/inbound connection management
When a new non-banned connection comes in and your node finds itself full, it needs to find a peer to eject.
Currently we eject the new peer. This has some good properties, in particular, an attacker can't partition an already working node just by filling his slots. It also creates relatively little distortion on the topology of the network, (not zero: peers with more reliable tcp connections are better connected).
There are downsides, it lets an attacker block all future connections pretty easily. Most of the slots can end up filled by reliable but useless peers, etc.
We can do better: It's not necessary to use a single strategy to pick all our peers, by using different strategies for subsets of peers we can get the good connectivity properties of all of them.
In general, we want to preserve some connections for peers which have properties which are hard for attackers to have. (Either because they're expensive to have in bulk, or because they're incompatible with 'attacking').
Take the list of all inbound connections,
Exclude all trusted port peers. (this is assuming we setup a second p2p port
that is localhost bound by default that is only for trusted peers).
Remove from consideration the 10 most recent peers that gave you blocks you
accepted that extended your tip. The rationale here is that you want to keep peers that are giving you blocks since they're provably working, but giving you a single block shouldn't let a peer squat on a connection forever.
Remove from consideration up to 10 peers that are from (what you believe to
be) your own local netgroup sorted by longest_mintime_between_reconnects. The rationale here is that membership in your own specific netgroup is hard for many attackers, even if they can get many networks on the internet. Sorting by longest_mintime_between_reconnects reduces punishes agressive reconnecters (e.g. spying nodes and connection fillers).
(It may be useful to separately ban agressive reconnecters, but any such
banning would have to be very conservative, so a priority here still helps)
Sort the list by good_peer_flag,HMAC(netgroup,key),longest_mintime_between_reconnects
and select 10 peers to remove from consideration. Only remote one per netgroup in this step. Having a netgroup that ranks highly according to your secret preference is costly for an attacker to achieve.
Sort the list by HMAC(addr,key),longest_conntime and select 10 peers to
remove from consideration. This helps preserve the random wiring of the network. Only take a single connection per address in this step. Having an address that ranks highly according to your secret preference is costly for an attacker to achieve.
Sort by good_peer, min(observed_ping_rtt), longest_uptime, and select 10 to remove
from consideration, skipping any repeated network groups and your own netgroup. Low rtt latency cannot be forged, making this another attacker scarce resource... though one that results in a bad nework topology.
Remove from consideration 10 of the remaining peers with the highest
cumulative (e.g. across restarts) time connected.
Remove from consideration 10 of the remaining peers with the longest connections
this session.
Of the remaining peers, randomly select a peer to kick with a strong bias
towards the shortest connection duration.