nginxでSecureLinkを構築

やりたい事は、rtmpで映像配信時 rtmp://にセキュリティをかけたい。

rtmp:// urlが拡散されて誰でもアクセスされるという事を防ぎたい。

参考はこちら
http://server-setting.info/centos/nginx-secure-link.html

このサイトを見ながら、セキュアリンクを実現してみる。

http://nginx.org/en/docs/http/ngx_http_secure_link_module.html

This module is not built by default, it should be enabled with the –with-http_secure_link_module configuration parameter.

build する時に、–with-http_secure_link_moduleをつけないとダメ―。

コンパイルの仕方はこちらから

Debian NginxでHLSライブストリーミング 手順まとめ

PHPも動かしたいので、動かし方が分からないかたはこちら

nginxでphpを動かす

今回はこんな感じでconfigureしてみた。

sudo ./configure --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --add-module=../nginx-rtmp-module --with-debug --prefix=/usr/local/nginx --with-http_secure_link_module --user=www-data --group=www-data
make install

 

ちなみに、再コンパイルする際には、既存のファイル等を削除しなくてもいいみたい。

会員登録などで
「下のリンクをクリックしてください
http://hanako.jp/regist/reg.php?ap9eur0jasdfjsdljfaeijeifja
このURLは1時間有効です」

のようなやつをnginxで実現する

securelink.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>Test SecureLink</title> 
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
</head>
<body>

<?php
// 秘密鍵 になります。なんでもOKですので、ここでは日本語(UTF-8)で設定してみます。
$secret = '日本語でもOK?';
// セキュアなリンク からでないとアクセスできないURIを設定します。
$path   = '/secure/';
// 公開鍵として、有効期限を time() + 秒 で設定します。
// -- この有効期限の設定の仕方は、Nginxではこの方法でしか認識できません。
$timestamp = time() + 3600; // 60(秒) x 60(分) = 3600(秒) = 1(時)
//※テストを行う際にはこの時間数を短くすると早く確認できる
 
// "秘密鍵 + パス + 公開鍵" を Nginxで扱うことができる md5 で暗号化します。
$hash = base64_encode(md5($secret . $path . $timestamp, true));
// +,/,= は、URLパラメータとして扱えないので、置換します。
$hash = strtr($hash, '+/', '-_');
$hash = str_replace('=', '', $hash);

//  セキュアなリンクを出力します。
$url = "{$path}?s={$hash}&t={$timestamp}";
echo '<a href="'.$url.'">シークレットリンク</a>';
?>

</body>
</html>

すると、シークレットリンクには

http://サーバホスト名/secure/?s=hdNICsMOPRchm-eD8M7IHQ&t=1475890667

このようなリンクが出力される。

sudo mkdir /usr/local/nginx/html/secure

セキュアディレクトリを作成し、index.htmlを作成する

<pre lang="php" escaped="true">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>Test SecureLink</title> 
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> 
</head>
<body>
<h1>おめでとうございます。</h1>
<p>おめでとうございます。<br />
あなたは、見事にこのページを見ることができました。
</p>
</body>
</html>

とすると、リンクをクリクすればそのままホームページは見れる

その後が問題で、このセキュアなリンクが正しいかを判断するために、secure_link,secure_link_md5の2つのディレクティブを利用

secure_link : セキュアなリンク情報(URI,URLパラメータ)から、認証に使用する情報を設定します。
secure_link_md5 : セキュアなリンク情報(URI,URLパラメータ)および秘密鍵から、 md5 で暗号化した情報を作成します。 ここで作成した情報が、先の secure_link で設定した情報と一致するか否かによって認証を行います。

nginx.confに以下を追加する

sudo vi /etc/nginx/nginx.conf
location /secure/ {
# MD5暗号化情報 公開鍵(有効期限)情報を認証情報として設定します。
# -- URLパラメータ s=XXXX , t=YYYY をそれぞれ設定しています。
secure_link $arg_s,$arg_t;

# 秘密鍵 + URI + 公開鍵(有効期限)でMD5暗号化情報を作成します。
# -- 先に設定された認証情報との比較結果が $secure_link へ出力されます。
secure_link_md5 日本語でもOK?$uri$arg_t;

# 認証結果が MD5暗号化情報の不一致なら $secure_link は何も設定されません。
# -- この場合、アクセス制限の 403 を返信します。
if ($secure_link = "") {
return 403;
}
# 認証結果が 有効期限切れなら $secure_link に 0 が設定されます。
# -- この場合、アクセス制限の 403 を返信します。
if ($secure_link = "0") {
return 403;
}
}

この設定がうまくいっていると、

シークレットリンクをクリックした際に

時間内
おめでとうございます。
おめでとうございます。
あなたは、見事にこのページを見ることができました。

時間外
403 Forbidden
nginx/1.11.4

と表示される。この仕組みを生かしてrtmp 配信も時間制限つけてみる

Streaming with nginx-rtmp-module Secure links