Ubuntu16.04でPHPのセッションハンドラーとしてRedisサーバーを設定する方法
序章
Redisは、オープンソースのKey-Valueキャッシュおよびストレージシステムであり、ハッシュ、リスト、セット、ビットマップなどのいくつかのデータ型を高度にサポートしているため、データ構造サーバーとも呼ばれます。 また、クラスタリングをサポートしているため、可用性が高くスケーラブルな環境で役立ちます。
このチュートリアルでは、Ubuntu16.04で実行されているPHPアプリケーションのセッションハンドラーとして使用される外部Redisサーバーをインストールして構成する方法を説明します。
セッションハンドラーは、セッションに保存されたデータの保存と取得を担当します。 デフォルトでは、PHPはこれにファイルを使用します。 これは単一のサーバーでは十分に機能しますが、セッション情報が単一のサーバーに関連付けられているため、パフォーマンスとスケーラビリティに大きな制限があります。
外部セッションハンドラーは、複数のアプリケーションサーバーで使用できる共有セッションデータの中央の場所を提供します。 これは、ロードバランサーの背後にスケーラブルなPHP環境を作成する場合に重要です。これは、どのアプリケーションサーバーが個々のリクエストを処理するかに関係なく、同じセッションデータが利用できるためです。
前提条件
このチュートリアルでは、2台のサーバーを使用してセッション処理を構成します。 フォローするには、次のものが必要です。
- Ubuntu16.04でLAMPまたはLEMPを実行しているPHPWebサーバー。 このサーバーをwebと呼びます。
- 2番目のクリーンなUbuntu16.04サーバー。Redisがインストールされます。 このサーバーをredisと呼びます。
これらの各サーバーでsudo
権限が設定されたroot以外のユーザーが必要です。 また、各サーバーで基本的なファイアウォールが実行されていると想定します。 両方のサーバーでUbuntu16.04初期サーバーセットアップガイドに従って、これらの要件の両方をセットアップできます。
ステップ1:Redisサーバーとクライアントソフトウェアをインストールする
最初のステップは、両方のマシンに必要なソフトウェアをインストールすることです。 redisマシンにはRedisサーバーが必要です。 web マシンに、セッション処理用のRedis PHP拡張機能と、テスト用のRedisコマンドラインクライアントをインストールします。
Redisサーバーのインストール
最初に行う必要があるのは、redisマシンでRedisサーバーを実行することです。
ChrisLeaが提供する信頼できるPPAリポジトリを備えた通常のUbuntuパッケージマネージャーを使用します。 これは、Redisの最新の安定バージョンを確実に入手するために必要です。
注:一般的なセキュリティアドバイスとして、信頼できるソースからのPPAのみを使用する必要があります。
まず、以下を実行してPPAリポジトリを追加します。
- sudo apt-add-repository ppa:chris-lea/redis-server
ENTER
を押して確認します。
次に、パッケージインデックスを更新し、次のように入力してRedisサーバーをインストールします。
- sudo apt-get update
- sudo apt-get install redis-server
これで、Redisがサーバーにインストールされて実行されているはずです。 次のように入力して、サービスが実行され、接続を受け入れていることをテストします。
- redis-cli ping
Redis server outputPONG
これにより、ポート6379のlocalhostで実行されているRedisインスタンスに接続されます。 応答としてPONGを取得する必要があります。
RedisクライアントとPHP拡張機能のインストール
次に、RedisコマンドラインクライアントとRedisPHP拡張機能をwebサーバーにインストールします。 コマンドラインクライアントを使用して、接続と認証を簡単にテストします。 PHP拡張機能を使用して、セッションデータを保存します。
ローカルパッケージインデックスを更新し、次のように入力してwebサーバーにソフトウェアをインストールします。
- sudo apt-get update
- sudo apt-get install redis-tools php-redis
これで、redis-cli
ツールにアクセスできるようになりますが、テストするサーバーにはまだアクセスできません。
ステップ2:外部接続を受け入れるようにRedisを構成する
デフォルトでは、Redisはlocalhost
からの接続のみを許可します。つまり、基本的には、Redisがインストールされているサーバー内からのみアクセスできます。 他のサーバーからの接続を許可するには、この構成を変更する必要があります。
Redisはネイティブ暗号化オプションを提供せず、信頼できるピアの分離されたネットワークにデプロイされていることを前提としています。 つまり、外部接続を安全に許可するには、両方のサーバーが分離されたネットワーク上にあるか、別の方法でサーバー間のトラフィックを保護する必要があります。
Redisが分離されたネットワークにデプロイされている場合…
サーバーが分離されたネットワークで動作している場合は、おそらく、分離されたネットワークのIPアドレスにバインドするようにRedisの構成ファイルを調整するだけで済みます。
redis サーバーで、Redis構成ファイルをバックアップして開きます。
- sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
- sudo nano /etc/redis/redis.conf
bind
行を見つけて、Redisサーバーの分離されたネットワークIPアドレスを追加します。
bind 127.0.0.1 isolated_IP_address
ファイルを保存して閉じます。 次のように入力して、サービスを再起動します。
- sudo systemctl restart redis-server.service
Redisポートへのアクセスを開きます。
- sudo ufw allow 6379
これで、Redisは分離されたネットワークからの接続を受け入れることができます。
Redisが分離されたネットワークにデプロイされていない場合…
分離されていない、または制御していないネットワークの場合、トラフィックを他の手段で保護することが不可欠です。 Redisサーバーへのトラフィックを保護するには、次のような多くのオプションがあります。
- stunnel を使用したトンネリング: redis サーバーに着信トンネルを設定し、webサーバーに発信トンネルを設定する必要があります。 Webサーバーはローカルポートに接続して、リモートのRedisサービスと通信します。
- spiped を使用したトンネリング:webサーバーは
spiped
クライアントマシンとして機能する必要があります。 各サーバーにsystemdユニットファイルを作成する必要があります。 Webサーバーはローカルポートに接続して、リモートのRedisサービスと通信します。 - PeerVPNを使用したVPNのセットアップ:VPN上で両方のサーバーにアクセスできる必要があります。 web サーバーは、VPNIPアドレスを使用してredisサーバーにアクセスできるようになります。
上記のいずれかの方法を使用して、webサーバーからredisサーバーへの安全なアクセスを構成します。 webマシンがリモートマシンのRedisサービスに接続するために使用するIPアドレスとポートを知っている必要があります。
この時点で、WebサーバーからRedisサーバーに安全にアクセスできるはずです。
ステップ3:Redisサーバーのパスワードを設定する
Redisインストールにセキュリティの層を追加するには、サーバーデータにアクセスするためのパスワードを設定することをお勧めします。 /etc/redis/redis.conf
でRedis構成ファイルを編集します。
- sudo nano /etc/redis/redis.conf
requirepass
ディレクティブを見つけて、強力なパスフレーズに設定します。 Redisトラフィックは外部から保護されている必要がありますが、これによりRedis自体に認証が提供されます。 Redisは高速で、パスワードの試行をレート制限しないため、ブルートフォース攻撃から保護するために強力で複雑なパスフレーズを選択してください。
requirepass yourverycomplexpasswordhere
終了したら、ファイルを保存して閉じます。
Redisサービスを再起動して、変更を実装します。
- sudo systemctl restart redis-server.service
これで、Redisサーバーは認証されていないリクエストを拒否するはずです。
ステップ4:Redisの接続と認証をテストする
変更が期待どおりに機能するかどうかをテストするには、webマシンからRedisサービスに接続します。
デフォルトでは、Redisサーバーはローカルインターフェイスで6379をリッスンしますが、上記で説明した各ネットワークセキュリティオプションは、外部の関係者に対して何らかの方法でデフォルトを変更します。 redis-cli
クライアントと-h
オプションを使用してIPアドレスを指定し、-p
オプションを使用してリモートサービスへの接続に必要なポートを指定できます。 デフォルトのオプション(それぞれ127.0.0.1と6379)を使用している場合は、これらのいずれかを省略できます。
使用する値は、ネットワークトラフィックを保護するために使用した方法によって異なります。
- 分離ネットワーク:Redisサーバーの分離ネットワークIPアドレスを使用します。 デフォルトのRedisポート(6379)が使用されているため、言及する必要はありません:
redis-cli -h redis_isolated_IP
- stunnelまたはspiped:リモートRedisサービスにトンネリングするローカルポートを使用します:
redis-cli -p 8000
- PeerVPN :RedisサーバーのVPN IPアドレスを使用します:
redis-cli -h 10.8.0.1
一般的な形式は次のとおりです。
- redis-cli -h ip_to_contact_redis -p port_to_contact_redis
webサーバーからリモートRedisインスタンスに接続できるはずです。
パスワードを定義してデータにアクセスしようとすると、AUTHエラーが発生するはずです。
- keys *
Web server output(error) NOAUTH Authentication required.
認証するには、AUTH
コマンドを実行し、/etc/redis/redis.conf
ファイルで定義したものと同じパスワードを入力する必要があります。
- AUTH yourverycomplexpasswordhere
クレデンシャルが受け入れられたことを示す応答としてOKが表示されます。
Web server outputOK
次に、Redis内で設定されているキーを一覧表示します。
- keys *
これが新しいRedisサーバーの場合、出力は次のようになります。
Web server output(empty list or set)
この出力は、Redisサーバーが空であることを意味します。これはまさに私たちが期待していることです。 web サーバーは、このRedisサーバーをセッションハンドラーとして使用するようにまだ構成されていません。
次のように入力して、コマンドシェルに戻ります。
- exit
認証で正常に接続できることを確認したので、Redisをデフォルトのセッションハンドラーにすることができます。
手順5:RedisをWebサーバーのデフォルトのセッションハンドラーとして設定する
次に、 webサーバー上のphp.ini
ファイルを編集して、PHPのデフォルトのセッションハンドラーを変更する必要があります。 このファイルの場所は、現在のスタックによって異なります。
デフォルトのリポジトリからインストールされたUbuntu16.04のLAMPスタックの場合、これは通常/etc/php/7.0/apache2/php.ini
です。 Ubuntu16.04のLEMPスタックの場合、パスは通常/etc/php/7.0/fpm/php.ini
です。 これらの場所のいずれかが正しいことを確認した場合は、次のセクションをスキップしてください。
(オプション)正しいphp.iniファイルを見つける
メインのphp.ini
ファイルの場所がわからない場合は、phpinfo()
機能を使用して確認できます。 webサーバーでドキュメントルートのinfo.php
というファイルを開きます。デフォルトでは、LAMPとLEMPの両方で/var/www/html
になります。
- sudo nano /var/www/html/info.php
次のコードをファイルに配置します。
<?php
phpinfo();
ブラウザでwebサーバーのドメイン名またはIPアドレスにアクセスし、続いて/info.php
にアクセスします。
http://web_server_domain_or_IP/info.php
「ロードされた構成ファイル」を含む行を探します。ロードされたメインのphp.ini
の正確な場所を見つける必要があります。
終了したら、環境に関する機密情報が表示されるため、ファイルを削除します。
- sudo rm /var/www/html/info.php
ファイルの場所がわかったので、編集に進むことができます。
構成の変更
php.ini
ファイルを開いて編集します。
デフォルト構成でLAMPスタックを使用している場合、必要なコマンドは次のとおりです。
- sudo nano /etc/php/7.0/apache2/php.ini
デフォルト構成でLEMPスタックを使用している場合、必要なコマンドは次のとおりです。
- sudo nano /etc/php/7.0/fpm/php.ini
上記のphpinfo()
メソッドを使用して別のパスを発見した場合は、代わりにそのパスをここに置き換えてください。
php.ini
ファイル内で、session.save_handler
を含む行を検索します。 デフォルト値はfiles
です。 これをredis
に変更して、RedisPHP拡張機能を使用します。
[label php.ini]
session.save_handler = redis
次に、session.save_path
を含む行を見つけます。 コメントを外して値を変更し、Redis接続文字列が含まれるようにする必要があります。
接続文字列は、次の形式を使用して、すべて1行で作成できます。
tcp://IP_address:port?auth=redis_password
繰り返しますが、適切な値は、選択した安全なネットワーク戦略によって異なります。 前にredis-cli
コマンドに指定したのと同じ値を使用します。 たとえば、stunnel
またはspiped
を使用している場合、session.save_path
は次のようになります。
[label php.ini]
session.save_path = "tcp://127.0.0.1:8000?auth=yourverycomplexpasswordhere"
終了したら、ファイルを保存して閉じます。 次に、PHPサービスを再起動して、変更を実装します。
LAMP 環境では、次のように入力します。
- sudo systemctl restart apache2
LEMP 環境では、次のように入力します。
- sudo systemctl restart php7.0-fpm
これで、セッションハンドラーとしてRedisを使用するようにPHPを構成する必要があります。
ステップ6:Redisセッション処理をテストする
セッションがRedisによって処理されるようにするには、セッションに情報を格納するPHPスクリプトまたはアプリケーションが必要になります。 カウンターを実装する簡単なスクリプトを使用します。 ページをリロードするたびに、印刷された番号が増加します。
ドキュメントルートフォルダ内のwebサーバーにtest.php
という名前のファイルを作成します。
- sudo nano /var/www/html/test.php
内部に、次のコードを貼り付けます。
[label /var/www/html/test.php]
<?php
//simple counter to test sessions. should increment on each page reload.
session_start();
$count = isset($_SESSION['count']) ? $_SESSION['count'] : 1;
echo $count;
$_SESSION['count'] = ++$count;
ファイルを保存して閉じます。
スクリプトにアクセスするには、ブラウザでwebサーバーのパブリックIPアドレスに続けて/test.php
を指定します。
http://web_server_public_IP/test.php
ページをリロードするたびに表示される数が増えるはずです。
次に、 redis マシンで、redis-cli
を使用してセッションを開きます。 ローカルインスタンスに接続しているため、IPアドレスやポートを指定する必要はありません。
- redis-cli
Redisパスワードを使用して認証します。
- AUTH yourverycomplexpasswordhere
Redis server outputOK
次に、既存のキーを確認します。
- keys *
PHPセッションの新しいエントリが表示されます。
Redis server output1) "PHPREDIS_SESSION:2ofnvhhr6gdvp88u0c4e7kb800"
キーの値を尋ねると、現在のカウンター値を確認できるはずです。
- get PHPREDIS_SESSION:2ofnvhhr6gdvp88u0c4e7kb800
Redis server output"count|i:6;"
これは、セッション情報がRedisサーバーに保存されていることを示しています。 追加のWebサーバーをRedisサーバーに接続して、セッションを一元管理できます。
結論
Redisは、PHPのセッションハンドラーとしても使用できる強力で高速なKey-Valueストレージサービスであり、セッションストレージ用の分散システムを提供することでスケーラブルなPHP環境を実現します。 PHPアプリケーションのスケーリングの詳細については、次の記事を確認してください:PHPアプリケーションの水平方向のスケーリング。