Today continues chapter 7 from the book Bitcoin: A Work in Progress.
We explained last week how if we make it expensive enough, it makes less and less economic sense for a miner to perform one. That, unless they’re duped:
It turns out an attacker can also use miners against you without their cooperation by trying to split miners. They do this by not just eclipsing you, but also by eclipsing one or more miners. The eclipsed miners, presumably a minority, would see the same transaction as you, the actual target victim. Once they mine it, the attacker ensures that your node is the only one that gets to see this block. This miner is a victim too, because just like your transaction ends up disappearing once the block eventually goes stale, their coinbase transaction disappears too. For all this economic damage, the attacker might only rob you of $100. So we really want eclipse attacks to be very difficult.
Miners and pool operators are of course not naive. They might run multiple nodes in different countries and take precautions so that an attacker won’t know which node to eclipse. In addition, mining is still somewhat centralized, so there are specialized networks that connect them, making eclipse attacks even more difficult.^[One such network to connect miners is the Fast Internet Bitcoin Relay Engine (FIBRE). But this shouldn’t be the only thing we’re relying on to prevent these attacks. Luckily, more and more improvements that are designed to make these attacks more difficult are being deployed.
So far we’ve assumed that an eclipse attack can be done, in order to explain how it’s used to trick you into parting with your hard-earned coins. But how is it actually done?
Recall from above that, in order to eclipse your node, the attacker needs to take over all eight of your outbound connections and whatever number of inbound connections your node has. This is a cat and mouse game, and even before the above-mentioned paper was written, the Bitcoin Core software was hardened to prevent eclipse attacks. But let’s see how the paper proposed overcoming the existing defenses.
There are a couple of ingredients. First, when a node starts, it tries to find other peers, and once it’s been running for a while, it has a list of addresses it learned from other peers and it stores them in a file. Then, whenever a node loses one of its eight outbound connections, or when it restarts, it looks at this file with all the addresses it’s ever heard of, and it starts randomly connecting to them.
As an attacker, the idea is to pollute this file by giving your node a bunch of addresses that either don’t exist or that they (the attacker) control. This way, whatever address your node picks, every time it makes a connection, it either fails because there’s nothing there, or it connects to the attacker — and eventually all connections are to the attacker.
The attacker also needs to control all inbound connections to your node. Without going into too much detail in this chapter, one approach is to just make lots and lots of connection attempts until all your 117 inbound slots are full. Over time, perhaps weeks, as honest peers occasionally disconnect from you, the attacker quickly fills the open inbound slots so that no new honest peers get through.
(This has been made more difficult by sometimes dropping an existing inbound connection in favor of a new one)
As early as 2012, developers realized it was possible for an attacker to give your node huge numbers of IP addresses, all controlled by them. Let’s say your node has 1,000 real IP addresses of other nodes. Then the attacker feeds you 9,000 addresses that they control. As your node starts to pick IP addresses, the odds are 90 percent that it will connect to the attacker.
But as long as these addresses were closely related, e.g. because they were all in the same data center, there was something that could be done. A bucket system was introduced, and it puts all IP addresses with the same two starting digits, e.g. 172.67.*.*
into the same bucket. The node would then pick from different buckets for each of its outbound connections.
In the example above, all the attacker’s IP addresses end up in one bucket, and there are 256 such buckets, so the odds of connecting to even a single attacker node drop dramatically. Keep in mind that you only need one honest peer to be protected against eclipse attacks.
Each bucket is also limited in size, so most of the 9,000 addresses in the example above would be thrown out of their bucket almost as soon as they entered it.
Finally, in the same pull request, nodes also started remembering which nodes they previously connected to. Whenever they needed a new connection, they would toss a coin, and either connect to one of those, or pick a new one from one of the 256 buckets.