edit (@b10c): the title was originally “/Satoshi:29.1.0(dont-spam-me-bro)/ nodes?”.
Noticed these connections on both my outbound and inbound direction on various nodes: “/Satoshi:29.1.0(dont-spam-me-bro)/”
They appear to behave fairly normally, relaying 0-fee TRUC transactions in a package (precluding stock Knots 29.1), but I don’t know anything else about them.
I noticed I have two of my outbound slots of len (demo.peer.observer) connected to them. instagibbs mentioned to me he has 3 of his outbound slots connected to them on one of his nodes. This is worrying, as filling outbound slots should be hard to avoid eclipse attacks.
I’m not sure ASMap would be a substantial improvement over the current /16 mechanism. There is 10 peers to choose from 10k /16’s available. That’s roughly a (n / 10_000)^10 probability to connect to an attacker controlling n /16’s.
That said, it seems that it’s not what happens in practice. The Bitprojects guy controls only 12 /16’s. That a node would pick any of those 12 for 4 of its slots if it has heard about all /16’s available is essentially null. Could it be that somehow he found a way to bias DNS seeds towards his nodes, such as a node joining the network does not hear about many more /16’s than his?
I’ve set up some data collection on the number of outbound connections I have to the bitproject IPs (also inbound, but don’t seem to have gotten any inbounds from them).
Currently, three of my nodes have two of their outbounds to bitprojects:
Or maybe his addresses get rumoured a lot more? If the addresses a node will return to a GETADDR are randomly sampled among all known addresses, instead of first sampling by /16, then it seems that his nodes would be overly represented.
We don’t sample based on /16 - we sample based on address (and abort/get another sample if another outbound is from the same range). For example, if we have an addrman with 99 addresses from /16 range A and 1 address from /16 range B, we’ll pick an addr from A for our first peer with 99% probability.
So controlling a large number of addresses from a given /16 range does increase chances of being picked even if other nodes will only make one connection to that range.
I discussed this with a few people out of band, but just to share here this explains why we are seeing so many peers connect to the Bitprojects guy. My previous assumption on how this logic works:
Was incorrect, as Martin explained above. So it seems that if he was controlling just a few more /16’s, as well as a few thousands more “node” IPs then he would have a decent chance of eclipsing a node.
I find it surprising that AddrMan doesn’t work the way i expected it to, because it would make the probability of controlling all of a node’s outbound connections decrease exponentially in the number of connection slots. As far as i understand (and what i got from a quick discussion at the office) this is due to architectural limitations in AddrMan’s implementation. I’ve started looking into what it would take to implement what i suggest.
So it seems that if he was controlling just a few more /16’s, as well as a few thousands more “node” IPs
FWIW, getting control of a /16 and all its IPs costs millions of USD. But using IPv6 should make this much easier to scale.
This seems quite problematic and defeats almost any gains asmap affords?
Why would it defeat all the gains? You can easily get hundreds of IPs across 13 different /16 on AWS or any other larger hoster. Getting many ASNs and making hundreds of IPs available through them is a much higher bar. Also, there are less than 100k ASNs in use in global routing and getting a large number of them without a legitimate use-case would a considerable bureaucratic hurdle.
The issue is that with the current peer selection algorithm you don’t need a large number of them, just as many as we make outbound connections by default, or slightly more. The bitprojects guy already controls 12 /24’s spread across /16 boundaries and 3 or 4 AS’s. It does not seem completely unrealistic to me that he would be able to spin up a large number of (maybe fake) nodes in more than 10 net groups (either /16’s or AS’s).
And I am saying that 10 is a large number for ASNs at least relatively speaking. There are 2^96 /32s in IPV6 almost all available to use if you just put down a little bit of money.
On 2026-03-24 at around 9:20 UTC one of my nodes made five outbound connections to bitprojects nodes. It didn’t have any before. These connections are still active.
I have logs for this, so I can investigate a bit (when I find the time to do so) why exactly this happened.
edit: I had a brief look at the logs. It turns out the node had a brief network disconnect due to datacenter maintaince, lost all it’s peers, and when it came back, it choose to open 5 outbound connection to bitprojects…
update: all of these nodes are now shut down and will not return – intended outcome has been reached, proved the point, and it seems like everyone who needs to understand the severity/risk does see it now.
lmk any questions.
btw this entire infra I stood up cost about $2k/mo
=== Inbound TCP/8333 (bitcoin) Connection and Network Stats ===
Total unique destination IPs: 3042
Total unique destination /24 subnets: 12
Total destination subnets sharing /16 boundary: 0
Total ASNs: 3 <<< BTW this defeats asmap in current state
Total subnets advertised per ASN: 4
Total inbound connections: 80526
Total unique source IPs: 35127
=== Source IP Connection Thresholds ===
Source IPs with 8+ connections: 653
Source IPs with 10+ connections: 433
Source IPs with 12+ connections: 307
Source IPs with 16+ connections: 178
Source IPs with 32+ connections: 38
Source IPs with 64+ connections: 14
Source IPs with 512+ connections: 0
Source IPs with 2048+ connections: 0
Since Bitcoin Core nodes make by default 8 outbound-full-relay and 2 block-relay-only connections, I’m assuming every source with more than 10 connections is either a custom client trying to mass-connect to all IPs or multiple Bitcoin Core nodes making connections from the same host / IP.
This still leaves us with 220 nodes potentially making 8+ connections to you. The highest I’ve seen personally is 6 connections to bitprojects for a short while, which is still worrying.
Yeah this is why I split out these connection counts in this way. There were dozens of subnets and single IPs that spun up hundreds or thousands of connections, so I automated null routing those sources once crossing the 1024 threshold.
so at any point in time I believe there were hundreds of nodes that -only- connected to me, and that doesn’t sound good.
when the infra ran uninterrupted for 60+ days these single source counts were double or higher.
I should not be able to do something like this for $2k/mo.
@fjahr ASNs are incredibly easy to justify approval for from the RIRs, and cost about $500 each for the higher numbers if buying, less if the RIR is assigning them. Getting dozens of them is easy. Even easier if an attacker is willing to spin up multiple legal entities and set up org accounts w/ the RIRs.
Separately on the IP side, renting/leasing IP space in /24 blocks costs about $0.30-0.40/mo per IP when rented from a third party/non carrier. Even less cost when you’re willing to rent poor reputation IPs, which bitcoin does not care about.
I intend to spin up some ways to pull down the full BGP routing table via API (will also put the code on github, pulls from FRR, can be spun up on cloud providers that support BGP), I think it would be useful to query the full AS path of a given node and use that for warnings. In the case of what I stood up, all of the ASNs and subnets shared common AS path ASNs.
Related to this topic, I opened an issue on the Bitcoin Core repository back in December about updating our peer selection algorithm to be more robust against an attacker “simply” spinning up a high number of nodes across a small number of net groups.
If there is renewed interest in addressing these concerns, i would welcome some feedback there.