はじめに

前回の記事では Wowza Streaming Engine のセットアップを行いました。 セットアップされたストリーミングサーバーは HTTPS サーバー証明書が設定されていないため、ストリーミングコンテンツや管理 UI は HTTP を使ってアクセスしました。

実際のサービスを公開する場合、HTTPS によるサービス提供が必要となります。 これは、サーバーサービス群の通信路のセキュリティ確保だけではありません。 ほとんどのウェブホスティングサービスの HTTPS 強制に伴って、Web ベースのプレイヤーをホストするサーバー (HTTPS) とコンテンツ (HTTP) の組み合わせは、既定で混在コンテンツを許可しないブラウザーポリシーのため、再生ができなくなる、という問題があります (前回の記事を参照)。

今回、Wowza Streaming Engine サーバーの以下のサービスに対して、HTTPS サーバー証明書の設定を行います。

サービスポート番号説明設定箇所
HTTPS ストリーミング443既定の HTTPS を使ったコンテンツストリーミングconf/VHost.xml
REST API インターフェース8087既定の REST API インターフェースを HTTPS に変更conf/Server.xml
Wowza Streaming Engine Manager 管理サービス8090管理画面へのアクセスを HTTPS 経由で行うmanager/conf/tomcat.properties

この記事では、前回の記事に引き続き、Ubuntu Linx 上にインストールされた Wowza Streaming Engine を対象とします。

HTTPS サーバー証明書の発行のまえに

HTTPS サーバー証明書を発行するにあたって、いくつかのケースがあります。

HTTPS サーバー証明書とは、サーバーのドメイン名に対して権威のある証明書発行機関 (証明書の認証局) により証明された証明書ですので、セットアップしたサーバーの外部公開 IP アドレスに対して、ドメイン名が割り当てられていることが必須となります。

一般的に、サービス公開を行うにあたって独自ドメイン名をお持ちの場合が多いため、その場合は、独自ドメインに対する HTTPS サーバー証明書の発行となります。 証明書の発行の依頼側がドメインの所有や指定したドメイン名のサーバーの所有を証明することにより、権威のある証明書発行機関は、依頼した者が正当なドメイン名の所有者であることを認め、証明書を発行します。

クラウドベンダーが提供する環境に展開する場合、そのクラウドベンダーの提供するドメイン名を使うことができる場合があります。 その場合は、クラウドベンダーのドメインに対する HTTPS サーバー証明書の発行となります。 このケースでは、クラウドの利用者はクラウドベンダーのドメインの所有者ではありません。 証明書の発行の依頼側がドメイン名のサーバーの所有を証明することにより、権威のある証明書発行機関は、依頼した者が正当なドメイン名の所有者であることを認め、証明書を発行します。

独自ドメインを所有しておらず、セットアップしたサーバーにドメイン名が割り当てられていない場合、それでも HTTPS サーバー証明書が必要な場合は、 Wowza Media Systems から提供されている StreamLock というマネージド サービスを利用することができます。 このサービスでは、サーバーの外部公開 IP アドレスを登録すると、[ランダムなホスト名].streamlock.net というドメイン名で HTTPS サーバー証明書を発行することができます。 サービスに登録した IP アドレスに対して [ランダムなホスト名].streamlock.net のドメイン名を独自の DNS で管理し、証明書発行機関に発行を依頼します。 これにより、発行された HTTPS サーバー証明書を提供することができるという仕組みとなっています。 このため、外部公開 IP アドレスが動的に変更されるホストでは利用することができません。固定の外部公開 IP アドレスを利用するようにしてください。

ケース別のまとめとしては、以下の通りです。

ケース発行方法
独自ドメイン名が割り当てられたサーバー証明書発行機関に発行を依頼する
クラウドベンダーのドメイン名が割り当てられたサーバー証明書発行機関に発行を依頼する
独自ドメイン名を所有しておらず、ドメイン名の割り当てがないサーバーWowza Media Systems の StreamLock サービスを利用する

この記事では、Let’s Encrypt と呼ばれている、フリーで自動化された証明書の発行を行う証明書発行機関を使った証明書の発行を紹介します。 Let’s Encrypt は、「世界中の HTTPS Web サイトの普及」というミッションのもと、様々なスポンサーの支援を受けて、HTTPS 証明書を無料で提供してくれています。

Wowza Media Systems の StreamLock サービスについては、Wowza のドキュメント記事: Get SSL/TLS certificates from the Wowza Streaming Engine StreamLock service を参照ください。

