ブロックチェーンを利用して非中央集権 (decentralized) 型の DNS を構築を目指すプロジェクト、 Handshake を知った。このプロジェクトは、DNS が本質的に ICANN が管理するルートサーバーによって集中管理されていることを問題として [1] 定義し、それを解決するためにドメイン名の情報をブロックチェーンに書き込むことで、P2P で 非中央集権型 の DNS を実現しようというものだ。

DNS root server
DNS roo...
.com
.com
.jp
.jp
example1.com
example...
example2.com
example...
.co.jp
.co.jp
.ne.jp

.ne.jp
a.co.jp
a.co.jp
b.co.jp
b.co.jp
a.ne.jp
a.ne.jp
b.ne.jp
b.ne.jp
Traditional DNS
Traditional DNS
Top Level Domain (TLD)
Top Level Domain (TLD)
.mecab: 192.0.2.1
.example: 198.51.100.1
.foobar: 203.0.113.0
.mecab: 192.0.2.1...
.mecab
.mecab
a.mecab
a.mecab
b.mecab
b.mecab
192.0.2.1
192.0.2.1
.example
.example
a.example
a.examp...
b.example
b.examp...
198.51.100.1
198.51.100.1
Handshake DNS
Handshake DNS
Top Level Domain (TLD)
Top Level Domain (TLD)
Viewer does not support full SVG 1.1

通常のの DNS と、Handshake による DNS の比較。前者では Top Level Domain (TLD) がルートサーバーによって管理されるのに対し、後者ではルートサーバーは存在せず、ブロックチェーンによる合意によって TLD を管理するネームサーバーが記録される。TLD 以下は通常の仕組みと同じだ。

公式ページでも "experimental" と書かれているようにまだまだ発展途上のプロジェクトではあるが、公開されているフルノードは Handshake 内のドメイン名を解決するリゾルバとして動くようになっており、本質的な機能は既に実装されている。

当然ながら、Handshake 上のドメイン名は通常の DNS サーバーからは解決されないため、例えばこのドメイン名を使って Web サイトを閲覧したい場合、ネットワークの設定を変更し、対応した DNS サーバーを利用するように設定する必要がある。一般のユーザーが Handshake DNS を透過的に利用する日はとても遠いだろうし、そもそもそのような日が来るかは分からないが、それでも期待できる、ワクワクするプロジェクトだと感じた。

そこで、実際に Handshake ドメイン名 mecab を取得して、またそのドメインのゾーン情報を管理する権威サーバーを構築してみた。Handshake DNS を解決できる環境であれば、 http://mecab/ でホームページ http://misosi.ru/ と同じコンテンツを閲覧できる。環境が無ければ、ゲートウェイ hns.to を使い、http://mecab.hns.to/ で閲覧できる。

本記事では、Handshake ドメインを取得するまでの一連の流れを紹介する。

Handshake ドメイン名の取得

まずは、ドメイン名を取得する方法について説明する。通常のドメイン名は先着順で取得されるが、Handshake ドメイン名はオークション形式で取得される。つまり、あるドメイン名を欲しいと思った人は一定期間のオークションを開始し、期間内に最高入札額を提示した人がドメインを取得する。このオークションはだれでも入札できるため、最初にそのドメイン名を欲しいと思った人が落札できない場合もある。

また、Handshake 上で取得できるドメインは全て TLD になる。取得した TLD 配下のドメインについては、通常の DNS のように自分でネームサーバーを設定することになる。

1. HNS の入手

入札には、Handshake のネイティブトークンである HNS を使う。まずは HNS を入手しなければならない。基本的には仮想通貨取引所で購入することになるだろう。ここでは HNS の取引について詳しくは述べないが、BittrexMXC.COM などで取り扱われている。

なお、2019 年 2月 時点で 15 人以上のフォロワーがいた GitHub ユーザーには 4246 HNS の無料配布が行われている(!) Claim HNS に書かれている手順で受け取ることができる。後でやり方についての記事を書くかもしれない。

2. HSD のインストール

Handshake のフルノードである hsd をインストールする。ソースコードをクローンして、npm install --production すればよい。

$ git clone https://github.com/handshake-org/hsd.git
$ cd hsd
$ git checkout v2.4.0 # そのときの最新のバージョンにする
$ npm install --production

インストール後、hsd ディレクトリで

$ ./bin/hsd --log-level info

とすると hsd が起動する。hsd はフルノードなので、全てのブロックをダウンロードしてネットワークと同期する。同期が終わるまでしばらく(数時間)待つ。

