2026年5月20日
2026年5月20日
WordPressのホットリンクを防御する方法
はじめに
ホットリンク(直リン)は、他のサイトが自分のサーバー上の画像・動画ファイルを直接URLで参照することです。自分のサーバーの帯域幅が消費されるにもかかわらず、恩恵は他サイトが受けます。適切に防御することで帯域幅の無駄遣いと著作権侵害を防げます。
症状・原因
- アクセス解析でトラフィックが多いのにページビューが少ない
- サーバーの転送量が異常に多く、帯域幅制限に引っかかっている
- 画像ファイルへの直接アクセスが大量に発生している
- 自分のサイトの画像が他サイトに無断で使用されている
解決手順
ステップ1:ホットリンクの状況を確認する
# 画像ファイルへのアクセスをRefererと一緒に確認
grep -E "\.(jpg|jpeg|png|gif|webp|svg|mp4|pdf)" /var/log/apache2/access.log | \
awk '{print $7, $11}' | \
grep -v '"https://example.com\|"-"' | \
sort | uniq -c | sort -rn | head -30
# ホットリンク元のドメインをリスト
grep -E "\.(jpg|png|gif|webp)" /var/log/nginx/access.log | \
grep -oP '"https?://[^/"]+"' | \
grep -v "example.com" | \
sort | uniq -c | sort -rn | head -20
# 月間転送量を確認
# Apache: awstats や GoAccess で集計
goaccess /var/log/apache2/access.log --log-format=COMBINED -o /tmp/report.html
ステップ2:Apacheでホットリンクを防ぐ(.htaccess)
# WordPress ルートの .htaccess(# BEGIN WordPress の前に追記)
<IfModule mod_rewrite.c>
RewriteEngine On
# ① Referer が空または自分のドメインの場合は許可
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?bing\. [NC]
# ② 画像・動画・PDFへのアクセスをブロック
RewriteRule \.(jpg|jpeg|png|gif|webp|svg|mp4|pdf|ico)$ - [F,L]
# ③ ブロック時に代替画像を表示する場合
# RewriteRule \.(jpg|jpeg|png|gif|webp)$ /images/hotlink-forbidden.png [R=301,L]
</IfModule>
# .htaccess 編集後の確認
# 自分のサイトから画像にアクセス → 表示できること
curl -I -H "Referer: https://example.com/" https://example.com/wp-content/uploads/test.jpg
# HTTP/2 200 が返れば OK
# 別サイトからのアクセスをシミュレート → ブロックされること
curl -I -H "Referer: https://other-site.com/" https://example.com/wp-content/uploads/test.jpg
# HTTP/2 403 が返れば成功
ステップ3:Nginxでホットリンクを防ぐ
# /etc/nginx/sites-available/example.com
server {
# ... 既存の設定 ...
# 画像・動画ファイルへのホットリンクを防ぐ
location ~* \.(jpg|jpeg|png|gif|webp|svg|mp4|pdf|ico)$ {
# 許可する Referer を指定
valid_referers none blocked server_names
~\.example\.com
~\.google\.
~\.bing\.;
# 無効な Referer からのアクセスを拒否
if ($invalid_referer) {
return 403;
# 代替画像にリダイレクトする場合:
# return 301 https://example.com/images/hotlink-forbidden.png;
}
# キャッシュ設定
expires 30d;
add_header Cache-Control "public, immutable";
}
}
# Nginx 設定テストと反映
sudo nginx -t && sudo systemctl reload nginx
ステップ4:WordPress から動的に制御する
// functions.php: 画像の直接アクセスを制御
// ① 特定の画像タイプへの直接アクセスをブロック
add_action('init', function(): void {
// 画像ファイルへの直接アクセス時に Referer を確認
$request_uri = $_SERVER['REQUEST_URI'] ?? '';
if (!preg_match('/\.(jpg|jpeg|png|gif|webp)$/i', $request_uri)) {
return;
}
$referer = $_SERVER['HTTP_REFERER'] ?? '';
$site_url = parse_url(get_site_url(), PHP_URL_HOST);
// Referer がない場合または自サイト以外の場合
if (!empty($referer)) {
$referer_host = parse_url($referer, PHP_URL_HOST);
$allowed_domains = [$site_url, 'www.' . $site_url, 'google.com', 'bing.com'];
$is_allowed = false;
foreach ($allowed_domains as $domain) {
if (str_ends_with($referer_host ?? '', $domain)) {
$is_allowed = true;
break;
}
}
if (!$is_allowed) {
status_header(403);
exit;
}
}
});
// ② 画像URLに署名付きトークンを追加(より高度な保護)
add_filter('wp_get_attachment_url', function(string $url): string {
// 公開ページでは通常のURL、管理画面では署名なし
if (is_admin() || wp_doing_ajax()) {
return $url;
}
return $url; // 署名ロジックはここに追加
});
ステップ5:Cloudflare でホットリンクを防ぐ
# Cloudflare ダッシュボード: Scrape Shield
# → Hotlink Protection を ON にするだけで完了
# 確認: Cloudflare の Hotlink Protection が有効な場合
# 他サイトの <img src="https://example.com/image.jpg"> は
# Cloudflare が自動的にブロック
# 許可するサイトを追加する場合は
# Cloudflare WAF → Custom Rules で Referer を条件に許可ルールを追加
# WP-CLI で Cloudflare 設定を確認(CF プラグイン使用時)
wp cf cache purge --type=everything
注意事項
RewriteCond %{HTTP_REFERER} !^$を含めることで、Refererが送信されない直接アクセス(ブックマーク・RSS・検索エンジンの直接クロール)は許可されます。これを除外するとRSSリーダーや一部のソーシャルメディアプレビューが機能しなくなる場合があります- Googlebot・Bingbot等の検索エンジンクローラーはRefererを送信しないため、
!^$条件があれば自動的に許可されます - SNSシェア時のOGP画像プレビューはFacebook・Twitter等のクローラーがRefererなしでアクセスするため、ホットリンク防止後も正常に機能します
まとめ
ホットリンク防止は①アクセスログでgrep -E "\.(jpg|png)"で外部Refererを確認、②Apacheは.htaccessにRewriteCond %{HTTP_REFERER}とRewriteRuleを追記、③Nginxはvalid_referersディレクティブと$invalid_referer条件でreturn 403、④Cloudflareは「Scrape Shield → Hotlink Protection」をONにするだけ、⑤curl -H "Referer: https://other.com/"で403が返ることを確認します。