HTTPS サーバー証明書の発行

この記事では、HTTPS サーバー証明書を発行に Certbot ツールを利用します。 Certbot ツールは、Let’s Encrypt 証明書発行機関に対して証明書の発行処理を、コマンドラインで利用することができるツールです。

Certbot ツールのインストール

以下のコマンドを実行して Certbot ツールをインストールします。

sudo apt install certbot -y

Certbot ツールには、証明書の発行と設置 (run)、証明書の発行のみ (certonly)、証明書の更新 (renew) などの 作業に合わせたサブコマンドが用意されています。 Apache や NGINX などの HTTP サーバーとも統合されており、証明書の発行と設置 (run) のサブコマンドを利用することで、証明書発行の自動化が行えるようになっています。 また、証明書発行機関がドメイン名所有の検証を行うためのオプションとして、以下のオプションが用意されています。

オプション説明
standaloneシンプルなスタンドアロンの Web サーバーを起動し、ドメイン名の所有を検証する (HTTPによる検証)
webroot既に起動している Web サーバーの webroot ディレクトリに検証のためのファイルを配置して検証する (HTTPによる検証)
manual手動で検証のための手続きを行う (DNS による検証、および、HTTPによる検証)
  • DNS による検証
    • ドメイン名の所有者は、所有している DNS の DNS レコードに指定されたランダムな値の TXT レコードを登録します
    • 証明書発行機関 (認証局) は、その DNS レコードに指定した値が正しく設定されているかを確認する、ことでドメイン名の所有を検証します
  • HTTP による検証
    • ドメイン名の所有者は、ドメイン名の Web サーバー上に、指定されたランダムな値を保持するテキストファイルを配置します
    • 証明書発行機関 (認証局) は、そのテキストファイルがHTTP経由で正しく取得でき、指定された値がファイルに含まれているかを確認する、ことでドメイン名の所有を検証します

以下のコマンドで certbot コマンドのオプションの詳細を確認することができます。 また、Certbot のドキュメントはこちらから確認することができます。

certbot --help

注意: Certbot ツールの既定の設定では、/etc フォルダなど管理者権限が必要なディレクトリへの書き込みが必要なため、sudo コマンドを使って実行するようにします

ケース別のドメイン名所有の検証方法について

HTTPS サーバー証明書を発行するにあたって、いくつかのケースがあり、上でその説明しました。 ここでは、それのケースのうち、ドメイン名の割り当てがある場合、証明書の発行のためのドメイン名所有の検証方法について説明します。

ケース1: 独自ドメインを所有している

独自ドメインを所有している場合、以下の2つの方法で、ドメイン名所有の検証が可能です。

  • DNS による検証
  • HTTP による検証

ケース2: クラウドのドメインを利用したドメイン名をサーバーに割り当てている

クラウドベンダーのドメインを利用している場合、そのドメインの所有や管理はクラウドベンダーが行っているため、DNS による検証を利用することができません。 この場合は、HTTP によるドメイン名所有の検証のみが利用可能です。

  • HTTP による検証

DNS 検証を使った発行

DNS 検証を使った証明書発行は、--manual オプションを使って、以下のコマンドを実行します。

sudo certbot certonly --manual --domain [ドメイン名] --email [Eメールアドレス] --agree-tos --preferred-challenges dns

出力結果:

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for wowza-01.stream.liveinstantly.cloud

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_acme-challenge.[ドメイン名].

with the following value:

KDXCIHSTiqQnl1J410aharFz7jz1-NZ8jha0ajajKjqePhhdc <== 検証用のランダムな文字列

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.wowza-01.stream.liveinstantly.cloud.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

ここでツールの実行が一旦停止し、ユーザーに DNS TXTレコードの追加を促します。 所有しているドメインの DNS に TXT レコードの検証用のランダムな文字列を追加したら、[Enter] キーを押して継続します。

ドメイン名所有の検証が完了すると、以下のように出力され、/etc/letsencrypt/live/[ドメイン名]/ 以下のフォルダに発行された証明書が保存されます。

Let’s Encrypt で発行された証明書の有効期間は 90 日間となります。

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/[ドメイン名]/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/[ドメイン名]/privkey.pem
This certificate expires on 2021-01-08.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

HTTP 検証を使った発行