以下のコマンドはローカルで起動中のフルノードに対して指示を出すコマンドになる。このため、hsd をバックグラウンドで動かしたまま実行する必要である。

$ ./bin/hsw-cli account get default | grep receiveAddress

とすると自分のアドレスが表示される。取引所で入手した HNS はこのアドレスに送るとドメイン名取得のために使えるようになる。

3. オークション

この節では、ドメイン名オークションの開催から入札、入札した場合のドメイン情報登録の方法や、落札できなかった場合の入札金額の回収を、順を追って説明する。ネットワークを操作するためのコマンドは hsd-clihsw-cli の両方があって紛らわしいが間違えないように注意したい。

3.1 ドメイン名の現在の状態を確認する

まず自分が欲しいドメイン名が取得可能かを調べる。

$ ./bin/hsd-cli rpc getnameinfo zettaini-hosikunai-domein

で、ドメイン名 zettaini-hosikunai-domein の状態が表示される。

{
  "start": {
    "reserved": false,
    "week": 27,
    "start": 29232
  },
  "info": null
}

上記のように、start オブジェクトが存在し、かつ start.reservedfalse の場合は、ドメイン名が現在空いていることを意味するので、オークションを主催して入札することができる。start.reservedtrue の場合、そのドメインは既存の有名なサイト [2] のために予約されているため入札することはできない。(例: google)

$ ./bin/hsd-cli rpc getnameinfo google
{
  "start": {
    "reserved": true,
    "week": 33,
    "start": 35280
  },
  "info": null
}

start が存在しない場合、そのドメインは既に取得されているか、またはちょうどオークションが開催されている。state フィールドが OPENING または BID の場合は、ちょうど現在オークションが開催されているところなので、直接入札できる。それ以外の場合、そのドメインは他の人に取得されているため諦めるしかない。

ドメインの状態を確認するために、Handshake のブロックチェーンエクスプローラーを使うのも良いだろう。例えば、https://e.hnsfans.com/ や、 https://hnscan.com/ がある。(e.hnsfans.com で mecab TLD の取得状況を見る例

3.2 オークションを開催する。

sendopen を発行することでオークションを開催する。

$ ./bin/hsw-cli rpc sendopen zettaini-hosikunai-domein
{
  "hash": "aa5f93ef1...",
  "witnessHash": "dbd7943fc...",
  "mtime": 1622228535,
  "version": 0,
  ...
}

成功すると、送信したトランザクションの詳細が表示される。Handshake ブロックチェーンでは、およそ 10 分ごとにブロックが生成されるため、最長で約 10 分ほど待つと、このトランザクションがネットワークで認識される。

ネットワークで認識されていれば、getnameinfo で確認すると、stateOPENING になっているはずだ。

OPENING になった後、実際に入札が可能な BIDDING フェーズになるまでさらに 37 ブロック、約 6 時間 かかる。ただ待つだけだ。

3.3 オークションに入札する

ドメインの入札ステータスが BIDDING になったらいよいよ入札を行う。落札者による確実な支払いを保証するため、入札時点で入札金額を一時的にロックアップし、落札できなかった人はオークション終了後にロックアップ額を回収する形を取っている。

$ ./bin/hsw-cli rpc sendopen zettaini-hosikunai-domein 10 100

上の例は、ドメイン名 zettaini-hishikunai-domein に対して、10 HNS で入札し、100 HNS のブラインドを追加する。この操作により、計 110 HNS が一時的にロックアップされる。ブラインドは、実際の入札額を隠すために追加でロックアップする額だ。

Handshake のオークションは、2 位価格封印入札(ヴィックリーオークション)という形式で行われる。入札額を伏せて入札した上で、最も高額の入札をした人が落札できる。しかしブロックチェーン上で全てのトランザクションが公開されるため、後に入札する人は先に入札した人の入札額を知ることができる。この問題に対処するため、任意のブラインドを追加して資金をロックアップすることができるようになっている。上記の例では、他の人からは 110 HNS をロックアップした入札者がいることが分かるが、実際の入札額は 110 HNS 以下であること以外は不明になる。

Blind

100 HNS
Blind...
10 HNS
10 HNS
Bid
Bid
Lock up

110 HNS
Lock up...
Lock up

50 HNS
Lock up...
Lock up

20 HNS
Lock up...
Bid
Bid
Lock up

80 HNS
Lock up...

Bid
? HNS

