比特币节点默认给自动连接设了总数上限,其中入站槽位(别人主动连你)数量可观。当入站连接已经占满、又有新连接敲门时,节点不会直接拒绝来客,而是先在现有入站连接里开一场”淘汰赛”,选一个踢掉腾位置。这套逻辑集中写在 v31.0 源码的 node/eviction.cpp,它的设计动机和每一步选择都透露着对女巫攻击的防范,值得逐段读一遍。
淘汰赛的入场资格
候选池只装活跃连接,然后按固定顺序做保护性剔除:
第一步,持有免驱逐权限(noban 白名单)的连接直接离场,永不参选。第二步,所有出站连接(你主动连别人的)整体移出——驱逐永远只发生在入站侧,你的主动连接不会为了腾位被牺牲。
接下来是五条”特征保护”,每条都以攻击者难以伪造为选择标准:
- 按网组(netgroup,大致对应一段有归属关系的地址空间)确定性保留 4 个,具体保护哪几个由密钥化哈希决定,攻击者无法预判;
- 保留最小往返时延最低的 8 条——想把这项指标刷上去,得物理上把机器搬到离你更近的地方,成本高昂;
- 保留最近给你送过进入内存池的新交易的 4 条——想刷这个指标必须做对全网有用的事;
- 保留最多 8 条只中继区块且送过新区块的连接;
- 保留最近送过新区块的 4 条。
这几条的共同逻辑写在源码注释里:要让攻击者完成网络分区,就必须同时在所有指标上都优于诚实节点,难度乘法叠加。

按比例的第二层保护
特征保护之后进入配比保护:总数的一半要保住。其中最多四分之一按”弱势网络”分配——Tor、I2P、本地回环、CJDNS 的节点因为天然延迟高,在按时间排序的淘汰里总吃亏,所以先给它们留席位,人少的网络优先捡漏空位。剩下的保席给在线时长最久的连接,连接越久越安全。
全部保护做完,若还剩候选,再看 prefer_evict 标记——在 v31.0 里它对应来自被”劝退”名单地址的连接,创建入站连接时就打上;有标记的成为唯一候选,先牺牲它们。最后一步是网组多样性优先:统计哪个网组在候选里占的连接最多且成员最年轻,从这个组里挑最年轻的那条断开。同一家云厂商塞进来的十条连接,会先折损掉最新的一条。
什么时候会触发
驱逐只在”满员还要继续收”时发生。默认配置下自动连接总数有上限,入站槽位用尽后,新入站连接到来时节点先做一次淘汰赛;若一个都踢不掉(所有候选都被保护规则罩住),日志里会留下一行”failed to find an eviction candidate - connection dropped (full)“,然后直接拒绝新来客。源码注释把这设计意图写得很直白:这套策略要防的就是攻击者触发的人为网络分区——想孤立一个节点,必须同时在所有保护指标上都胜过诚实对端。而持有免驱逐白名单权限的连接从不参选。对端视角看到的”连上几秒被断开”,多数就是自己恰好落在候选池里最年轻、同网组最拥挤的那条。
被踢与踢别的观感差异
对普通运营者,这套机制的日常表现是:入站连接会随时间自然换血,但你自己发起的八条出站连接和跑了几天的老入站连接都很稳;刚连上来的入站连接最容易被后来者顶掉,这是”年轻先出局”规则的直接推论。想验证不靠猜:getpeerinfo 里能看到每条连接的建立时间与网组归属,日志在收到连接并触发驱逐时会写明选中了哪条连接。需要说明边界:这套顺序是 v31.0 源码的实现细节,历史版本阈值与保护项有过演化,核对旧版本请以对应版本的源码为准。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。