アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

AWS上にbitcoin-seederを立てる

今回はDNSを使ったことはあるけど設定したことがないNetwork初心者の僕がbitcoindns-seederを立てたので、その時の作業ログ的なものをまとめたいと思います。seederのプログラムはこちらを使いました。
github.com

DNS seederとは

bitcoinのnodeを起動するとまず最初に、nodeは他のnodeと接続してblockを取得する必要があります。この時、現在activeなfull nodeのIPリストを返してくれるのがdns seederになります。
今まで僕はactive nodeのIPリストはハードコーディングされたseederのアドレスに対してbitcoin p2p protocolのaddrメッセージで収集しているものと思っていたのですが、実際はDNS問い合わせで収集しています。
つまり以下の様にnslookupで問い合わせすることでもactive nodeのIPリストが取得できます。

$ nslookup dnsseed.bluematt.me

DNS seederについてのより詳しい内容は以下を参照してください。
Satoshi Client Node Discovery - Bitcoin Wiki

今回の作業内容

今回は簡単にいえばちょっと特殊な権威DNSを立てることになります。なので次の様な作業を行いました。

  1. dns seeder用のEC2インスタンスの起動
  2. dns seederのbuild
  3. seederがIPを収集できているか確認
  4. DNSサブドメインを切る
  5. dns seederに移譲するためのサブドメインを切る
  6. DNS問い合わせで外部からIPリストが取得できるか確認

dns seeder用のEC2インスタンスの起動

今回は一番シンプルなEC2インスタンスを選択しました。最初は開発環境と本番環境の差異がなく気軽に扱える様にdockerで環境構築しようとしていましたが、いかんせんdockerの知識が足りずにうまくいかなかったためEC2インスタンス上で直接dns seederを動かすことにしました。
AMIはdevelop系のパッケージも含まれてるほうが良さそうなので2番目のamazon linuxのimageを選択します。

インスタンスタイプは特にマシンパワーは使わないのでt2.microを選択します。
DNSの問い合わせを受け付けできる様にしないといけないので、インスタンスにはsecurity groupでUDP 53番ポートを開けておく必要があります。

あとはssh等ができる様に自分のIPからのフルアクセスか22番ポートの解放など適切に設定してください。

dns seederのbuild

EC2インスタンスが起動したら、早速dns seederをbuildします。
必要なlibraryをインストールしてからrepositoryをgit cloneしてmakeします。具体的には以下のコマンドをそれぞれ実行してください。

# install necessary dev tools for make.
sudo yum update -y
sudo yum groupinstall -y "Development Tools"
sudo yum install -y boost-devel openssl openssl-devel

# clone project
git clone https://github.com/sipa/bitcoin-seeder
cd bitcoin-seeder

# build
make

# install
sudo cp ./dnsseed /usr/bin/dnsseed

seederがIPを収集できているか確認

buildが正常に終了したら実際に実行してIPが収集できるかまずは確認します。
この作業ではterminalを2つ用意して片方でdns seederの起動実行、もう片方でローカルでのdns問い合わせを行います。

最初に以下のコマンドでdnsseedを起動します。

[ec2-user@ip-10-100-101-157 ~]$ sudo dnsseed -h localhost -n localhost -m nakajo@chaintope.com

次に別のterminalでdigコマンドで収集したIPの一覧が帰ってくるか確認します。無事に収集できている場合は以下の様な結果が帰ってきます。

[ec2-user@ip-10-100-101-157 ~]$ dig localhost @localhost

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.58.amzn1 <<>> localhost @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26971
;; flags: qr aa rd; QUERY: 1, ANSWER: 26, AUTHORITY: 1, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;localhost.			IN	A

;; ANSWER SECTION:
localhost.		3600	IN	A	35.198.151.21
localhost.		3600	IN	A	103.66.180.5
localhost.		3600	IN	A	181.30.30.53
localhost.		3600	IN	A	112.82.114.20
localhost.		3600	IN	A	70.179.154.23
localhost.		3600	IN	A	88.4.220.44
localhost.		3600	IN	A	212.9.185.194
localhost.		3600	IN	A	88.99.185.148
localhost.		3600	IN	A	88.82.181.44
localhost.		3600	IN	A	46.101.96.79
localhost.		3600	IN	A	13.230.26.197
localhost.		3600	IN	A	174.52.197.109
localhost.		3600	IN	A	87.79.94.221
localhost.		3600	IN	A	201.46.21.248
localhost.		3600	IN	A	35.187.203.246
localhost.		3600	IN	A	91.154.23.91
localhost.		3600	IN	A	31.48.33.236
localhost.		3600	IN	A	112.74.177.26
localhost.		3600	IN	A	70.70.136.159
localhost.		3600	IN	A	216.197.76.39
localhost.		3600	IN	A	35.199.54.227
localhost.		3600	IN	A	193.23.181.135
localhost.		3600	IN	A	194.106.216.20
localhost.		3600	IN	A	50.3.73.114
localhost.		3600	IN	A	136.243.105.206
localhost.		3600	IN	A	54.36.234.240

;; AUTHORITY SECTION:
localhost.		40000	IN	NS	localhost.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Thu Oct  4 01:45:02 2018
;; MSG SIZE  rcvd: 466

DNSサブドメインを切る