Bid...

Bid
? HNS

Bid...

Bid
? HNS

Bid...
Viewer does not support full SVG 1.1

入札の概念図。ブラインドを追加して資金をロックアップすることで、実際の入札額を不明瞭にできる。左の入札したユーザーは、他の入札に関して合計のロックアップ額を知ることしかできない。

2 位価格封印入札では、最高入札額を提示した入札者が、次点の入札額を支払って落札する。例えば、オークションの参加者が 1000 HNS を入札した A と 10 HNS を入札した B の 2 人のみだった場合、A が 10 HNS で落札する。また、自分以外に入札者がいなかった場合、無料で落札できる。このオークション形式では、自分がそのドメイン名に感じる価値の範囲内においては、入札額を高く設定することで損はしないはずなので、入札額を変に渋って他の人に落札されてしまわないようにしたい。

なお、最高額入札者が複数存在した場合、最高額入札者の中でランダムに落札者が決定する。これを防ぐため、0.1 HNS のような端数を追加すると、万が一このようなケースが起こったときに救われるかもしれない。

最後に、落札者の決定するプロセスにおいて、ブラインドは完全に無視されることに注意したい。例えば上記のような複数の最高入札額が現れたケースでも、ブラインドが多かったからといって有利になることはない

入札期間は 720 ブロック(約 5 日)だ。この間に入札する必要がある。入札額を追加したい場合、sendbid を重ねて実行することで、再入札できる。ただし、前の入札は取り消されず、別々の入札者として扱われる。(例えば、入札者が実際は自分だけだったとしても、 2 回入札した場合は、無料で落札できない)

3.4. 入札額を開示する

入札期間が終わり、ステータスが REVEAL になると、sendreveal コマンドで実際の入札額を開示できる。

$ ./bin/hsw-cli rpc sendreveal zettaini-hosikunai-domein

この操作により、ブラインド分のロックアップが解除され、手元に戻ってくる。各入札者が reveal を行い次第、ブロックチェーンエクスプローラーを見ると実際の入札額が分かるようになる。

REVEAL 期間は 1440 ブロック(約 10 日)あるこの期間に reveal 操作を行わないと、ブラインドを含む全てのロックアップ額が没収(ネットワーク上で焼却)されてしまうので確実に reveal するようにしたい。

REVEAL 期間が終わると、ステータスは CLOSED となる。

3.5. (A) ドメインのレコードを登録する。

ステータスが CLOSED に変わった後、オークションに競り勝ち、無事そのドメインを取得することができていたら、sendupdate コマンドで DNS リソースレコードを登録できる。これにより、登録したドメイン名を解決する権威 DNS サーバーを指定できる。

詳細は省略するが、単純な例では以下のようになる。

$ ./bin/hsw-cli rpc sendupdate zettaini-hosikunai-domein $(cat <<<EOF
{
  "records": [{
    "type": "NS",
    "ns": "ns1.example.com.",
  }]
}
EOF
)

権威 DNS サーバーが、通常の DNS サーバーで解決できるホスト名 ns1.example.com を持っている場合は上記のように指定できる。

そうでない場合、

$ ./bin/hsw-cli rpc sendupdate zettaini-hosikunai-domein $(cat <<<EOF
{
  "records": [{
    "type": "GLUE4",
    "ns": "ns1.zettaini-hosikunai-domein.",
    "address": "203.0.113.1"
  }]
}
EOF
)

として 203.0.113.1 の IP アドレスを持ち、ns1.zettaini-hosikunai-domein. の内部名で解決される権威ネームサーバーを指定できる。

初めて sendupdate を実行した際、実際に入札した価格と、落札額(=次点入札者の入札額)の差額が自動的に回収される。

取得したドメイン名は 2 年で有効期限が切れる。切れてしまう前に sendrenewal を発行することで更新ができる。

3.5. (B) 競り負けた際に入札額を回収する

運悪くドメイン名を落札できなかった場合、sendredeem コマンドにより入札額を回収できる。

$ ./bin/hsw-cli rpc sendredeem zettaini-hosikunai-domein

残念でした。

4. 確認

getnameresource コマンドで、ブロックチェーン上で実際にリソースレコードが登録されたことを確認できる。

$ ./bin/hsd-cli rpc getnameresource zettaini-hosikunai-domein
{
  "records": [{
    "type": "GLUE4",
    "ns": "ns1.zettaini-hosikunai-domein.",
    "address": "203.0.113.1"
  }]
}

