torのhidden serviceで使うアドレスを計算する(Vanity Addresses)

最近このような記事を読みました.

今のインターネットはドメイン頼りな割に単一障害点となってしまってあまりよろしくない.でも逃げ道があまりないのですよね…….
とりあえず以前からそのうちやろうと思って放置していたtorのhidden serviceでミラーを立てるのをやってみようかなと思い立ちました.

とりあえず /etc/tor/torrc で以下のあたりを有効にしてtorを再起動してhttpdの設定をするだけで動きます.

HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 127.0.0.1:80

このときのアドレスはtor再起動後に HiddenServiceDir 以下に作られる hostname ファイルの中の名前になります.

$ sudo cat /var/lib/tor/hidden_service/hostname
tbiettfnprnqpoccrz3ll7hioprbyjoam2n6okihpadf5ukaa4hwrwad.onion

このアドレスは[a-z|3-7]の32文字(BASE32)からなる16文字の onion v2 アドレスと,56文字の onion v3 アドレスがあって,最近は後者のv3アドレスが規定値になっているようです.鍵は RSA から ed25519 になっています.

Onion v2 はホストネームから秘密鍵を求めるのに現実的な時間で済むのが近づいてきているようなのでとても長くて使いづらいですがこれからはOnion v3 アドレスにしたほうが良さそうです.
今はv2,v3 を併用しているところも多いようです.

Onion v2 Onion v3

hostname文字長

16

56

鍵形式

RSA

ed25519

鍵ファイル名

private_key

hs_ed25519_secret_key hs_ed25519_public_key

(無駄に)アドレスを計算して好みの単語にマッチしたものを探す(例えばmatokenから始まるアドレスを探すとか)ことが可能です.
こういったアドレスはVanity Addresses というようです.

他にもアドレスを売っているところもありますが,相手は秘密鍵を持っているわけであまりよくないと思います.

Onion v2 アドレスを eschalot で探す

Onion v2 アドレスを eschalot というツールを使ってみます.

導入
$ sudo apt install libssl-dev
$ git clone https://github.com/ReclaimYourPrivacy/eschalot
$ cd eschalot
$ make
$ ./eschalot
Version: 1.2.0

usage:
eschalot [-c] [-v] [-t count] ([-n] [-l min-max] -f filename) | (-r regex) | (-p prefix)
  -v         : verbose mode - print extra information to STDERR
  -c         : continue searching after the hash is found
  -t count   : number of threads to spawn default is one)
  -l min-max : look for prefixes that are from 'min' to 'max' characters long
  -n         : Allow digits to be part of the prefix (affects wordlist mode only)
  -f filename: name of the text file with a list of prefixes
  -p prefix  : single prefix to look for (1-16 characters long)
  -r regex   : search for a POSIX-style regular expression

Examples:
  eschalot -cvt4 -l8-12 -f wordlist.txt >> results.txt
  eschalot -v -r '^test|^exam'
  eschalot -ct5 -p test

  base32 alphabet allows letters [a-z] and digits [2-7]
  Regex pattern examples:
    xxx           must contain 'xxx'
    ^foo          must begin with 'foo'
    bar$          must end with 'bar'
    b[aoeiu]r     must have a vowel between 'b' and 'r'
    '^ab|^cd'     must begin with 'ab' or 'cd'
    [a-z]{16}     must contain letters only, no digits
    ^dusk.*dawn$  must begin with 'dusk' and end with 'dawn'
    [a-z2-7]{16}  any name - will succeed after one iteration

以下は -t でスレッド数を指定,-v で冗長出力,-pabc 方始まるホスト名を探しています.
見つかると標準出力にホスト名と秘密鍵が出力されます.