まず最初に以下を参考にしながらDNSサブドメインを切ります。サブドメインを切る理由はDNS設定にミスった時にrootドメインのゾーンファイルに影響を及ぼさない様にするためです。なのでこの作業は必須ではありません。
以下の記事を参考にしながら適当なサブドメインを切りました。
dev.classmethod.jp

dns seederに移譲するためのサブドメインを切る

次に、上記のサブドメイン以下にさらにdns seederに権限を移譲するためのサブドメインを切ります。
dns seederは起動すると権威DNSとして動きます。そのため、ゾーン情報の管理をdns seederに移譲する必要があります。

イメージとしては、seed.bitcoin.example.comというアドレスに問い合わせをした時に、dns seederが直接応答を返すようにしなければいけません。なので、dns seederへ与えるドメインのレコードはAレコードではなくNSレコードとして登録する必要があります。

上記を踏まえるとRoute53の設定は内容は以下の様になります。

赤字の部分がdns seederのための設定になります。example.comのrootドメインに関しては適宜自分のドメインに読み替えてください。

この設定では新しくseed.bitcoin.example.comというゾーンを定義し、そのゾーン情報についてはns.bitcoin.example.comが教えてくれますという定義になります。また、ns.bitcoin.example.comがどこにあるのかは次のAレコードでIPを指定しています。

ns.bitcoin.example.comのIPに先ほど立てたEC2インスタンスのpublic IPを指定します。つまり、dns seederはName Serverとして動作することになります。流れとしては、seed.bitcoin.example.comを問い合わせると、それについてはns.bitcoin.example.comに問い合わせてねと言われてそのIPを教えてもらいます。その後、ns.bitcoin.example.comにseed.bitcoin.example.comのIPを教えてねという問い合わせが飛んでくるので、この問い合わせに対してdns seederが収集したactive nodeのIPリストを返すという動きになります。

DNS問い合わせで外部からIPリストが取得できるか確認

publicなDNSへの設定も終わったので、上記のDNS設定で実際に外部からIPが取得できるか確認します。

まずはdnsseederを上記の設定のDNS問い合わせに対して応答できる様に、自身のhost nameと問い合わせの時に飛んでくるname serverのドメイン名を指定して実行します。具体定期に以下のコマンドになります。

sudo dnsseed -h seed.bitcoin.example.com -n ns.bitcoin.example.com -m nakajo@chaintope.com

DNS情報が十分に行き渡った後(だいたい2時間程度?)にnslookupで問い合わせをするとIPのリストが帰ってきます。
今度はpublicなDNSとして問い合わせ可能なのでEC2上ではなく任意の環境でdigで問い合わせてみると次の様な結果が表示されます。

以下は実際に僕が立てたdns seederへの問い合わせ結果です。

nakajo$ dig seed.tapyrus.dev.haw.biz

; <<>> DiG 9.8.3-P1 <<>> seed.tapyrus.dev.haw.biz
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62355
;; flags: qr rd ra; QUERY: 1, ANSWER: 24, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;seed.tapyrus.dev.haw.biz.	IN	A

;; ANSWER SECTION:
seed.tapyrus.dev.haw.biz. 3600	IN	A	35.195.168.234
seed.tapyrus.dev.haw.biz. 3600	IN	A	54.212.129.214
seed.tapyrus.dev.haw.biz. 3600	IN	A	51.15.93.131
seed.tapyrus.dev.haw.biz. 3600	IN	A	153.127.246.86
seed.tapyrus.dev.haw.biz. 3600	IN	A	188.209.52.95
seed.tapyrus.dev.haw.biz. 3600	IN	A	85.144.83.16
seed.tapyrus.dev.haw.biz. 3600	IN	A	35.178.57.206
seed.tapyrus.dev.haw.biz. 3600	IN	A	192.241.207.148
seed.tapyrus.dev.haw.biz. 3600	IN	A	35.241.231.155
seed.tapyrus.dev.haw.biz. 3600	IN	A	18.188.22.47
seed.tapyrus.dev.haw.biz. 3600	IN	A	18.222.116.234
seed.tapyrus.dev.haw.biz. 3600	IN	A	155.94.231.23
seed.tapyrus.dev.haw.biz. 3600	IN	A	36.110.15.202
seed.tapyrus.dev.haw.biz. 3600	IN	A	52.14.101.83
seed.tapyrus.dev.haw.biz. 3600	IN	A	81.34.237.176
seed.tapyrus.dev.haw.biz. 3600	IN	A	108.248.221.82
seed.tapyrus.dev.haw.biz. 3600	IN	A	35.240.108.5
seed.tapyrus.dev.haw.biz. 3600	IN	A	138.201.238.212
seed.tapyrus.dev.haw.biz. 3600	IN	A	128.199.202.168
seed.tapyrus.dev.haw.biz. 3600	IN	A	91.225.236.152
seed.tapyrus.dev.haw.biz. 3600	IN	A	47.96.111.40
seed.tapyrus.dev.haw.biz. 3600	IN	A	61.69.193.78
seed.tapyrus.dev.haw.biz. 3600	IN	A	95.216.23.174
seed.tapyrus.dev.haw.biz. 3600	IN	A	5.9.5.135

;; Query time: 408 msec
;; SERVER: 192.168.0.1#53(192.168.0.1)
;; WHEN: Thu Oct  4 11:53:23 2018
;; MSG SIZE  rcvd: 426

これで作業は完了です。