Abstract: This piece is written by Bitcoin Core contributor and researcher, Gleb Naumenko. Gleb is a recipient of 100x Group’s Bitcoin developer grant program. In this article Gleb writes about how Bitcoin Core connects to other nodes on the network. He first provides some background about the latest default connection policy in Bitcoin Core 0.20.0, before explaining why there may be weaknesses in the current system which could make it easier for malicious actors to initiate an eclipse attack. Gleb goes on to talk about a potential more robust experimental peer selection methodology called “asmap”. Gleb then provides instructions for testing this new feature. Testing would help in ensuring the best security practices become more accessible.
Illustration of Bitcoin Core’s new peer selection methodology
Call to action: testing and improving asmap
The new asmap feature to better diversify network peers is now available in Bitcoin Core 0.20. It even received some media coverage, but the feature is experimental, opt-in (not on by default) and currently targeted to advanced users.
This post attempts to help node operators use/test asmap. Use by node operators is highly desirable for testing this feature beyond a handful of core developers and paving the road to becoming the default mode for peer selection in future versions of Bitcoin Core. Be the first to use new security features of Bitcoin Core node, help make them secure and easy to use, and contribute to Bitcoin-related utilities!
We first cover the background and fundamentals, but if you already know about Border Gateway Protocol (BGP) and the ideas behind asmap, you can skip ahead to the call to action section.
Background: connectivity, eclipse attacks and spying
Every Bitcoin Core node nowadays by default establishes 10 connections (8 full connections and 2 block-relay-only connections). Those connections are used to send and receive transactions, blocks, and other less important messages.
Bitcoin Core 0.20.0 default connection policy
A node creates 10 outbound connections to ensure that a single (or a couple of) malicious peers can’t single-handedly control its access to the network. There are also inbound connections made by other nodes to the node. Since they are initiated by random nodes in the network and may belong to a single entity, they are much less relevant in terms of the node security.
The threat of being isolated from the honest nodes is known as an “eclipse attack”. It allows an attacker to steal funds [1, 2], spy on transactions, and reduce the efficiency of the victim’s mining. Eclipse attacks are a form of Sybil attack, because by running more malicious nodes an attacker increases their success rate.
Even if only 7 out of 10 victim’s outbound connections are controlled by an attacker, it’s still no good, because it makes linking transactions to the victim’s IP-address much easier.
To increase the cost of these attacks, Bitcoin Core started diversifying peer connections by what is called a netgroup bucketing. For instance, if you take a simple IP address like “172.16.254.1”, Bitcoin Core connects to at most one IP which looks like “172.16.any.any” (if possible).
The assumption was that it would be more difficult for an attacker to create fake nodes in different netgroups. This was based on the expectation that netgroups roughly correspond to regions and internet providers, therefore running fake nodes would require negotiating with many actors and make bulk deals less useful.
To be clear, we’re talking about an attacker running at least 1,000 fake nodes to get some chance to spy and probably at least 10,000 fake nodes to perform eclipse attacks, for the current network of reachable nodes. That’s why diversification is important; at this scale, there is a huge difference between renting an IP range from one provider and collecting a set of diverse IPs.
Unfortunately, the assumption that netgroups correspond to regions and internet providers no longer holds. Over the past years, IPv4 addresses have become more fluid, in the sense that they are traded between entities and resulting mapping is now in many cases near-random. For example, Amazon now controls many IP ranges.
A New Solution: asmap
To achieve better peer diversity we need to use a scarcer, less fluid property than netgroups. Recent research has suggested we diversify instead by Autonomous System Number (ASN). An ASN usually represents several smaller ISPs and is indeed a relatively scarce property of Internet nodes currently, at least as scarce as netgroups used to be.
Fortunately, obtaining ASN data is not difficult. According to the current operation of the BGP protocol, every router (including the one you have at home) can derive a path to a particular IP by jumping through ASN hops.
To ensure the filter is more effective, we not only look at the final ASN that owns a given IP address; we also consider the whole path in terms of ASN hops before reaching the target.
We describe an Autonomous System (AS) as mapped if it is the first AS acting as a gateway to multiple paths to a target, a quality that confers it the ability to single-handedly control what the target node receives and sends (if unauthenticated, which is the case for Bitcoin Core currently). In some of the documentation we call it a bottleneck.
The result of this process is that we obtain a list of IP-to-ASN mappings — an autonomous system map. We therefore call the project asmap.
The asmap software required to diversify by AS is now available. It includes:
- bitcoin-asmap utility: the code for compressing IP<->ASN mappings into a much smaller asmap file (from 200Mb down to 1 Mb) to make it easier to distribute the map and use it on constrained devices
- asmap-rs: a library for generating IP<->ASN mappings using open source Border Gateway Protocol (BGP) data, instead of computing a path locally
These tools are necessary to make the experience with asmap secure and easy.
One may also take a look at the asmap integration into Bitcoin Core, discussed in the review club.
Call to action
The best way to help is to just use asmap! Here are the steps:
|0||Make sure you understand the risks associated with using asmap: the feature is still experimental, so it is possible that due to a bug a node using asmap would be easier to attack (e.g., eclipse). Use at your own risk, ideally with a non-production instance.|
|1||For the most basic experience, just install Bitcoin Core 0.20 and download a sample asmap file here. Go to step 3.|
|2||For the advanced experience (much more useful for us here), take the following steps: |
|3||Start your testing Bitcoin Core node with the `-asmap=<filepath>` config option pointing to the location of your compressed asmap file. You can run `./src/bitcoind -help | grep -A4 asmap` from the root of your Bitcoin Core repository to see the help doc.|
|4||Take a look at the debug log of your node to see that asmap worked properly (e.g. grep for `asmap`, `mapped` and compare it with what you expected in terms of the asmap logic).|
|5||You can see the per-peer AS mappings with either the new `mapped_as` field in the `getpeerinfo` RPC, or in the GUI “Peers” window by clicking on a peer and looking at the “Mapped AS” field located at the bottom of the peer details on the right.|
|6||(Optional) Keep a node running and monitor the debug log over some time (maybe a couple times a week) by grepping for `mapped`, `asmap` and `bucket` or with a script.|
Don’t hesitate to try different options/configurations (for example, download data only from some specified RIPE RIS endpoints, as described in the asmap-rs instructions).
Then, file issues on GitHub, share feedback, comment on the bitcoin-asmap PR to Bitcoin Core! My email is naumenko dot gs at gmail dot com.
The asmap tools could also use some love from developers willing to contribute!
- Find a bug while testing (see previous section) and open an issue (perhaps followed by a PR to fix it)
- Work on an issue from the list of issues
- Review the source code and pending PRs
- Attempt to break something with malformed input data
- Improve the efficiency, logging, user experience, etc.
The code itself is short and easy, but looking into the implementation would require some knowledge of:
- Internet protocols, BGP and rust (for asmap-rs)
- Algorithms and compression (for bitcoin-asmap)
One could also re-implement the whole thing from scratch, but at this point I think we should not disperse our attention across multiple redundant implementations.
The most advanced users might want to feed asmap data from their own router to bitcoin-asmap compressor. It might require some pre-formatting, because bitcoin-asmap works only with a specific input. If you succeed at this, please share your experience (ideally, a full cycle, not just the compression) in the PR comments or elsewhere.
I’m grateful to Jon Atack, Greg Sanders and Michael Ford (fanquake) for reviewing this article.
Gleb Naumenko, Bitcoin Core Developer