$ time ./eschalot -t`nproc` -v -p abc
Verbose, single result, no digits, 4 threads, prefixes 3-3 characters long.
Thread #1 started.
Thread #2 started.
Thread #3 started.
Thread #4 started.
Running, collecting performance data...
Found a key for abc (3) - abcamzmribeujuzw.onion
----------------------------------------------------------------
abcamzmribeujuzw.onion
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDIHD5uCynAW/Y1Vmyef8KrKuyFMzavij5Gl6aHYoiaGWNkJOZ7
P/Xc1Z78YTZ7LtzpWCAWLax4PmIhQiwPhldsD/kVWKAi0fODxaP/Z0XoJjqIfx8f
CmVWIQ1L9TVp9kfp8nLtXm9CnawCT98g0VE/jvZEddBV2oaVCuq88BTsoQIEAQBz
4QKBgBHzMeQAOOkyB3yCc51oYOh92jYLyXJuc511HR9yki7b/CxIhjL7miA+GVmJ
n4DD9nKubE5/xE6KrNnm3YZ1kmar2Yl/8fLJxBUrVoDUeGAc7i77i+tqM4d1LCr3
X1Ead8S7WpnnTVSmRHiLjuebaF78BWiMII4+3v9d1e6PQXbRAkEA9IJknhUNSO5b
1bzEIOmybg94r3fvBdWsc9xiwm6ONMBI2WyAVwmxDZ63Spwb/AyKCEblwekcaw6h
NMmhBQeUmQJBANGDs597RqBQUsFqtb5BoBkQgELIVeS4xKgZXrDI9SKfnnpTxv8Z
ypah+g335EN3/bBgfbqy8C7zFZhjHclzFUkCQQDcoP4aDG1zPO4TFcnguwvnGv/j
kOBS3h0CJOVY+rLTlUaekvjD6ugVLQ0olFItL1wyyZ3IifKcDHoDWJo/OOZZAkAQ
82dcvUGLOUpZObyFTdyUkU/eytiXaQZM0UdTDPnGYmrH/CBEaoSSjgRG7MEdFf2k
r+VVLqSnp+g6tFwp9It5AkBI4fJxCrrANt3E/CCrFW4iZXIqP3aPXHHZK5SqtQzJ
gBKUN8HSRxo/dURQPOLKKX0ynVJaMhg5UO4tQ3rHiJwa
-----END RSA PRIVATE KEY-----

Segmentation fault

real    0m0.126s
user    0m0.399s
sys     0m0.015s

-r オプションで正規表現が利用できます.以下の例は abc から始まり bca で終わるホスト名か,deadbeef で始まるアドレスを探しています.

$ ./eschalot -t`nproc` -v -r "^abc.*bca^|^deadbeef"

-c オプションで1つ見つかっても中断するまで探し続けます.
ファイルにリダイレクトしておくと便利です.

$ ./eschalot -cvt`nproc` -r "^abc.bca^|^deadbeef" >> result.log

探したいワードが多い場合は1ワード1行の辞書ファイルを作成して -f オプションで指定すると便利です.ただし,辞書ファイル指定時は7文字以下のワードは無視されるようです.-l オプションで 7-16 のように最小文字数を7以下にすればと思ったのですが,このオプションは7以下だとエラーで終了してしまいます.

$ ./eschalot -cvt`nproc` -f ./wordlist.dic >> result.log

GPUを使うツールも複数あります.例えば Scallion こっちのほうがずっと速いでしょう.(ASICとかもあるのかな?)

Onion v3 アドレスを mkp224o で探す

Onion v3 アドレスは mkp224o というツールを使ってみました.

configure optionに --enable-amd64-51-30k , --enable-amd64-64-24k というものがあるので試してみましたが,なし,--enable-amd64-51-30k , --enable-amd64-64-24k のいずれでも有意な速度差は見られませんでした.(Intel® Core™ i5-3320M)

導入
$ sudo apt install libsodium-dev autoconf
$ git clone https://github.com/cathugger/mkp224o
$ cd mkp224o
$ ./autogen.sh
$ ./configure
$ make
$ ./mkp224o
Usage: ./mkp224o filter [filter...] [options]
       ./mkp224o -f filterfile [options]
Options:
        -h  - print help to stdout and quit
        -f  - specify filter file which contains filters separated by newlines
        -D  - deduplicate filters
        -q  - do not print diagnostic output to stderr
        -x  - do not print onion names
        -v  - print more diagnostic data
        -o filename  - output onion names to specified file (append)
        -O filename  - output onion names to specified file (overwrite)
        -F  - include directory names in onion names output
        -d dirname  - output directory
        -t numthreads  - specify number of threads to utilise (default - CPU core count or 1)
        -j numthreads  - same as -t
        -n numkeys  - specify number of keys (default - 0 - unlimited)
        -N numwords  - specify number of words per key (default - 1)
        -z  - use faster key generation method; this is now default
        -Z  - use slower key generation method
        -B  - use batching key generation method (>10x faster than -z, experimental)
        -s  - print statistics each 10 seconds
        -S t  - print statistics every specified ammount of seconds
        -T  - do not reset statistics counters when printing
        -y  - output generated keys in YAML format instead of dumping them to filesystem
        -Y [filename [host.onion]]  - parse YAML encoded input and extract key(s) to filesystem
        --rawyaml  - raw (unprefixed) public/secret keys for -y/-Y (may be useful for tor controller API)
        -p passphrase  - use passphrase to initialize the random seed with
        -P  - same as -p, but takes passphrase from PASSPHRASE environment variable

