跳至主要內容
高級

AddrMan

深入了解 Bitcoin Core 的地址管理器,如何發現、儲存和選擇對等節點地址。

12 分鐘

什麼是 AddrMan?

AddrMan(Address Manager)是 Bitcoin Core 的地址管理系統,負責發現、儲存和選擇對等節點地址。 它使用精心設計的數據結構來抵抗 Eclipse 攻擊,確保節點能夠連接到真實的比特幣網路。

AddrMan 的職責

地址收集

  • • 從 DNS seeds 獲取初始地址
  • • 接收對等節點廣播的地址
  • • 記錄成功連接的節點

連接選擇

  • • 選擇要連接的節點
  • • 平衡新舊地址
  • • 防止連接偏向

雙表架構

AddrMan 結構:

┌──────────────────────────────────────────────────────┐
│  New Table (1024 buckets × 64 entries)               │
│  ├── 儲存從未成功連接過的地址                          │
│  ├── 按來源 IP 分組(防止單一來源控制)                 │
│  └── 最多 65,536 個地址                              │
├──────────────────────────────────────────────────────┤
│  Tried Table (256 buckets × 64 entries)              │
│  ├── 儲存成功連接過的地址                             │
│  ├── 按目標 IP 分組                                  │
│  └── 最多 16,384 個地址                              │
└──────────────────────────────────────────────────────┘
interface AddrInfo {
  addr: NetAddress;      // IP:Port
  source: NetAddress;    // 誰告訴我們這個地址
  lastTry: number;       // 最後嘗試連接時間
  lastSuccess: number;   // 最後成功連接時間
  nAttempts: number;     // 連接嘗試次數
}

class AddrMan {
  private newTable: AddrInfo[/* 1024 */][/* 64 */];
  private triedTable: AddrInfo[/* 256 */][/* 64 */];
  private nKey: Buffer;  // 隨機密鑰,防止預測

  // New 表的 bucket 選擇(基於來源 IP)
  getNewBucket(addr: NetAddress, source: NetAddress): number {
    const sourceGroup = this.getGroup(source);  // /16 網段
    const hash = this.hash(this.nKey, sourceGroup, addr);
    return hash % 1024;
  }

  // Tried 表的 bucket 選擇(基於目標 IP)
  getTriedBucket(addr: NetAddress): number {
    const addrGroup = this.getGroup(addr);
    const hash = this.hash(this.nKey, addrGroup);
    return hash % 256;
  }

  // 標記連接成功,移到 Tried 表
  good(addr: NetAddress): void {
    const info = this.findInNew(addr);
    if (!info) return;

    this.removeFromNew(addr);
    const bucket = this.getTriedBucket(addr);
    info.lastSuccess = Date.now();
    this.triedTable[bucket][position] = info;
  }
}

Eclipse 攻擊防護

什麼是 Eclipse 攻擊?

攻擊者控制受害節點的所有連接,將其與真實網路隔離。

  • • 雙花攻擊 - 讓商家看到假的確認
  • • 自私挖礦 - 延遲受害者看到新區塊
  • • N-confirmation 攻擊 - 製造假的確認深度

防禦機制

  • 1
    基於來源的 Bucket 分配

    單一來源無法填滿所有 bucket

  • 2
    隨機密鑰 (nKey)

    每個節點不同,攻擊者無法預測 bucket

  • 3
    網段多樣性

    出站連接確保來自不同的 /16 網段

  • 4
    錨定連接

    重啟時優先連接最後成功的節點

持久化

# 地址數據庫
~/.bitcoin/peers.dat

# 錨定檔案(重啟時優先連接)
~/.bitcoin/anchors.dat

# 查看已知地址
bitcoin-cli getnodeaddresses 10

# 手動添加節點
bitcoin-cli addnode "192.168.1.100:8333" "add"

# 查看連接的節點
bitcoin-cli getpeerinfo | jq '.[].addr'

配置選項

# bitcoin.conf

# 手動指定節點
addnode=192.168.1.100:8333

# 只連接到指定節點
connect=192.168.1.100:8333

# DNS seeds(預設開啟)
dnsseed=1

# 固定 seeds
fixedseeds=1

# 最大連接數
maxconnections=125

總結

  • 雙表架構:New 表存新地址,Tried 表存驗證過的地址
  • Eclipse 防護:基於來源分組、隨機密鑰、網段多樣性
  • 錨定連接:重啟時優先連接已知可信節點
已複製連結
已複製到剪貼簿