📌

Hotlink Protection (画像の直リンク防止)機能

2024/11/11に公開

今日はCloudflare の Hotlink Protection機能を試していきます。この機能は別のサイトから管理対象のサイトが保有する画像の直接リンクをブロックすることが出来ます。

Hotlink とはCloudflareのサービス名ではなく、一般的なウェブ用語です。他のウェブサイトの画像やファイルを直接自分のページに表示させることを指します。通常、ウェブサイトにある画像や動画などのコンテンツは、サイト所有者が自分のサーバーにアップロードして使いますが、ホットリンクの場合は、他のサイトのサーバーからそのコンテンツを「直接リンク」して表示させます。

画像だけが別のウェブサイトから呼び出された場合、本来ウェブサイトが意図している情報がユーザーに提供されない、もしくはGA4等を用いたユーザー情報の収集が行えないなどウェブサイト運営側のメリットが薄い状態で、アクセスが発生し続ける一方で、画像にはアクセスが継続的に発生するためサイトの負荷だけが高まるといった状況が発生します。また画像が著作権などで保護されている場合、その侵害も懸念されます。

CloudflareのHotlink ProtectionはReferrerによりその制御を行います。

Referrerとは

あるウェブページにアクセスした際に、前のページ(どのページから来たのか)を示す情報のことです。特に、ブラウザがHTTPリクエストをサーバーに送信する際に、リファラーヘッダーとして送られる情報を指します。例えば、あるウェブページ(A)から別のウェブページ(B)にリンクをクリックすると、Bのサーバーにアクセスが届く際、リファラーとしてAのURLが通知されます。

例えば以下のHTMLがhttps://a.harunobukameda.com/index.htmlでホスティングされている場合

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Hello World</title>
</head>

<body>
  <h1>Hello World</h1>
  <p>こんにちは、世界!</p>
  <img src="a.jpg"/>
</body>

</html>

a.jpgの呼び出しの際にはhttps://a.harunobukameda.com/index.htmlというReffererが渡されることになります。

Hotlink Protectionはこの値が異なるリクエスト、つまり別のウェブサイトからのリクエストをブロックします。

さっそくやってみる

使い方は簡単です。Cloudflareのマネージメントコンソールの左ペインから、Scrape ShieldHotlink Protectionのトグルをオンにするだけです。


この状態でいつも通りnginxでWebを構築します。
https://zenn.dev/kameoncloud/articles/6d2dec59232917
index.htmlを以下にしてCloudflare経由でのアクセスを設定します。

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Hello World</title>
</head>

<body>
  <h1>Hello World</h1>
  <p>こんにちは、世界!</p>
  <img src="a.jpg"/>
</body>

</html>

a.jpgは何でも良いので適当なものを配置しておきます。サイトにアクセスすると以下のように画像が表示されます。

次に別ドメインでもう一台ウェブサイトを構築し以下のhtmlを配置します。

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Hello World</title>
</head>

<body>
  <h1>Hello World</h1>
  <p>こんにちは、世界!</p>
  <img src="https://a.harunobukameda.com/a.jpg"/>
</body>

</html>
  <img src="https://a.harunobukameda.com/a.jpg"/>

の行が先ほどとの変更点です。このサイトが別ドメインでホスティングされている場合、本来期待されているhttps://a.harunobukameda.com/index.htmlとは別Referrerからa.jpgが呼び出されます。
アクセスを行うと以下の通り画像の読み込みが失敗しています。

一方直接ブラウザでhttps://a.harunobukameda.com/a.jpgを呼び出すと画像は表示されます。Referrerが空の場合は引き続きアクセスが可能です。これは、例えばXやSlack、GooglChat等今のSNSやチャットツールはURLを共有するとその画像をサムネイルとして抽出して表示してくれる機能が備わっています。それを機能させるためには画像そのもののURLへボットがアクセスした際に読み込めるようにしておく必要があるためです。これも防ぎたい場合は、Cloudflare Workersを用いて画像の読み込みをスクリプトで制御することが可能です。

Discussion