探したいワードを引数に与えて実行するだけで利用できます.結果はホスト名のディレクトリ以下にファイルとして出力されます.

$ time ./mkp224o abcd
sorting filters... done.
filters:
        abcd
in total, 1 filter
using 4 threads
abcdpr2quwoxranttf2ywckm7g5giysscy62kmhyqmnq2ycvooxbtryd.onion
^Cwaiting for threads to finish... done.

real    0m8.982s
user    0m21.740s
sys     0m0.167s
$ ls -A abcdpr2quwoxranttf2ywckm7g5giysscy62kmhyqmnq2ycvooxbtryd.onion
hostname  hs_ed25519_public_key  hs_ed25519_secret_key

結果を onion ディレクトリに格納するようにしました.

$ time ./mkp224o -d ./onion abcd

フィルタは複数書けます.

$ time ./mkp224o -d ./onion abcd efgh ijkl

-S オプションで指定した秒数ごとに統計上を鵜を出力します.フィルタに辞書ファイルを使います.

$ ./mkp224o -S 300 -d ./onion -f ./wordlist.dic

以下は手元のNotePCとRaspberry Pi 3 model Bでの速度です.PCの方は熱でスロットリングが効いているのもありますが,案外Raspberry Pi が悪くない数字に見えます.自分の環境の場合電気代等を考えるとRaspberry Pi を並列で動かしておくほうが良さそうです.

Intel® Core™ i5-3320M
>calc/sec:202602.624226, succ/sec:0.000000, rest/sec:0.000000, elapsed:300.129147sec
>calc/sec:177378.183948, succ/sec:0.006667, rest/sec:0.006667, elapsed:600.131277sec
>calc/sec:155232.657607, succ/sec:0.006667, rest/sec:0.006667, elapsed:900.106274sec
>calc/sec:111928.180486, succ/sec:0.000000, rest/sec:0.000000, elapsed:1200.166338sec
Raspberry Pi 3 model B(aarch64 kernel)
>calc/sec:103867.893552, succ/sec:0.003333, rest/sec:0.003333, elapsed:300.130969sec
>calc/sec:100761.039921, succ/sec:0.003333, rest/sec:0.003333, elapsed:600.155046sec
>calc/sec:94511.877034, succ/sec:0.009999, rest/sec:0.009999, elapsed:900.194934sec
>calc/sec:91854.274354, succ/sec:0.003334, rest/sec:0.003334, elapsed:1200.130938sec

Vanity Addresses の設定

Onion v2

torrc の HiddenServiceDir 以下の hostname, hs_ed25519_public_key, hs_ed25519_secret_key を退避します.
次に private_key ファイルをtorの権限で作成し,見つけたRSA鍵を保存します.

その後torのサービスを再起動すると反映されて hostname ファイルも作成されます.

$ grep ^HiddenServiceDir /etc/tor/torrc
HiddenServiceDir /var/lib/tor/other_hidden_service/
$ sudo ls -A /var/lib/tor/other_hidden_service/
authorized_clients  hostname  hs_ed25519_public_key  hs_ed25519_secret_key  private_key
$ sudo rm /var/lib/tor/other_hidden_service/hostname /var/lib/tor/other_hidden_service/hs_ed25519_public_key /var/lib/tor/other_hidden_service/hs_ed25519_secret_key
$ sudo install -o debian-tor -g debian-tor -m 400 /dev/null /var/lib/tor/other_hidden_service/private_key
$ echo '-----BEGIN RSA PRIVATE KEY-----
> MIICXQIBAAKBgQDIHD5uCynAW/Y1Vmyef8KrKuyFMzavij5Gl6aHYoiaGWNkJOZ7
> P/Xc1Z78YTZ7LtzpWCAWLax4PmIhQiwPhldsD/kVWKAi0fODxaP/Z0XoJjqIfx8f
> CmVWIQ1L9TVp9kfp8nLtXm9CnawCT98g0VE/jvZEddBV2oaVCuq88BTsoQIEAQBz
> 4QKBgBHzMeQAOOkyB3yCc51oYOh92jYLyXJuc511HR9yki7b/CxIhjL7miA+GVmJ
> n4DD9nKubE5/xE6KrNnm3YZ1kmar2Yl/8fLJxBUrVoDUeGAc7i77i+tqM4d1LCr3
> X1Ead8S7WpnnTVSmRHiLjuebaF78BWiMII4+3v9d1e6PQXbRAkEA9IJknhUNSO5b
> 1bzEIOmybg94r3fvBdWsc9xiwm6ONMBI2WyAVwmxDZ63Spwb/AyKCEblwekcaw6h
> NMmhBQeUmQJBANGDs597RqBQUsFqtb5BoBkQgELIVeS4xKgZXrDI9SKfnnpTxv8Z
> ypah+g335EN3/bBgfbqy8C7zFZhjHclzFUkCQQDcoP4aDG1zPO4TFcnguwvnGv/j
> kOBS3h0CJOVY+rLTlUaekvjD6ugVLQ0olFItL1wyyZ3IifKcDHoDWJo/OOZZAkAQ
> 82dcvUGLOUpZObyFTdyUkU/eytiXaQZM0UdTDPnGYmrH/CBEaoSSjgRG7MEdFf2k
> r+VVLqSnp+g6tFwp9It5AkBI4fJxCrrANt3E/CCrFW4iZXIqP3aPXHHZK5SqtQzJ
> gBKUN8HSRxo/dURQPOLKKX0ynVJaMhg5UO4tQ3rHiJwa
> -----END RSA PRIVATE KEY-----' | sudo -u debian-tor tee /var/lib/tor/other_hidden_service/private_key
$ sudo service tor restart
$ torsocks w3m `sudo -u debian-tor cat /var/lib/tor/other_hidden_service/hostname`