HTTP 検証を使った証明書発行は、Web サーバーを別途必要とします。 セットアップしたストリーミングサーバーには、Web サーバーをセットアップしていないため、--standalone オプションを使うことにします。

証明書の発行は、以下のコマンドを実行します。

注意: 80番ポートを使ったサービスが起動していないことを事前に確認してください

sudo certbot certonly --standalone --domain [ドメイン名] --email [Eメールアドレス] --agree-tos

HTTP によるドメイン所有の検証は、Certbot ツールが起動した Web サーバーにより自動化され、 証明書の発行が完了すると、以下のように出力さます。 発行された証明書は、同様に、/etc/letsencrypt/live/[ドメイン名]/ 以下のフォルダに保存されます。

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for [ドメイン名]

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/[ドメイン名]/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/[ドメイン名]/privkey.pem
This certificate expires on 2021-01-08.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Wowza Streaming Engine への HTTPS サーバー証明書の設定

Certbot ツールを使って発行した HTTPS 証明書 (およびサーバー秘密鍵) は、以下のディレクトリに格納されています。

  • HTTPS 証明書 (X.509 証明書): /etc/letsencrypt/live/[ドメイン名]/cert.pem
  • サーバー秘密鍵: /etc/letsencrypt/live/[ドメイン名]/privkey.pem

/etc/letsencrypt/live/ ディレクトリ以下に最新の HTTPS 証明書が保存され、 /etc/letsencrypt/archives ディレクトリ以下に古い HTTPS 証明書も含めた過去に発行したすべての証明書が含まれます。

PEM 形式のファイルとして保存されており、証明書や鍵のバイナリデータが BASE64 方式でエンコードされたテキスト形式のファイルとなっています。

HTTPS 証明書の内容を確認するには、OpenSSL コマンドを使って、以下のコマンドを実行します。

sudo openssl x509 -text -in /etc/letsencrypt/live/[ドメイン名]/cert.pem

注意: 管理者権限のみアクセス可能となっているため、sudo コマンドを使って openssl コマンドを実行します

Wowza Streaming Engine で HTTPS 証明書を利用するためには、Java Key Store 形式 (.jks) に変換する必要があります。

HTTPS 証明書とサーバー秘密鍵を Java Key Store 形式 (.jks) に変換する

Java Key Store 形式 (.jks) は、X.509 証明書や対応する秘密鍵などをパスワードに基づく鍵で保護された1つのファイルに保管することが可能な鍵ストアファイル形式です。 Java SE ランタイムに含まれる keytool と呼ばれるツールを使って管理することができます。このツールでは、PKCS#12 形式から JKS 形式に変換することが可能なため、 まず、OpenSSL コマンドを使って PKCS#12 形式の鍵ストアを作成し、その後、JKS 形式の鍵ストアファイルを作成します。

PKCS#12 形式 (.p12) は、IETF で既定されたフォーマット仕様で、JKS 形式と同様に、X.509 証明書や対応する秘密鍵などをパスワードに基づく鍵で保護された1つのファイルに保管することが可能な鍵ストアファイル形式です

以下のコマンドを実行して、PKCS#12 形式の鍵ストアファイルを作成し、作成した PKCS#12 形式の鍵ストアファイルを JKS 形式の鍵ストアファイルに変換します。

export DOMAIN=[ドメイン名]
sudo openssl pkcs12 -export -legacy \
    -in /etc/letsencrypt/live/${DOMAIN}/fullchain.pem \
    -inkey /etc/letsencrypt/live/${DOMAIN}/privkey.pem \
    -out ${DOMAIN}.p12 -password pass:[パスワード文字列]
sudo /usr/local/WowzaStreamingEngine/java/bin/keytool -v -importkeystore \
    -destkeystore ${DOMAIN}.jks -deststoretype jks -deststorepass [JKSパスワード文字列] \
    -srckeystore ${DOMAIN}.p12 -srcstoretype pkcs12 -srcstorepass [パスワード文字列]

HTTPS ストリーミングを設定する

既定の設定では、HTTPS (443番ポート) は有効になっていません。

