フタなしカンヅメ

徒然なるままに @happytar0

mod_rewriteで直リンク対策を簡単にする

外部から勝手にリンクされて困ってしまう場合、特に画像や動画ファイルなど比較的重たいファイルを勝手にリンクされてしまうと帯域を無駄に使ってしまい、困ってしまうことがあると思います。
そこでリファラを使って、直リンクされている場合に403を返すようにmod_rewriteを使ってみます。
今回はそれを簡単にするために、直リンクを許可するドメインをリスト化し、RewriteMapを使って処理したいと思います。

RewriteMapについては下記の記事でも取り上げています。
Apacheのmod_rewriteを使ってフェイルオーバー? - フタなしカンヅメ

Apacheの設定ファイルは以下のようにします。

<IfModule mod_rewrite.c>
  RewriteEngine On
  # 必ずロックファイルを指定
  RewriteLock /tmp/map.lock
  # RewriteMapで使う外部プログラムを指定
  RewriteMap referercheck-map prg:/usr/local/bin/referer_check.rb
</IfModule>

<Directory />
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} \.(gif|png|jpg|jpeg|bmp)$ [NC]
  RewriteCond ${referercheck-map:%{HTTP_REFERER}|NG} ^NG$
  RewriteRule ^.*$ / [L,F]
</Directory>

許可ドメインリストを読み取って処理する「referer_check.rb」の中身です。

#!/usr/bin/env ruby
$stdin.sync = 1
$stdout.sync = 1

require 'uri'

CHECK_OK = 'OK'
CHECK_NG = 'NG'

list_file = '/usr/local/etc/referer_list'

referer_list = []
File::open(list_file) do |f|
  while line = f.gets
    referer_list << line.chomp if line.chomp[0, 1] != "#"
  end
end

while true
  flag = nil
  buffer = $stdin.gets
  referer = URI.encode(buffer.strip)

  if referer.empty?
    flag = true
  else 
    begin
      uri = URI.parse(referer)
      flag = referer_list.any? {|v| uri.host.include?(v)} if uri.host
    rescue Exception
      #
    end
  end

  $stdout.puts(flag ? CHECK_OK : CHECK_NG)
end

referer_check.rbには実行権限が必要ですので注意してください。リストファイルは、一行ずつ許可ドメイン(ホスト)を記述します。

example.com
example.co.jp

許可するドメインが増えたら、リストを更新するだけで対応できるので、ちょっと簡単?になった気がします。今回は許可ドメインということでしたが、同じように拒否ドメインリストで対応ってことも可能だと思います。