Onion v3

torrc の HiddenServiceDir 以下の hostname, hs_ed25519_public_key, hs_ed25519_secret_key を退避します.
次に hs_ed25519_secret_key ファイルをtorの権限でコピーします.

その後torのサービスを再起動すると反映されて hostname, hs_ed25519_public_key ファイルも作成されます.

$ grep ^HiddenServiceDir /etc/tor/torrc
HiddenServiceDir /var/lib/tor/other_hidden_service/
$ sudo ls -A /var/lib/tor/other_hidden_service/
authorized_clients  hostname  hs_ed25519_public_key  hs_ed25519_secret_key  private_key
$ sudo rm /var/lib/tor/other_hidden_service/hostname /var/lib/tor/other_hidden_service/hs_ed25519_public_key /var/lib/tor/other_hidden_service/hs_ed25519_secret_key
$ sudo install -o debian-tor -g debian-tor -m 400 ./onion/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion/hs_ed25519_secret_key /var/lib/tor/other_hidden_service/hs_ed25519_secret_key
$ sudo service tor restart
$ torsocks w3m `sudo -u debian-tor cat /var/lib/tor/other_hidden_service/hostname`

まとめ

という感じで3日ほど動かしてみましたが matoken から始まるホスト名を3つほど掘り当てました.近いうちにミラーを設定してみようと思います.(v2, v3のアドレスを1つのtorサービスでホストする方法ってあるのかな?)
しかし設定してもアクセスはほぼ無いような気も…….

ちなみにtorはNAT越えもしてしまうのでsshdなどを許可する場合は注意しましょう.

$ torsocks w3m -dump http://matoken3inrzd4ks.onion/
 _     _   _             ____               _        _              _____
| |__ | |_| |_ _ __ _   / / / __ ___   __ _| |_ ___ | | _____ _ __ |___ /
| '_ \| __| __| '_ (_) / / / '_ ` _ \ / _` | __/ _ \| |/ / _ \ '_ \  |_ \
| | | | |_| |_| |_) | / / /| | | | | | (_| | || (_) |   <  __/ | | |___) |
|_| |_|\__|\__| .__(_)_/_/ |_| |_| |_|\__,_|\__\___/|_|\_\___|_| |_|____/
              |_|
 _                   _ _  _   _                     _                __
(_)_ __  _ __ ______| | || | | | _____   ___  _ __ (_) ___  _ __    / /
| | '_ \| '__|_  / _` | || |_| |/ / __| / _ \| '_ \| |/ _ \| '_ \  / /
| | | | | |   / / (_| |__   _|   <\__ \| (_) | | | | | (_) | | | |/ /
|_|_| |_|_|  /___\__,_|  |_| |_|\_\___(_)___/|_| |_|_|\___/|_| |_/_/
環境
$ dpkg-query -W tor
tor     0.3.5.10-1
$ lsb_release -dr
Description:    Debian GNU/Linux 10 (buster)
Release:        10
$ uname -m
aarch64
$ cat /proc/device-tree/model ;echo
Raspberry Pi 3 Model B Rev 1.2