title | emoji | type | topics | published | order | layout | |||||
---|---|---|---|---|---|---|---|---|---|---|---|
Nginx で Tor からのアクセス制限を行う方法 |
🈲 |
tech |
|
true |
37 |
article |
先日、Tor からのアクセスを制限するために Nginx の設定を追加する機会があり、せっかくなので Qiita でその方法を紹介したいと思います。
この記事の手順を試す前に、実際に Tor からのアクセス制限がどのようになるか確認したい場合は、noraworld.jp に、通常のブラウザ、Tor Browser それぞれでアクセスしてみてください。Tor Browser の利用に関しては後述の「設定が正しいかどうか確認」をご確認ください。
Tor からのアクセスを最も簡単に検知する方法は、IP アドレスが Tor exit ノードのものであるかどうかを調べることです。Tor は、ノードと呼ばれるサーバを複数経由することにより匿名性を実現しています。複数のノードを経由し、一番最後に経由したノードからインターネットに接続し、Web サーバと通信します。このときの一番最後に経由するノードを、インターネットに出るノードということで、Tor exit ノードと呼ばれます。
Tor exit ノードからインターネットに接続し Web サーバと通信を行うので、Web サーバ側でログとして記録される(検出できる)IP アドレスは、直近の IP アドレスである Tor exit ノードのものとなります。つまり、Tor exit ノードの IP アドレスであると認識できれば、Web サーバ側に接続を試みたクライアントが、Tor を利用しているか否かを判定できます。
Tor exit ノードは世界中にたくさんありますが、Tor exit ノードの IP アドレス一覧がいくつかのサイトに公開されています。たとえば Tor プロジェクト公式の Tor exit nodes - Tor Check が挙げられます。この一覧に記載されている IP アドレスをすべてアクセス拒否するように Nginx の設定ファイルに追加することで、Tor からのアクセスを制限することができます。
この記事では、Tor exit ノードの IP アドレス制限を行う際の Nginx の設定方法を 2 種類紹介します。
最も素直な設定方法は、deny ディレクティブを使用することです。Nginx では
deny 192.168.0.1;
のように記述することで IP アドレスを制限することができます。上記の例では、IP アドレス 192.168.0.1
からのアクセスがあると、Nginx は HTTP ステータスコード 403 Forbidden を返し、それ以外の IP アドレスからのアクセスは通常通り(制限をかけていない場合と同様に)振る舞います。Tor exit ノードの IP アドレスを上記のようにすべて列挙すれば Tor からのアクセスを制限することができます。
とはいえ、Tor exit nodes - Tor Check を見てわかる通り、これだけの IP アドレスを元々ある Nginx の設定ファイルに丸書きしてしまうと設定ファイルが長くなり可読性が悪くなります。そこで、別のファイルに、拒否する IP アドレスの一覧だけを書いておき、それを元々ある Nginx の設定ファイル側で読み込むようにします。
まずは拒否する IP アドレス一覧のファイルを作ります。Nginx の設定ファイルがあるディレクトリに移動し、以下のコマンドを実行します。ファイル名はなんでもいいですが、ここでは tor-exit-nodes
とします。
$ curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1 | sed '/^#/ !s/^/deny /g; s/$/;/g' > tor-exit-nodes
参考元: How to block TOR exit nodes from accessing your website on Apache and Nginx
作成されたファイルが以下のようになっていることを確認してください。
# This is a list of all Tor exit nodes from the past 16 hours that can contact 1.1.1.1 on port 80 #
# You can update this list by visiting https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1 #
# This file was generated on Sun Sep 3 07:04:10 UTC 2017 #
deny 1.160.199.140;
deny 1.160.207.95;
deny 1.163.203.136;
# ...
このファイルを元々の Nginx の設定ファイルから読み込みます。http コンテキストに以下の 1 行を追加します。
http {
include tor-exit-nodes;
server {
# ...
# ...
}
}
include ファイル名
とすることで、ファイル名の Nginx の設定を読み込むことができます。これで設定は完了です。
Nginx の設定ファイルにミスがないかチェックします。
$ sudo nginx -t
問題がなければ再起動します。
$ sudo nginx -s reload
これで Tor からのアクセスを制限することができます。
設定が正しいかどうかを確認するには、後述の「設定が正しいかどうか確認」を参照してください。
もう一つの方法として、Tor exit ノードの IP アドレスからのアクセスの際に、固有に変数を割り当て、その変数の値によって処理を振り分ける、という方法です。
geo
ディレクティブは、IP アドレス(とサブネットマスク)に基づき、変数に特定の値を割り振るためのディレクティブです。
geo $foo {
default 0;
192.168.0.1 1;
192.168.0.2 1;
192.168.1.1 2;
192.168.1.2 2;
}
例として、上記の設定では、192.168.0.1
または 192.168.0.2
からのアクセスの場合には変数 $foo
に 1
が、192.168.1.1
または 192.168.1.2
からのアクセスの場合には 2
が、それ以外の IP アドレスからのアクセスの場合には default
の値である 0
が代入されます。プログラミング言語でいう switch 文に構文が似ていますね。
このように特定の IP アドレスに特定の値を割り振ることで処理を分岐させることができます。これを利用して、先ほどの方法 1 で紹介したように、別の設定ファイルに Tor exit ノードの IP アドレスを列挙しておき、それらの IP アドレスに特定の値を割り当てることで、処理を分岐させます。
以下のコマンドを実行して拒否する IP アドレスの一覧を作成します。先ほどは deny
を使用していましたが、今回は、IP アドレスの後ろに値を割り当てるので、少しファイルの内容が異なります。
$ curl https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1 | sed '/^#/ !s/$/ 1;/g' > tor-exit-nodes
作成されたファイルが以下のようになっていることを確認してください。
# This is a list of all Tor exit nodes from the past 16 hours that can contact 1.1.1.1 on port 80 #
# You can update this list by visiting https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=1.1.1.1 #
# This file was generated on Sun Sep 3 07:04:10 UTC 2017 #
1.160.199.140 1;
1.160.207.95 1;
1.163.203.136 1;
# ...
❗ 見栄えのために適切なスペースを入れています。
先ほどと同様に元々の Nginx の設定ファイルから読み込みます。以下のように設定します。
http {
geo $tor {
default 0;
include tor-exit-nodes;
}
server {
if ($tor) {
return 403;
}
# ...
# ...
}
}
アクセス制限したい Web サイトの server
コンテキストで
if ($tor) {
return 403;
}
とします。変数 $tor
は、Tor exit ノードの IP アドレスにマッチする場合は 1
, そうでない場合には 0
となるので、if
ディレクティブの処理は、$tor
が 1
のとき、つまり Tor exit ノードの IP アドレスである場合に実行されます。return 403
を処理するので、deny
したときと同様に HTTP ステータスコード 403 Forbidden を返すので、方法 1 のときと同じく Tor からのアクセスを制限することができます。
この方法は、方法 1 のときに比べて、若干設定が煩雑である上に、アクセス制限したい Web サイト(server
コンテキスト)すべてに対して設定する必要があるので、方法 1 で解決する場合はそちらをおすすめします。方法 1 は単に 403 Forbidden を返すことしかできないのに対し、方法 2 では、server
コンテキストごとに異なる処理をすることができ、また、方法 1 よりも柔軟な処理を行うことができます。
たとえば、Tor からのアクセス制限の場合には A というエラー HTML ページを返却し、それ以外の、たとえば管理者ページなどに対するアクセス制限の場合には B というエラーページを返却したい、という場合には以下のように設定できます。
server {
location / {
if ($tor) {
return 403;
}
error_page 403 /tor.html;
}
location /.well-known {
return 403;
error_page 403 /403.html;
}
location = /tor.html {
root /var/www/html;
internal;
}
location = /403.html {
root /var/www/html;
internal;
}
}
Tor からのアクセスの場合には、/var/www/html/tor.html
がエラーページとして返され、/.well-known
に対するアクセスの場合には(この場合は Tor からのアクセスかどうかに関わらず)/var/www/html/403.html
がエラーページとして返されます。
このように IP アドレスごとに柔軟に処理を振り分けたいときなどには、geo
ディレクティブと if
ディレクティブによる分岐が有効です。
設定できたら、ミスがないか確認し、Nginx を再起動します。
$ sudo nginx -t
$ sudo nginx -s reload
では、Tor からのアクセス制限ができているかどうかを実際に確認します。Tor Browser をインストールしていない場合は、公式のダウンロードページからダウンロードできます。ダウンロードしたら画面の指示に従ってインストールを完了させてください。
Tor からのアクセス制限を行った Web サイトに、通常のブラウザと Tor Browser の両方でアクセスします。通常のブラウザで通常通りのコンテンツが表示され、Tor Browser でエラーページが表示されれば成功です!
単に Tor からのアクセス制限をかけたい場合は方法 1 を、Tor からのアクセスによるエラーページと管理者ページなどへのアクセスによるエラーページを変えたい場合など、柔軟に処理を振り分けたい場合は方法 2 をお試しください。