オープンソースのNGINXソフトウェアとNGINX Plus はどちらも、Web サーバー、リバース プロキシ、コンテンツのキャッシュとして非常に安全で信頼性があります。 権限のないクライアントによるアクセスに対する追加の保護として、 Secure Link モジュールのディレクティブを使用して、クライアントが要求するアセットの URL に特定のハッシュ文字列を含めるように要求できます。
このブログ投稿では、Secure Link モジュールに実装されている 2 つの方法を構成する方法について説明します。 サンプル構成スニペットは HTML およびメディア プレイリスト ファイルを保護しますが、任意のタイプの HTTP URL に適用できます。 これらの方法は NGINX と NGINX Plus の両方に適用されますが、簡潔にするために、このブログの残りの部分では NGINX Plus のみについて説明します。
Secure Link モジュールは、 HTTP 要求の URL 内のエンコードされた文字列と、その要求に対して計算された文字列を比較して、要求されたリソースの有効性を検証します。 リンクの有効期間が限られており、その期間が過ぎると、そのリンクは古いものと見なされます。 これらのチェックのステータスは$secure_link
変数にキャプチャされ、処理のフローを制御するために使用されます。
前述のように、モジュールは 2 つのメソッドを提供します。 特定のhttp
、 server
、またはlocation
コンテキストで構成できるのは、そのうちの 1 つだけです。
最初のよりシンプルなモードはsecure_link_secret
ディレクティブによって有効になります。 エンコードされた文字列は、URL の最後の部分と NGINX Plus 設定で定義された秘密の単語の 2 つのテキスト文字列の連結に基づいて計算された MD5 ハッシュです。 (最初のテキスト文字列の詳細については、 「基本的なセキュリティ保護された URL の使用」を参照してください。)
保護されたリソースにアクセスするには、クライアントは URL プレフィックスの直後にハッシュを含める必要があります。これは、スラッシュのない任意の文字列です。 このサンプル URL では、プレフィックスはvideosで、保護されたリソースはファイルbunny.m3u8です。
/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8
この方法の使用例の 1 つは、ユーザーが共有のために画像またはドキュメントをサーバーにアップロードしたが、公式リンクが公開されるまでファイル名を知っているユーザーがアクセスできないようにしたい場合です。
2 番目のより柔軟な方法は、 secure_link
およびsecure_link_md5
ディレクティブによって有効になります。 ここでエンコードされた文字列は、NGINX Plus 構成ファイルで定義された変数の MD5 ハッシュです。 最も一般的には、特定のクライアント IP アドレスへのアクセスを制限するために$remote_addr
変数が含まれますが、 User-Agent
ヘッダーをキャプチャして特定のブラウザーへのアクセスを制限する$http_user_agent
などの他の値を使用することもできます。
オプションで、ハッシュが正しい場合でも URL が機能しなくなる有効期限を指定できます。
ハッシュを指定するには、クライアントはリクエスト URL にmd5引数を追加する必要があります。 ハッシュされた文字列に有効期限が含まれている場合、クライアントは、保護されたファイルpricelist.htmlを要求する次のサンプル URL のように、有効期限を指定するためにexpires引数も追加する必要があります。
/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740
Secure Link モジュールは、nginx.org のビルド済みオープンソース NGINX バイナリ、オペレーティング システム ベンダーが提供する NGINX パッケージ、およびNGINX Plusに含まれています。 ソースから NGINX をビルドする場合、デフォルトでは含まれません。configure コマンドに
--with-http_secure_link_module
引数を含めることで有効にします。
URL を保護するより基本的な方法は、 secure_link_secret
ディレクティブを使用することです。 次のサンプル スニペットでは、 /bunny.m3u8という名前の HTTP ライブ ストリーミング (HLS) メディア プレイリスト ファイルを保護します。 これは/opt/secure/hlsディレクトリに保存されますが、 videosプレフィックスで始まる URL を使用してクライアントに公開されます。
server {
listen 80;
server_name secure-link-demo;
location /videos {
secure_link_secret enigma;
if ($secure_link = "") { return 403; }
rewrite ^ /secure/$secure_link;
}
location /secure {
internal;
root /opt;
}
}
この構成では、ファイル/opt/secure/hls/bunny.m3u8にアクセスするには、クライアントは次の URL を提示する必要があります。
/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8
ハッシュ化された文字列はプレフィックスの直後に続きます。プレフィックスはスラッシュのない任意の文字列です (ここではvideos )。
ハッシュは、2 つの要素を連結したテキスト文字列に対して計算されます。
secure_link_secret
ディレクティブへのパラメータ。ここではenigma です
。クライアントのリクエスト URL に正しいハッシュがない場合、NGINX Plus は$secure_link
変数を空の文字列に設定します。 の もし
テストが失敗し、NGINX Plusは 403
禁断
HTTP 応答のステータス コード。
それ以外の場合 (ハッシュが正しいことを意味します)、書き換え
ディレクティブは URL を書き換えます。この例では、 /secure/hls/bunny.m3u8になります ( $secure_link
変数はハッシュに続く URL の部分をキャプチャします)。 /secureで始まる URL は、2 番目のロケーション
ブロックによって処理されます。 そのブロック内のroot
ディレクティブは、要求されたファイルのルート ディレクトリとして/opt を設定し、 internal
ディレクティブは、ブロックが内部で生成された要求にのみ使用されることを指定します。
クライアントが URL に含める必要がある 16 進形式の MD5 ハッシュを取得するには、 -hex
オプションを指定してopenssl
md5
コマンドを実行します。
# echo -n 'hls/bunny.m3u8enigma' | openssl md5 -hex (stdin)= 80e2dfecb5f54513ad4e2e6217d36fd4
プログラムによるハッシュの生成については、 「プログラムによるハッシュの生成」を参照してください。
次のサンプルcurl
コマンドは、サーバーがさまざまなセキュリティ保護された URL にどのように応答するかを示しています。
URLに正しいMD5ハッシュが含まれている場合、応答は200
わかりました
:
# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hls/bunny.m3u8 | head -n 1 HTTP/1.1 200 OK
MD5ハッシュが間違っている場合、応答は次のようになります。403
禁断
:
# curl -I http://secure-link-demo/videos/2c5e80de986b6fc80dd33e16cf824123/hls/bunny.m3u8 | head -n 1 HTTP/1.1 403 禁止
bunny.m3u8のハッシュが別のファイルに使用されている場合、応答も403
禁断
:
# curl -I http://secure-link-demo/videos/80e2dfecb5f54513ad4e2e6217d36fd4/hs/oven.m3u8 | head -n 1 HTTP/1.1 403 禁止
URL を保護するためのより柔軟な方法として、 secure_link
およびsecure_link_md5
ディレクティブを使用します。 この例では、これらを使用して、IP アドレス 192.168.33.14 のクライアントからのみ、2016 年 12 月 31 日までのみ、 /var/www/ files/pricelist.html ファイルへのアクセスを許可します。
仮想サーバーはポート 80 でリッスンし、 location
/files
ブロックの下にあるすべてのセキュリティ保護された HTTP 要求を処理します。ここで、 root
ディレクティブは、要求されたファイルのルート ディレクトリとして/var/wwwを設定します。
secure_link
ディレクティブは、リクエスト URL 内の引数を取得する 2 つの変数を定義します。 $arg_md5
はmd5引数の値に設定され、 $arg_expires は
expires引数の値に設定されています。
secure_link_md5
ディレクティブは、リクエストの MD5 値を生成するためにハッシュされる式を定義します。URL 処理中に、ハッシュは$arg_md5
の値と比較されます。 ここでのサンプル式には、リクエストで渡された有効期限 ( $secure_link_expires
変数でキャプチャされます)、URL ( $uri
)、クライアント IP アドレス ( $remote_addr
)、および単語enigma
が含まれています。
server {
listen 80;
server_name secure-link-demo;
location /files {
root /var/www;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr enigma";
if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
}
この設定では、 /var/www/files/pricelist.htmlにアクセスするには、IP アドレス 192.168.33.14 のクライアントが2016 年 12 月 31 日土曜日 23:59:00 UTCまでに次のリクエスト URL を送信する必要があります。
/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740
クライアントから送信された URL のハッシュ ( $arg_md5
変数でキャプチャ) がsecure_link_md5
ディレクティブから計算されたハッシュと一致しない場合、NGINX Plus は$secure_link
変数を空の文字列に設定します。 if
テストが失敗し、NGINX Plusが403
HTTP 応答の禁止
ステータス コード。
ハッシュが一致してもリンクの有効期限が切れている場合は、NGINX Plusは $セキュアリンク
変数に 0
; 再び もし
テストは失敗しますが、今回はNGINX Plusが 410
消えた
HTTP 応答のステータス コード。
ここで、クライアントが URL に含めるmd5およびexpires引数をどのように計算するかを見てみましょう。
最初のステップは、有効期限に相当する Unix 時間を決定することです。その値は、 $secure_link_expires
変数の形式でハッシュ式に含まれているためです。 Unix 時間 (エポック(1970-01-01 00:00:00 UTC)からの秒数) を取得するには、 -d
オプションと+%s
フォーマット指定子を指定したdate
コマンドを使用します。
この例では、有効期限をSat Dec 31 23:59:00 UTC 2016に設定しているので、コマンドは次のようになります。
#日付 -d "2016-12-31 23:59" +%s1483228740
クライアントは、この値をリクエスト URL のexpires=1483228740引数として含めます。
ここで、 secure_link_md5
ディレクティブで定義された文字列 ( $secure_link_expires$uri$remote_addr
謎
) を 3 つのコマンドで実行します。
-binary
オプションを指定したopenssl
md5
コマンドは、バイナリ形式で MD5 ハッシュを生成します。openssl
base64
コマンドは、ハッシュ値にBase64エンコーディングを適用します。tr
コマンドは、プラス記号 ( +
) をハイフン ( -
) に、スラッシュ ( /
) をアンダースコア ( _
) に置き換え、エンコードされた値から等号 ( =
) を削除します。この例では、完全なコマンドは次のようになります。
# echo -n '1483228740/files/pricelist.html192.168.33.14 enigma' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d = AUEnXC7T-Tfv9WLsWbf-mw
クライアントは、この値を要求 URL のmd5=AUEnXC7T-Tfv9WLsWbf-mw引数として含めます。
NGINX Plus Web サーバーがアプリケーション サーバーから動的コンテンツを提供している場合、NGINX Plus とアプリケーション サーバーの両方で同じセキュリティ保護された URL を使用する必要があります。 URL 内のmd5引数のハッシュをプログラムで生成できます。 次の Node.js 関数は、上記の NGINX Plus 設定スニペットで定義されたハッシュと一致するハッシュを生成します。 有効期限、URL、クライアント IP アドレス、および秘密の単語を引数として受け取り、Base64 でエンコードされたバイナリ形式の MD5 ハッシュを返します。
var crypto = require("crypto");
function generateSecurePathHash(expires, url, client_ip, secret) {
if (!expires || !url || !client_ip || !secret) {
return undefined;
}
var input = expires + url + client_ip + " " + secret;
var binaryHash = crypto.createHash("md5").update(input).digest();
var base64Value = new Buffer(binaryHash).toString('base64');
return base64Value.replace(/=/g, '').replace(/+/g, '-').replace(///g, '_');
}
現在の例のハッシュを計算するには、次の引数を渡します。
generateSecurePathHash(new Date('12/31/2016 23:59:00').getTime()), '/files/pricelist.html', “192.168.33.14”, "enigma");
次のサンプルcurl
コマンドは、サーバーがセキュリティ保護された URL にどのように応答するかを示しています。
IPアドレス192.168.33.14のクライアントが正しいMD5ハッシュと有効期限を入力すれば、応答は次のようになります。200
わかりました
:
# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 200 OK
異なるIPアドレスを持つクライアントが同じURLを送信した場合、応答は403
禁断
:
# curl -I --interface "192.168.33.33" 'http://secure-link-demo/files/pricelist.html?md5=AUEnXC7T-Tfv9WLsWbf-mw&expires=1483228740' | head -n 1 HTTP/1.1 403 禁止
md5引数のハッシュ値が正しくない場合、応答は403
禁断
:
# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=qeUNjiY2FTIVMaXUsxG-7w&expires=1483228740' | head -n 1 HTTP/1.1 403 禁止
URLの有効期限が切れている場合( expires引数で指定された日付が過去である場合)、応答は次のようになります。410
消えた
:
# curl -I --interface "192.168.33.14" 'http://secure-link-demo/files/pricelist.html?md5=Z2rNva2InyVcRTlhqAkT4Q&expires=1467417540' | head -n 1 HTTP/1.1 410 消えた
以下は、メディア アセットのプレイリストとセグメント ファイルの両方を保護するために使用される、有効期限付きのセキュリティ保護された URL の別の例です。
前の例との 1 つの違いは、 $file_name
変数でファイル名をキャプチャし、 secure_link_md5 ディレクティブに渡すときに、プレイリスト ( .m3u8ファイル) と HLS セグメント ( .tsファイル) から拡張子を削除するためのマップ
構成
ブロックをここに追加していることです。 これは、プレイリストだけでなく、個々の.tsセグメントに対するリクエストを保護するために役立ちます。
最初の例とのもう 1 つの違いは、特定の Web ブラウザー上のクライアントへのアクセスを制限するために (たとえば、URL が Safari では機能するが、Chrome や Firefox では機能しないなど) 、 secure_link_md5
ディレクティブ
に $http_user_agent 変数 ( User-Agent
ヘッダーをキャプチャ) を含めることです。
map $uri $file_name {
デフォルトなし;
"~*/s/(?<name>.*).m3u8" $name;
"~*/s/(?<name>.*).ts" $name;
}
server {
listen 80;
server_name secure-link-demo;
location /s {
root /opt;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$file_name$http_user_agent enigma";
if ($secure_link = "") { return 403; }
if ($secure_link = "0") { return 410; }
}
}
NGINX の Secure Link モジュールを使用すると、URL の特定の部分のハッシュなどのエンコードされたデータを追加することで、ファイルを不正アクセスから保護できます。 有効期限を追加すると、リンクの有効期間も制限され、セキュリティがさらに強化されます。
NGINX Plus をお試しいただくには、今すぐ30 日間の無料トライアルを開始するか、弊社にお問い合わせの上、使用事例についてご相談ください。
「このブログ投稿には、入手できなくなった製品やサポートされなくなった製品が参照されている場合があります。 利用可能な F5 NGINX 製品およびソリューションに関する最新情報については、 NGINX 製品ファミリーをご覧ください。 NGINX は現在 F5 の一部です。 以前の NGINX.com リンクはすべて、F5.com の同様の NGINX コンテンツにリダイレクトされます。"