自己ホスティングで実現するXPUBの管理方法
落ち着く気配のない円安も相まって、久々にBTC価格(円建て)がATHしました。嬉しいニュースである一方、相場が盛り上がると、それに比例してハッカーの活動が活発化し、不正流出やハッキング被害は増加する傾向にあります。
BTCの管理方法(特にコールドウォレット)については日々進化していますが、XPUBの取り扱いに関しては、依然として多くの方がサードパーティのウォレットに頼るケースがほとんどではないでしょうか。コールドウォレットに保管しているBTC残高やトランザクションを把握しておくために、XPUBをスマートフォンのウォレットに登録する、といった具合です。
秘密鍵やニーモニックとは異なり、XPUBには流出や漏洩による直接的なセキュリティリスクはありませんが、その一方で以下のようなリスクが伴います。
- プライバシーの侵害: XPUBが第三者に共有されると、その鍵に紐づくトランザクションとBTC残高を全て閲覧されてしまいます。
- 攻撃対象になるリスク: 保有しているBTC残高が明らかになることで、特に高額なBTC保有者は、悪意のある第三者からの攻撃にさらされるリスクが高まります。
例えば、XPUBがウォレットプロバイダーから漏洩したり、プロバイダーに悪意のある者がいた際、XPUBに関連するIPアドレスやメールアドレスなどから、ソーシャルエンジニアリング等の攻撃の対象になりえます。
こういった事象は実際に起こりうる、あるいは既に起きていると考えられます。
XPUBの管理をサードパーティに頼らずに、自己完結型で実現できれば、こうしたリスクは大幅に低減できます。そこで今回は、私が実践しているXPUBの管理方法を記事にしたいと思います。
1. システム構成
以下のような構成を採用することで、外部に依存することなくXPUBの管理・監視が可能です。
+----------------------------------------+
| Hosting Server |
| |
| +----------------+ |
| | Bitcoin Core | |
| +--------+-------+ |
| | |
| +--------v-------+ |
| | NBXplorer | |
| +--------+-------+ |
| | |
| +--------v-------+ |
| | Block-Alert | |
| +--------+-------+ |
| | |
| +--------v-------+ |
| | ntfy | |
| +----------------+ |
+----------------------------------------+
^
|
[VPN]
|
v
+----------------+
| Smartphone |
+----------------+
|
v
[User]
- Bitcoin Core
- Bitcoinのフルノード。
- Bitcoin ネットワークと同期し、ブロックデータを管理・保存する。
- NBXplorer
- NBitcoinをベースとしたUTXO追跡ツール。
- Bitcoin Coreから取得したブロックデータを基に、XPUBから生成されるアドレスのUTXOを監視し、新たなトランザクションの発生をリアルタイムで検出する。
- Block-Alert
- 上記の構成を実現するために、自分が作成したNBXploerとntfyのパイプとなるツール。レポジトリはこちら。
- ユーザーが指定したXPUBをNBXplorerに登録し、更新を購読する。トランザクションの更新の検知と定期的な残高レポートを実行し、Ntfyに通知リクエストを送信する。
- ntfy
- プッシュ通信を送受信することができるOSS。自分でサーバーをホストできる。
- Block-Alertからの通知リクエストを受けて、スマホにプッシュ通知を送信する。
2. データフロー
上記の構成で実行されるXPUBの登録から更新の受け取りまでの、一連のフローの解説です。
- Block-Alertを通じて、指定したXPUBをNBXplorerに登録し、更新を購読。
- 新しいTxをNBXplorerが検出すると、Block-AlertにTxデータを送信。
- Block-Alertが受け取ったTxデータから通知データを作成。
- ntfyサーバーに通知データを送信。
- ntfyサーバーからVPNを通じてスマートフォンにプッシュ通知を送信。
このフローにより、自己ホスティング環境内でXPUBを管理し、コールドウォレットのBTCの状態をリアルタイムで監視することが可能になります。
3. 導入手順
すべてのソフトウェアの導入と設定を記事にすると、かなりの長文になってしまうので、ここではBlock-Alertの導入に限定したいと思います。それ以外は公式ドキュメント等を参照してください。有料部分ではUmbrelを利用してる方向けに、より簡単な導入方法を紹介しています。
ntfyの導入の注意点として、通知を受け取るデバイスがiOSの場合、サーバーに以下の項目を設定する必要があります。
upstream-base-url: "https://ntfy.sh"
base-url: ntfyサーバーのURL
また、サーバーとスマホ間の通信にはVPNを使用するので、それぞれにセットアップしてください。導入が簡単なので、ノードランナーにも御用達のTailscaleがおすすめです。
1. Node.jsのインストール
以下のコマンドを実行してNode.jsをインストールします。ここではnvm
を使用してv20.18.0(LTS)
をインストールします。
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash
$ nvm install 20
$ node -v
v20.18.0
$ npm -v
10.8.2
2. Block-Alertのインストール
レポジトリをクローンします。
$ git clone https://github.com/btk080428/Block-Alert.git
$ cd Block-Alert
パッケージをインストールしてbuildします。
$ npm install
$ npm run build
以下の環境変数を設定します。環境変数はBlock-Alert/
に.env
を作成するか、node
のプロセス起動時に直接指定してください。(node scripts/createEnv.js
で.env
の作成を簡略化できます。ターミナルから各項目を入力してください。)
NBXPLORER_URL= NBXplorerのURL
EXTENDED_PUBKEY= 登録するXPUB
BALANCE_REPORT_INTERVAL_MS= 残高レポートを実行するインターバル(ミリ秒)
NBXPLORER_COOKIE_PATH= .cookieファイルのパス(オプショナル。NBXplorerを--noauthで起動することで省略可能)
NTFY_URL= NtfyのURL
NTFY_TOPIC= 通知の送受信のためのTOPIC名
NTFY_USER= ntfyのユーザー名 (オプショナル。認証有効時のみ)
NTFY_PASSWORD= パスワード (オプショナル。認証有効時のみ)
EXTENDED_PUBKEY
はNBXplorerのフォーマットで設定してください。ウォレットの仕様によっては取得できる拡張公開鍵がzpub
などの場合があるので、WebのConverterか、node scripts/convertXpub.js
を実行して適宜変換してください。
NTFY_TOPIC
は英数字(a-z、A-Z、0-9)、ハイフン(-)、アンダースコア(_)を含む最大64文字の文字列が使用できます。ntfyの認証を有効にしない場合はTOPICはパスワードのような役割を果たすので、単純なものではなく(e.g, notify)、複雑で予測しにくいもの(e.g, ZYx73Kw2_G23h7fdX)にすることが推奨されています。
このタイミングで通知を受け取るデバイスにntfyアプリをインストールして、設定したNTFY_URL
とNTFY_TOPIC
を指定してサーバーに接続してください。
設定できたらBlock-Alertを起動します。
$ npm run start
起動すると指定したXPUBのUTXO setのscanを開始します。NBXplorerのデフォルトでは起動時のBlock heightからしか情報を保持しないので、rescanを実行して過去に発生した残高を取得します。
[2024-10-28T16:11:42.031Z] [INFO] [Main] Initializing Application
[2024-10-28T16:11:42.035Z] [INFO] [ProcessManager] Starting all services...
[2024-10-28T16:11:42.035Z] [INFO] [NtfyService] Starting NtfyService
[2024-10-28T16:11:42.035Z] [INFO] [NtfyService] Starting Ntfy health check...
[2024-10-28T16:11:42.046Z] [INFO] [NtfyService] Ntfy health check passed
[2024-10-28T16:11:42.046Z] [INFO] [NtfyService] NtfyService started successfully
[2024-10-28T16:11:42.046Z] [INFO] [NBXplorerService] Starting NBXplorerService
[2024-10-28T16:11:42.046Z] [INFO] [NBXplorerService] Starting NBXplorer health check...
[2024-10-28T16:11:42.111Z] [INFO] [NBXplorerService] NBXplorer health check passed
[2024-10-28T16:11:42.187Z] [INFO] [NBXplorerService] Tracked extended public key: tpubD6NzVbkrYhZ4X3cxCktWVsVvMDd35JbNdhzZxb1aeDCG7LfN6KbcDQsqiyJHMEQGJURRgdxGbFBBF32Brwb2LsfpE2jQfCZKwzNBBMosjfm
[2024-10-28T16:11:42.195Z] [INFO] [NBXplorerService] Connected to NBXplorer WebSocket
[2024-10-28T16:11:42.195Z] [INFO] [NBXplorerService] Subscribed tpubD6NzVbkrYhZ4X3cxCktWVsVvMDd35JbNdhzZxb1aeDCG7LfN6KbcDQsqiyJHMEQGJURRgdxGbFBBF32Brwb2LsfpE2jQfCZKwzNBBMosjfm to NBXplorer
[2024-10-28T16:11:42.195Z] [INFO] [NBXplorerService] Starting UTXOs scan for extended public key...
スキャンが完了するとntfyにセットアップ完了メッセージと、
Block-Alert setup completed successfully 👍
初回の残高レポートがプッシュ通知されます。
🔍 Balance Report
🔑 XPUB: tpubD6NzVb...BMosjfm
|
├─📍 tb1q3jrh...f7zs3xqe
├─ Unconfirmed: 0 BTC
└─ Confirmed: 0.00001 BTC
|
├─ 📍 tb1qr6ew...e8cc43z5
├─ Unconfirmed: 0 BTC
└─ Confirmed: 0.00004 BTC
|
└─ 📍 tb1q6rz2...9pqc4vkt
├─ Unconfirmed: 0 BTC
└─ Confirmed: 0.00016621 BTC
├─ ⏳ Total Unconfirmed: 0 BTC
└─ ✅ Total Confirmed: 0.00021621 BTC
セットアップ完了以降は、登録したXPUBに関連するTXが発生すると、リアルタイムでプッシュ通知が送信されます。
📝 TXID: 70f6738036...4688828cc7
├─ ⏳ Status: Unconfirmed
├─ 💵 Type: Received
├─ 💰 Amount: 0.0001 BTC
├─ 🕒 Timestamp: 2024/1/22 18:31
└─ 🔑 XPUB: tpubD6NzVb...BMosjfm
[View on mempool.space]
以上で導入は完了です。
有料部分では、5分で完了するUmbrelでのセットアップ方法を紹介します。