登録した情報で実際に DNS を引けるようになるには、 36ブロック(約 6 時間)ごとに発生する urkle-tree の更新タイミングを待たなければならない。これが更新されると、以下のように DNS の解決を試すことができる。

hsd フルノードは、それ自体が Handshake DNS ドメイン名を解決するネームサーバーとしての機能を持っている。デフォルトでは、ポート 5349 で権威サーバー、5350 でフルサービスリゾルバが動いている。よって、

$ dig +noall +authority +additional @localhost -p 5349 zettaini-hosikunai-domein.
zettaini-hosikunai-domein.                  21600   IN      NS      ns1.zettaini-hosikunai-domein.
ns1.zettaini-hosikunai-domein.              21600   IN      A       203.0.113.1
...

のようにドメイン名が解決できることを確認できる。また、権威ネームサーバー ns1.zettaini-hosikunai-domein. を正しく設定していれば、フルサービスリゾルバを使って

$ dig +short @localhost -p 5350 www.zettaini-hosikunai-domein.
203.0.113.2

のように、権威ネームサーバーが解決する結果を得ることができるはずだ。また、hdns.io が公開しているオープンリゾルバ 103.196.38.38103.196.38.39 でも同じ結果が返ってくることを確認できるはずだ。

おわりに

この記事では、Handshake の概要と、Handshake でドメイン名を取得する方法について取得した。僕は実際に mecab というトップレベルドメインを取得して、http://mecab/ でホームページ http://misosi.ru/ と同じコンテンツを表示するようにしてみた。当然、この URL は通常の DNS で解決することはできない。しかし、Handshake ドメインを解決してページを表示してくれるゲートウェイ hns.to を通せば、http://mecab.hns.to/ として見ることができる。もちろん、ネットワーク の設定を変更し、ネームサーバーとして上記の 103.196.38.38103.196.38.39 を指定しても見ることができる。

はじめに書いたように、Handshake はまだ実験的なプロジェクトで、稼働はするが実用的に使える状態ではない。そもそも Handshake DNS を解決できるネームサーバーを設定しているユーザーがいないということは脇に置いても、CDN がない(少なくとも、Cloudflare は ICANN が管理しているドメインしか origin に指定できない)とか、対応した認証局 (CA) がないため SSL で暗号化できないという問題がある。

しかし、鶏か卵かという問題はあれど、Handshake が普及するにつれて既存のサービスも徐々に対応が進むかもしれないので、これからに期待したい。CA に関しては、そもそも Handshake のプロジェクトのスコープとして、分散型の CA を立ち上げることも含まれるため、プロジェクトの今後に期待したい。

最後に、本文に含めた物も含め、Handshake に関連したいくつかのサービスを挙げて終わりにしようと思う。

  • Namebase (https://www.namebase.io/): ドメイン名売買サービス。自分が持つドメインの管理も行える。実は手元に hsd をインストールしなくても、このサイトに HNS を送金してそこからドメイン取得を行えるらしい。reveal や 更新の処理も自動でやってくれるようだ。その他 Handshake に関する文書も多くあり、情報源としても役に立つ。
  • hns.to (https://hns.to/): Handshake ゲートウェイ。Handshake ドメイン名の後に .hns.to を付けると、それが HTTP サーバーだった場合、提供されているコンテンツを表示してくれる。
  • hdns.io (https://www.hdns.io): Handshake ドメイン名を解決するオープンリゾルバ。103.196.38.38103.196.38.39
  • domains.tasuki (http://domains.tasuki) と sniper.tasuki (http://sniper.tasuki): Namebase で売られているドメインを価格帯ごとにリストするサイトと、オークションの締め切りが近いドメインをリストするサイト。これらは Handshake ドメイン名で公開されているので、閲覧するには環境を整える必要がある。(おそらく JavaScript の都合で、hns.to を通しても見ることができない。)

  1. 例えば、政府がドメイン名を差し押さえることがある。(参考: アメリカ政府がWebサイトのDNSを差し押さえ、数十サイトがアクセス不可に | 初代編集長ブログ―安田英久 | Web担当者Forum↩︎

  2. Alexa ランキング上位 10 万位までに入ったドメイン名が予約されている。これらのドメインの所有者は、TXT レコードを設定するか、または DNSSEC を設定したネームサーバーであれば、その秘密鍵を使って署名した情報を送信することで Handshake 上でも同じドメインを取得することができる。詳細は How to Claim a Name 参照。 ↩︎