こんにちは、インフラとプロトコルの泥沼をいくつもくぐり抜けてきたシニアネットワークエンジニアの私だ。
今日は、Webアプリケーションの開発現場やインフラ運用で、なぜか見落とされがちでありながら、セキュリティとプライバシーの観点で時として爆弾になりうるHTTPヘッダー、`Referer`(と、その正しい綴りである `Referrer-Policy`)について話をしよう。
「リンクを踏んだら、どこから来たのかが相手サーバーにバレる」というあの仕様だ。甘く見ていると、内部システムのURL構造や機密情報を含むクエリパラメータが外部のサードパーティ広告や解析ツールにダダ漏れになり、インシデントの温床になる。
今回は、この `Referer` の仕様の基本から、ブラウザがどのようにプライバシーを守るべく進化してきたのか、そして実務で私たちがどう設定し、どうデバッグすべきかを徹底的に解説しよう。
—
1. なぜ「Referer」なのか?(歴史と基本仕様)
まず、ネットワーキングの歴史を少しだけ紐解こう。HTTP/0.9や1.0の初期、Webは単なる静的なドキュメントの共有空間だった。しかし、動的なWebアプリケーションへと進化するにつれ、「ユーザーがどのページからこのページに遷移してきたか(リファラー)」を知る必要性が出てきた。
ここでトリビアだが、HTTP仕様書(RFC)を策定する際、単語の綴りを `referrer` ではなく、当時のタイポ(誤字)である `Referer` のまま標準化してしまった。そのため、HTTPヘッダーとしては `Referer` なのに、後から登場したDOM APIやポリシー設定では正しい綴りである `referrer` が使われるという、エンジニア泣かせの歴史的負債が生まれたのだ。
Refererの基本挙動と通信フロー
ユーザーがサイトA(`https://example.com/page-a`)にいて、そこに貼られたリンクをクリックしてサイトB(`https://api.example.org/landing`)に移動する瞬間、ブラウザはHTTPリクエストの中に次のようなヘッダーをこっそり付与する。
GET /landing HTTP/1.1
Host: api.example.org
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)…
Accept: text/html,application/xhtml+xml…
Referer: https://example.com/page-a
サイトBのサーバーサイドやWebアプリケーションのログには、この `Referer` ヘッダーが残り、「おや、うちのサイトにはexample.comのpage-aから人が流れてきているな」と解析できるわけだ。アクセス解析の基本原理だな。
—
2. プライバシーのジレンマと情報漏洩のリスク
ベンダーやマーケターにとっては便利な `Referer` だが、プライバシーの観点からは悪夢になり得る。
例えば、社内システムのURLが以下のような構造だったとしよう。
`https://intranet.company.local/secure/document?token=abc123secret&user=john_doe`
この社内ページから、うっかり外部のオープンなWebサイトへリンクを踏んだ瞬間、この完全なURL(機密トークンやユーザー名を含むクエリパラメータごと)が、外部サイトのサーバーに `Referer` として送信されてしまう。セキュアな閉じたネットワークのつもりが、HTTPヘッダーを介して外部に機密情報をばら撒いていた……なんて笑えない事故が、現実の現場では幾度となく起きている。
この問題を解決するためにブラウザベンダーとW3Cが立ち上がり、誕生したのが `Referrer-Policy` だ。
—
3. Referrer-Policyの種類と挙動を完全理解する
私たちは、HTTPレスポンスヘッダーやHTMLのメタタグを用いて、ブラウザに「どこまでの情報をRefererとして送っていいか」を厳格に指示できる。実務でよく使われる主要なポリシーを見ていこう。
| ポリシー名 | 挙動の概要 | 実務での評価 |
| :— | :— | :— |
| `no-referrer` | 一切のRefererを送らない。 | プライバシー最高だが、アクセス解析が死ぬ。 |
| `no-referrer-when-downgrade` | デフォルト。HTTPS→HTTPのダウングレード時以外はフルURLを送る。 | レガシーブラウザ向けのデフォルト。 |
| `origin` | パスやクエリを削り、オリジン(例: `https://example.com/`)のみを送る。 | バランス型。どこから来たかはわかるが機密は守られる。 |
| `origin-when-cross-origin` | 同一オリジンならフルURL、クロスオリジンならオリジンのみ。 | 利便性とプライバシーの折衷案。 |
| `strict-origin-when-cross-origin` | 現代のモダンブラウザのデフォルト。 HTTPS→HTTPSならフル、クロスオリジンかつHTTPS→HTTPなら送らない。 | セキュリティと機能性のベストプラクティス。 |
| `same-origin` | 同一オリジン内でのみRefererを送る。外部には一切送らない。 | 社内ポータルや高機密Webアプリ向け。 |
—
4. 実務での実装・設定パターン
では、実際のインフラやアプリケーション層で、どのようにこのポリシーを制御すべきか。具体的な設定例を示そう。
① Webサーバー(Nginx)でのグローバル設定
すべてのレスポンスに強固なポリシーを強制するため、Nginxのグローバル設定(またはサーバーブロック)に記述する。
server {
listen 443 ssl;
server_name app.example.com;
# SSL/TLS設定は省略…
# すべてのレスポンスにデフォルトのReferrer-Policyを付与
add_header Referrer-Policy “strict-origin-when-cross-origin” always;
location / {
root /var/www/html;
index index.html;
}
}
シニアのワンポイントメモ: `always` をつけるのを忘れるな。これを付けないと、4xxや5xxのエラーレスポンス時にヘッダーがドロップされ、意図しない挙動をすることがある。
② HTMLのmetaタグによる制御
特定のページだけ挙動を変えたい場合や、静的ホスティング(S3 + CloudFrontなど)でHTTPヘッダーの制御が面倒な場合は、HTMLの `
` 内に記述する手もある。
機密性の高いトランザクション画面
③ モダンなJavaScript (Fetch API) での制御
フロントエンドから非同期リクエスト(`fetch`)を飛ばす際にも、リクエスト単位でReferrerの送信を制御できる。
// 機密情報を扱うAPIエンドポイントへリクエストを送信する例
async function sendSensitiveData() {
try {
const response = await fetch(‘https://api.example.com/v1/update’, {
method: ‘POST’,
headers: {
‘Content-Type’: ‘application/json’,
‘Authorization’: ‘Bearer secret_token_xyz’
},
body: JSON.stringify({ status: ‘active’ }),
// このリクエストではRefererを完全に抑制する
referrerPolicy: ‘no-referrer’
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log(‘送信成功:’, data);
} catch (error) {
console.error(‘通信エラー:’, error);
}
}
sendSensitiveData();
—
5. デバッグとトラブルシューティングの実践
現場で「あれ? 外部の解析ツールにURLのクエリパラメータが丸見えになってるぞ」というトラブルに直面したとき、どうやって調査・検証すべきか。私のオススメの手順を伝授しよう。
curlでのヘッダー確認
まずはAPIやサーバーが意図した `Referrer-Policy` を返しているか、`curl` で叩いて確認する。
curl -I -s https://app.example.com/ | grep -i “Referrer-Policy”
期待される出力例:
referrer-policy: strict-origin-when-cross-origin
ブラウザの開発者ツール(DevTools)でのパケット追跡
1. ブラウザ(ChromeやEdgeなど)の開発者ツールを開き、「Network(ネットワーク)」タブを選択する。
2. 実際にリンクをクリックするか、リクエストを発生させる。
3. 発生したリクエストをクリックし、「Headers(ヘッダー)」タブの 「Request Headers」 セクションを確認する。
4. そこに `Referer` がどのように送信されているか(フルURLか、オリジンだけか、そもそも無いか)が生々しく表示される。
もし「クエリパラメータが含まれてしまっている!」と気づいたら、即座にNginxやアプリケーションのレスポンスヘッダーに `Referrer-Policy: strict-origin-when-cross-origin`(あるいはより厳格なポリシー)を実装し、ブラウザに強制するのだ。
—
まとめ
`Referer` ヘッダーと `Referrer-Policy` は、Webの「つながりやすさ」という利便性と、「プライバシーとセキュリティの保護」という現代の重大な要請のせめぎ合いの歴史そのものだ。
- 原則として、すべてのWebアプリケーションは `Referrer-Policy` を明示的に設定すべきである。
- デフォルトの挙動に頼るのではなく、モダンブラウザの標準である `strict-origin-when-cross-origin` などをインフラ層(Nginx/Apache/CDN)で一括適用するのが、プロのインフラエンジニアの仕事というものだ。
さあ、今すぐ君の管理しているサーバーのレスポンスヘッダーを確認してみよう。思わぬ「情報の漏れ穴」が見つかるかもしれないぞ。
コメント