突然ですがSecureLinkモジュールとはなんぞや、というところですが、簡単に言うと、サービス登録時のメールアドレス確認で、下記の様なメールで見たことがあるような、一定時間のみ有効な時限式URLの認証機能を提供するモジュールです。
通常このような機能を作成する場合、URLの発行、利用期限の管理含め、基本的にはいわゆるPHP、Ruby、Python、Javaなどのサーバサイドアプリケーションで実装して利用しますが、このSecureLinkモジュールはこのうちの利用期限管理(URLの正当性検証)をnginx側で処理してくれるものになります。
そのため、時限式URLに絡めて、事前に入力されたユーザー情報を参照して〜といった、上記のメール画像のような機能には適さないですが、例えば、特定の静的ファイルを時限式URLで不特定多数に配布したい、といった場合であれば有効であると言えます。
長い前置きはさておき、以下からは実際に設定していきます。
まず、このモジュールはnginxの標準モジュールとしては提供されていないため、nginxのconfigure時に--with-http_secure_link_moduleオプションを付けてビルドし、有効化します。
一番簡単な設定方法としては、モジュールの公式ドキュメントやこちらのページ(by レンタルサーバー・自宅サーバー設定・構築のヒント)で紹介されているとおり設定すると基本的に動きます。
で、同じ内容で紹介してもあまり芸がないので、今回はほんの少しだけトリッキーな設定(ただの応用)での構築をここで記載してみます。
まず、構成を下記の様に設定するものとします。
URL
https://example.com
└通常URL
https://example.com/secure
└セキュアリンクURL
/secure/パス以下は、ドキュメントルート外の/var/www/example.com/secureを参照したいので、alias で別途パスを指定してます。(ここでrootディレクティブで指定すると、/secureの参照先が/var/www/example.com/secure/secure 以下を参照する事となり、恐らく想定した通りのパスを見てくれません)
セキュアリンクモジュールを使用した場合、パラメータまで一致していて初めてアクセスできるので、これらのURLパラメータを削除して、直接 https://example.com/secure/secret.html にアクセスしても、secret.htmlは閲覧できません。
が、今回はもうちょっとURLをそれっぽくしたい。
というURLのフォーマットにしたいと思ったので、下記の様にアレンジしてみました。
また、対象のファイルは同じく名前付き正規表現で変数$filepathに格納しています。
すべての認証が成功した際に、try_files で$filepathを確認し、なければ404を返す様にしています。
通常このような機能を作成する場合、URLの発行、利用期限の管理含め、基本的にはいわゆるPHP、Ruby、Python、Javaなどのサーバサイドアプリケーションで実装して利用しますが、このSecureLinkモジュールはこのうちの利用期限管理(URLの正当性検証)をnginx側で処理してくれるものになります。
そのため、時限式URLに絡めて、事前に入力されたユーザー情報を参照して〜といった、上記のメール画像のような機能には適さないですが、例えば、特定の静的ファイルを時限式URLで不特定多数に配布したい、といった場合であれば有効であると言えます。
長い前置きはさておき、以下からは実際に設定していきます。
まず、このモジュールはnginxの標準モジュールとしては提供されていないため、nginxのconfigure時に--with-http_secure_link_moduleオプションを付けてビルドし、有効化します。
一番簡単な設定方法としては、モジュールの公式ドキュメントやこちらのページ(by レンタルサーバー・自宅サーバー設定・構築のヒント)で紹介されているとおり設定すると基本的に動きます。
で、同じ内容で紹介してもあまり芸がないので、今回はほんの少しだけトリッキーな設定(ただの応用)での構築をここで記載してみます。
まず、構成を下記の様に設定するものとします。
パス設定
/var/www/example.com/public
└ドキュメントルート
/var/www/example.com/secure
└セキュアファイル設置場所
URL
https://example.com
└通常URL
https://example.com/secure
└セキュアリンクURL
通常の設定
ここまでの設定で、通常設定すると下記の様な設定になります。server {
root /var/www/example.com/public;
index index.html;
# SecureLinkアクセス用URI
location /secure/ {
alias /var/www/example.com/secure;
# 公開鍵のパラメータ k=公開鍵&t=タイムスタンプ のパラメータを与える設定
secure_link $arg_k,$arg_t;
# 公開鍵レシピ
secure_link_md5 YOUR_SECRET_KEY_WITH$uri?$arg_t;
if ($secure_link = "") {
# 認証NGの場合404を返却
return 404;
}
if ($secure_link = "0") {
# 有効期限切れの場合は403を返却
return 403;
}
try_files /$request_uri =404;
}
}
上記設定では、例えば https://example.com/secure/secret.html?k=OqjJ-smKxgnNTCGYz78TOg&t=1531815176 というURLにアクセスすると、パラメータkの公開鍵とtのタイムスタンプがそれぞれ正しければsecret.htmlのファイルを閲覧することができます。/secure/パス以下は、ドキュメントルート外の/var/www/example.com/secureを参照したいので、alias で別途パスを指定してます。(ここでrootディレクティブで指定すると、/secureの参照先が/var/www/example.com/secure/secure 以下を参照する事となり、恐らく想定した通りのパスを見てくれません)
セキュアリンクモジュールを使用した場合、パラメータまで一致していて初めてアクセスできるので、これらのURLパラメータを削除して、直接 https://example.com/secure/secret.html にアクセスしても、secret.htmlは閲覧できません。
が、今回はもうちょっとURLをそれっぽくしたい。
セキュアリンクのURLをカスタムしたい
https://example.com/secure/OqjJ-smKxgnNTCGYz78TOg/secret.html?t=1531815176というURLのフォーマットにしたいと思ったので、下記の様にアレンジしてみました。
# SecureLinkアクセス用URI
location ~ ^/secure/(?<pubkey>[0-9a-zA-Z_\-]+)/(?<filepath>.+) {
alias /var/www/example.com/secure;
# Public key (URI)
secure_link $pubkey,$arg_t;
# Secret key
secure_link_md5 "YOUR_SECRET_KEY_WITH$filepath?$secure_link_expires";
# Invalid key
if ($secure_link = "") {
return 404;
}
# timeout
if ($secure_link = "0") {
return 403;
}
try_files /$filepath =404;
}
今回のポイント
ポイントはlocationディレクティブを名前付き正規表現でパラメータを判定できるようにして、その名前(ここでは変数$pubkey)とURLパラメータ(t)をsecure_linkに引数として渡しているところです。また、対象のファイルは同じく名前付き正規表現で変数$filepathに格納しています。
すべての認証が成功した際に、try_files で$filepathを確認し、なければ404を返す様にしています。