某フリマサービスのシステム変更の際に、CDNの仕様把握を誤った為に、会員情報をCDNにキャッシュしてしまい、購入履歴、住所やクレカ情報の一部といった会員の個人情報を漏えいしてしまった事故が先日ありました。
そこで今回はNginxの基本的なキャッシュコントロールに関するディレクティブをおさらいする記事にします。
まずはシンプルに。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# vi /etc/nginx/conf.d/server.conf server { listen 80; # アクセス可能なIPアドレス、もしくはドメイン server_name 192.168.11.27; root /var/www/html; index index.html; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_max_temp_file_size 0; location / { expires -1; proxy_pass http://localhost:8000; } } server { listen 8000; server_name localhost; root /var/www/html; index index.html; } |
判定
304の判定とEtagも判定させたくありません。Etagはアンテナサイトなどと連携している場合には不具合になる場合もあります。
- sendfile
OSのキャッシュ。 - if_modified_since
更新通知を判定します。304の場合はデータを取りにいきません。 - Etag
ブラウザキャッシュの管理番号ようなもの、サーバ側で更新されたら値が変わるので、ブラウザはデータを取りにいきます。同じ値であれば更新されていないものとしてブラウザのキャッシュを利用するため高速な処理になります
上記を踏まえて変更
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
server { listen 80; # アクセス可能なIPアドレス、もしくはドメイン server_name 192.168.11.27; root /var/www/html; index index.html; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_max_temp_file_size 0; sendfile off; etag off; if_modified_since off; location / { expires -1; proxy_pass http://localhost:8000; } } server { listen 8000; server_name localhost; root /var/www/html; index index.html; add_header Cache-Control no-cache; sendfile off; etag off; if_modified_since off; } |
判定
いいですね。
no-cacheディレクトリだけキャッシュしない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
server { listen 80; server_name 192.168.11.27; root /var/www/html; index index.html; location /no-cache/ { add_header Cache-Control no-cache; #※CDNの種類によってはno-cacheをprivateに変える必要がある。 sendfile off; etag off; if_modified_since off; } } |
キャッシュは便利だけれど、怖い
Nginxのキャッシュ機構を採用する場合は、絶対に管理画面系をキャッシュしてはいけませんし、その場合は少しコンフィグが複雑になります。利用時は必要な部分だけキャッシュを添えて、安全に利用しないといけない。
また、冒頭の某フリマサービスのケースに戻りますが、新たなCDNをうまく使うには
1 |
× Cache-Control no-cache; |
1 |
○ Cache-Control private; |
privateになっていないとページをキャッシュしてしまうという仕様だった模様です。なにこれ怖い!
技術的な失敗例を教えて貰えるのはとても有難い(ㆁᴗㆁ✿)
トラブルや失敗例に学ぶことって勉強になります。頭の中に失敗例のインデックスを作っておくと、自身が管理するシステムの障害が起こった時に、障害の予測が速くなりますし、失敗例に陥るアンチパターンなシステムを組まずに済みます。
今回のケースの教訓として
外部サービスを変更する場合は、そのサービスの仕様の細かい把握が必要であること、検証を重ねて行なわないといけない。言うのは簡単ですが。
お疲れ様です。