以下の手順で、Wowza Streaming Engine の Virtual Host 設定に HTTPS ポート設定を追加します。

  1. /usr/local/WowzaStreamingEngine/conf/VHost.xml を編集し、以下の部分を有効にします (XMLのコメントアウト <!-- --> を削除します)。

          <!-- 443 with SSL -->
          <HostPort>
                  <Name>Default SSL Streaming</Name>
                  <Type>Streaming</Type>
                  <ProcessorCount>${com.wowza.wms.TuningAuto}</ProcessorCount>
                  <IpAddress>*</IpAddress>
                  <Port>443</Port>
                  <HTTPIdent2Response></HTTPIdent2Response>
                  <SSLConfig>
                          <KeyStorePath>${com.wowza.wms.context.VHostConfigHome}/conf/keystore.jks</KeyStorePath>
                          <KeyStorePassword>[JKSパスワード文字列]</KeyStorePassword>
                          <KeyStoreType>JKS</KeyStoreType>
                          <DomainToKeyStoreMapPath></DomainToKeyStoreMapPath>
                          <SSLProtocol>TLS</SSLProtocol>
                          <Algorithm>SunX509</Algorithm>
                          <CipherSuites></CipherSuites>
                          <Protocols></Protocols>
                          <AllowHttp2>false</AllowHttp2>
                  </SSLConfig>
                  <SocketConfiguration>
                          <ReuseAddress>true</ReuseAddress>
                          <ReceiveBufferSize>65000</ReceiveBufferSize>
                          <ReadBufferSize>65000</ReadBufferSize>
                          <SendBufferSize>65000</SendBufferSize>
                          <KeepAlive>true</KeepAlive>
                          <AcceptorBackLog>100</AcceptorBackLog>
                  </SocketConfiguration>
                  <HTTPStreamerAdapterIDs>cupertinostreaming,smoothstreaming,sanjosestreaming,dvrchunkstreaming,mpegdashstreaming</HTTPStreamerAdapterIDs>
                  <HTTPProviders>
                          <HTTPProvider>
                                  <BaseClass>com.wowza.wms.http.HTTPCrossdomain</BaseClass>
                                  <RequestFilters>*crossdomain.xml</RequestFilters>
                                  <AuthenticationMethod>none</AuthenticationMethod>
                          </HTTPProvider>
                          <HTTPProvider>
                                  <BaseClass>com.wowza.wms.http.HTTPClientAccessPolicy</BaseClass>
                                  <RequestFilters>*clientaccesspolicy.xml</RequestFilters>
                                  <AuthenticationMethod>none</AuthenticationMethod>
                          </HTTPProvider>
                          <HTTPProvider>
                                  <BaseClass>com.wowza.wms.http.HTTPProviderMediaList</BaseClass>
                                  <RequestFilters>*jwplayer.rss|*jwplayer.smil|*medialist.smil|*manifest-rtmp.f4m</RequestFilters>
                                  <AuthenticationMethod>none</AuthenticationMethod>
                          </HTTPProvider>
                          <HTTPProvider>
                                  <BaseClass>com.wowza.wms.http.HTTPServerVersion</BaseClass>
                                  <RequestFilters>*ServerVersion</RequestFilters>
                                  <AuthenticationMethod>none</AuthenticationMethod>
                          </HTTPProvider>
                  </HTTPProviders>
          </HostPort>
    
  2. JKS鍵ストアファイルをコピーします

    sudo cp ${PWD}/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/conf/
    sudo ln -s /usr/local/WowzaStreamingEngine/conf/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/conf/keystore.jks
    
  3. Wowza Streaming Engine を再起動する

    sudo systemctl restart WowzaStreamingEngine
    

HTTPS 証明書が正しくロードされ、443 ポート番号が正しくセットアップされたか、 Wowza Streaming Engine ログ (/usr/local/WowzaStreamingEngine/logs/wowzastreamingengine_access.log) を確認します。

以下の3行の出力がログに含まれていれば、正しくセットアップされています。

_defaultVHost_  SSL ([any]:443): keyStorePath:/usr/local/WowzaStreamingEngine/conf/keystore.jks
_defaultVHost_  Bind attempt ([any]:443:4)
_defaultVHost_  Bind successful ([any]:443)

また、以下のコマンドを実行し、443 ポートにアクセスできるかどうかも確認します。

curl https://[ドメイン名]/ServerVersion

Wowza Streaming Engine のバージョン情報が表示されれば問題ありません。

REST API インターフェスで HTTPS を有効する

既定では Wowza Streaming Engine の REST API インターフェースは HTTP/8087 となっています。

