Stopping the Botnet

If you're in The Netherlands next week on June 28th, you can alpha test my new course! It's about how to contribute to Bitcoin Core, with a focus on the process around making and reviewing pull requests.

You can sign up here. I'm looking for up to ten participants. Interested but can't make it? Reply to this newsletter and I'll keep you in the loop.

Today continues chapter 7 from the book Bitcoin: A Work in Progress.

Last week we described an eclipse attack by a hypothetical botnet, controlling many diverse IP address. How do we deal with that?

How to Solve It

It’s important to understand that attacks like these are a numbers game. An attacker needs to give your node a lot of spam addresses to fill up all the buckets and make sure it only connects to you.

So one obvious mitigation of an attack like this is to have more buckets. Unfortunately, this doesn’t help much with isolation, because doubling the number of buckets only doubles the attack cost, and we already saw how cheap it is. Still, the number of buckets was quadrupled almost immediately after the paper was published.

Another countermeasure lies in the aforementioned coin toss. This toss was actually biased toward trying new nodes and toward those that your node most recently learned about. This was changed to just a coin toss (in that same early pull request). Why not go further and only connect to peers your node has known the longest? There are always tradeoffs — in this case, your node might spend too much time going through a list of no-longer-reachable IP addresses.

But there was another proposed mitigation that also provided a bias toward familiar nodes, only in a safer way. It pertained to how buckets are handled when they’re about to overflow. When you hear of a new address and you want to put it in a bucket and remove something else, you first check the address that’s already in the bucket. That entails connecting to it to see if it still exists. If it does exist, you don’t replace it. This is called a feeler connection. This was more complicated and it took until mid-2016 to be implemented (by one of the authors in fact).

Still, other mitigations took much longer. When Bitcoin Core 0.21.0 was released in January 2021, it included a new method to prevent eclipse attacks that was suggested in this same 2015 paper: the use of anchor connections. What happens is that when you restart, you try to remember some of the last connections you had. Your node remembers the two connections that it only exchanges blocks with, and it tries to reconnect to those.

Why two? It’s not a good idea to always try to reconnect to the same nodes again when you restart, as, for all you know, the reason you crashed in the first place is because one of those nodes was evil. The same logic applies to the scenario where you’re already being eclipsed.