竹丼へのアクセスを referer で判別して拒否した話

前回に続いて、今度はポータル系サイトを拒否する。
別に収集するだけなら良いのだけど、検索に引っかかるの本当に勘弁して欲しいと思ってる。
Twitterまわりでもアカウント消しても外部のサイトにツイート残り続けたりするのでまるっと滅べば良い。

使うモジュールが有効になっているかを確認する

$ nginx -V 2>&1 | tr -- - '\n' | grep _module

nginx -V は標準エラー出力に出ているので 2>&1 が必要。

ここで、 ngx_http_referer_module がなければ追加する必要がある。

http_addition_module 
http_auth_request_module 
http_dav_module 
http_flv_module 
http_gunzip_module 
http_gzip_static_module 
http_mp4_module 
http_random_index_module 
http_realip_module 
http_secure_link_module 
http_slice_module 
http_ssl_module 
http_stub_status_module 
http_sub_module 
http_v2_module 
mail_ssl_module 
stream_realip_module 
stream_ssl_module 
stream_ssl_preread_module

あっ…ない…。
ない場合は nginx をビルドしなおす必要があるらしいので面倒。

nginx には 2種類のモジュールがあって

  • 静的module
    • ビルド時のみ組み込みが可能。
  • 動的module
    • ビルドし直すことなく追加可能。

とのこと。つらい。

理想

location / {
  try_files $uri @proxy;
}

location / {
  valid_referers none blocked server_names taketodon.com;

  if ($invalid_referer) {
    return 403;
  }
  try_files $uri @proxy;
}

valid_referers に記述してマッチしたものは $invalid_referer に 空文字が、マッチしないものは “1” がセットされる。
if 文で “” は false, “1” は true 判定なので、マッチしなかったものは 403 を返してあげる。

  • none
    リクエストヘッダに Referer がないやつ
  • blocked
    リクエストヘッダに Referer があるけど、その値が消されたかなんかでないやつ
  • server_names
    リクエストヘッダに Referer があるやつ
    任意の文字列と正規表現が使える

はず!(試してないのであってるか誰か教えてください)

現実

$http_referer は使えるので、それを使って制御する。

location / {
  if ($http_referer ~* (example.com|example.jp)){
    return 403;
  }
  try_files $uri @proxy;
}

終わったらリロード

$ systemctl reload nginx
参考