以下の手順で、REST API インターフェースを HTTPS で公開するよう設定を変更します。

  1. /usr/local/WowzaStreamingEngine/conf/Server.xml を編集し、以下のように設定します。

        <RESTInterface>
            :
          <SSLConfig>
                  <Enable>true</Enable>
                  <KeyStorePath>${com.wowza.wms.ConfigHome}/conf/keystore.jks</KeyStorePath>
                  <KeyStorePassword>[JKSパスワード文字列]</KeyStorePassword>
                  <KeyStoreType>JKS</KeyStoreType>
                  <SSLProtocol>TLS</SSLProtocol>
                  <Algorithm>SunX509</Algorithm>
                  <CipherSuites></CipherSuites>
                  <Protocols></Protocols>
          </SSLConfig>
          <IPWhiteList>*</IPWhiteList>
            :
        </RESTInterface>
    

    または、以下のコマンドで Server.xml を変更することも可能です。

    cat /usr/local/WowzaStreamingEngine/conf/Server.xml | \
      xmlstarlet edit --update "/Root/Server/RESTInterface/SSLConfig/Enable" --value "true" | \
      xmlstarlet edit --update "/Root/Server/RESTInterface/SSLConfig/KeyStorePath" --value "\${com.wowza.wms.ConfigHome}/conf/keystore.jks" | \
      xmlstarlet edit --update "/Root/Server/RESTInterface/SSLConfig/KeyStorePassword" --value "[JKSパスワード文字列]" | \
      | xmlstarlet format -t | xmlstarlet c14n > /tmp/Server.xml
    sudo cp /tmp/Server.xml /usr/local/WowzaStreamingEngine/conf/Server.xml
    
  2. JKS鍵ストアファイルをコピーします

    sudo cp ${PWD}/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/conf/
    sudo ln -s /usr/local/WowzaStreamingEngine/conf/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/conf/keystore.jks
    
  3. Wowza Streaming Engine を再起動する

    sudo systemctl restart WowzaStreamingEngine
    

HTTPS 証明書が正しくロードされ、443 ポート番号が正しくセットアップされたか、 Wowza Streaming Engine ログ (/usr/local/WowzaStreamingEngine/logs/wowzastreamingengine_access.log) を確認します。

RESTServer: Bind attempt ([any]:8087)
RESTServer: Bind successful ([any]:8087)
Wowza REST API started
RESTServer: SSL:Yes

また、以下のコマンドを実行し、8087 ポートに HTTPS でアクセスできるかどうかも確認します。

curl https://[ドメイン名]:8087/ -u [ユーザー名]:[パスワード]

Wowza Streaming Engine のバージョン情報が表示されれば問題ありません。

管理 UI からアクセスする場合は、Wowza Streaming Engine Manager 管理サービスの HTTPS を有効にする必要があります

Wowza Streaming Engine Manager 管理サービスの HTTPS を有効する

既定では Wowza Streaming Engine Manager 管理サービスは、HTTP/8086 となっています。

以下の手順で、管理サービスを HTTPS/8090 で公開するよう設定を変更します。

  1. /usr/local/WowzaStreamingEngine/manager/conf/tomcat.properties.xml を編集し、以下のように設定します。

    httpsPort=8090
    httpsKeyStore=conf/keystore.jks
    httpsKeyStorePassword=zRostinB9e8aTnFjfdEd
    
  2. JKS鍵ストアファイルをコピーします

    sudo cp ${PWD}/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/manager/conf/
    sudo ln -s /usr/local/WowzaStreamingEngine/manager/conf/${DOMAIN}.jks /usr/local/WowzaStreamingEngine/manager/conf/keystore.jks
    
  3. Wowza Streaming Engine を再起動する

    sudo systemctl restart WowzaStreamingEngineManager
    

REST API インターフェースの HTTPS を有効にした場合は、管理 UI にアクセスし、"[+] Server" をクリックし、REST API インターフェースのホスト名を https://[HTTPS 証明書のドメイン名]:8087 に設定し、[Sign In] をクリックしてログインします。

まとめ

この記事では、Let’s Encrypt で発行した証明書を使って、Wowza Streaming Engine の HTTPS 証明書のセットアップを行いました。

Certbot ツールを利用すると、証明書の発行前後にカスタムのイベントフックスクリプトを動作させることができるため、DNS レコードの追加・更新の自動化が可能となったり、証明書の有効期限が切れに合わせて自動更新スクリプトを cron で動作させたり、などの運用も可能となります。

Certbot で発行した証明書から JKS 形式のファイルを生成するスクリプトを Gist で公開しています。