このチュートリアルの以前のバージョンは、Justin Ellingwoodによって作成されました。
はじめに
Radis は、柔軟性、パフォーマンス、幅広い言語サポートで知られるインメモリ型の Key-Value ストアです。このチュートリアルでは、Ubuntu 20.04サーバーにRedisをインストールし、設定、保護する方法を説明します。
前提条件
このガイドを完了するには、sudo
権限が付与されたroot以外のユーザー、ufw
で設定したファイアウォールを備えたUbuntu 20.04サーバーへのアクセスが必要です。Ubuntu 20.04初期サーバーセットアップガイドに従ってこれをセットアップします。
ステップ1 — Redisのインストールと設定
APTパッケージマネージャーを使用して、公式UbuntuリポジトリからRedisをインストールします。執筆時点では、デフォルトリポジトリで利用可能なバージョンは5.0.7です。
まず、ローカルapt
パッケージキャッシュを更新します。
次に、以下のように入力しRedisをインストールします。
- sudo apt install redis-server
これにより、Redisとその依存関係がダウンロード、インストールされます。続いて、インストール中に自動生成されたRedis設定ファイルに、1点重要な変更を加えます。
任意のテキストエディターでこのファイルを開きます。
- sudo nano /etc/redis/redis.conf
ファイル内で、supervised
ディレクティブを検索します。このディレクティブを使用すると、Redisをサービスとして管理するinitシステムを宣言でき、その操作をより詳細に制御できます。supervised
ディレクティブは、デフォルトでno
に設定されています。systemdinitシステムを使用するUbuntuを実行しているので、systemd
に変更します。
/etc/redis/redis.conf
. . .
# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
# supervised no - no supervision interaction
# supervised upstart - signal upstart by putting Redis into SIGSTOP mode
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
# supervised auto - detect upstart or systemd method based on
# UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
# They do not enable continuous liveness pings back to your supervisor.
supervised systemd
. . .
現時点でRedis設定ファイルに必要な変更はこれだけなので、終了したら保存して閉じます。nano
を使用した場合は、CTRL + X
、Y
、ENTER
キーを押します。
次に、Redisサービスを再起動して、設定ファイルに加えた変更を反映します。
- sudo systemctl restart redis.service
これで、Radisのインストールと設定が完了しマシン上で稼働します。ただし、使用を開始する前に、Redisが正しく機能しているか確認しましょう。
ステップ2 — Redisのテスト
新たにインストールしたあらゆるソフトウェアと同様に、Redisを設定変更する前に、期待どおりに機能しているか確認することをお勧めします。このステップではRedisが正常に動作しているか確認する方法をいくつか見ていきます。
まず、Redisサービスが稼働しているか確認します。
- sudo systemctl status redis
エラーなく稼働していれば、このコマンドは次のような出力を生成します。
Output
● redis-server.service - Advanced key-value store
Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-04-30 23:26:54 UTC; 4s ago
Docs: http://redis.io/documentation,
man:redis-server(1)
Process: 36552 ExecStart=/usr/bin/redis-server /etc/redis/redis.conf (code=exited, status=0/SUCCESS)
Main PID: 36561 (redis-server)
Tasks: 4 (limit: 2345)
Memory: 1.8M
CGroup: /system.slice/redis-server.service
└─36561 /usr/bin/redis-server 127.0.0.1:6379
. . .
ここで、Redisが稼働し既に有効になっていることがわかります。つまり、サーバーが起動するたびにRedisも起動するように設定されています。
注:通常、これがRedisの多くの共通ユースケースで推奨される設定です。サーバーが起動するたびにRedisを手動で起動させたい場合は、次のコマンドで設定します。
- sudo systemctl disable redis
Redisが正しく機能しているかテストするには、Redisのコマンドラインクライアントredis-cli
を使用してサーバーに接続します。
次のプロンプトで、ping
コマンドにより接続テストをします。
Output
PONG
この出力から、サーバーと接続できているのが分かります。次に、以下を実行して鍵を設定できるか確認します。
Output
OK
次のように入力して値を取得します。
すべてが機能していれば、保存した値が取得できるはずです。
Output
"It's working!"
値を取得できることを確認したら、Redisプロンプトを終了してシェルに戻ります。
最終テストとして、Redisが停止または再起動した後でもデータを保持できるか確認します。これを行うには、まずRedisインスタンスを再起動します。
- sudo systemctl restart redis
次に、コマンドラインクライアントに再接続します。
そこでテスト値がまだ利用可能であることを確認します。
鍵の値にまだアクセスできます。
Output
"It's working!"
終了したら、シェルを再度終了します。
これで、Redisのインストールは完全に機能し、使用できる状態にあります。 ただし、デフォルトの構成設定の一部は安全でないため、悪意のある攻撃者に、サーバーとそのデータに攻撃してアクセスする機会を与えてしまいます。 このチュートリアルの後半の手順では、Redisの公式Webサイトで明記された、これらの脆弱性を軽減する方法について説明します。 これらの手順はオプションであり、従わない選択した場合でもRedisは引き続き機能しますが、システムのセキュリティを強化するためにも、これらを完了することを強くお勧めします。
ステップ3 — localhostヘのバインド
デフォルトでは、Redisはlocalhostからのみアクセス可能です。ただし、これとは異なるチュートリアルに従ってRedisをインストール・設定した場合は、どこからでも接続できるように設定ファイルを更新した可能性があります。これは、localhostへのバインドほど安全ではありません。
これを修正するには、Redis設定ファイルを開いて編集します。
- sudo nano /etc/redis/redis.conf
この行を見つけて、コメントが解除されていることを確認します(#
があれば削除します)。
/etc/redis/redis.conf
bind 127.0.0.1 ::1
終了したらファイルを保存して閉じます(CTRL + X
、Y
、ENTER
キーを押します)。
次に、サービスを再起動して、systemdが変更を読み取ることを確認します。
- sudo systemctl restart redis
この変更が有効になったことを確認するには、次のようにnetstat
コマンドを実行します。
- sudo netstat -lnp | grep redis
Output
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 14222/redis-server
tcp6 0 0 ::1:6379 :::* LISTEN 14222/redis-server
注:netstat
コマンドがデフォルトで使用できないことがあります。その場合は、次のコマンドで(ほかの便利なネットワークツールと併せて)インストールできます。
- sudo apt install net-tools
この出力から、redis-server
プログラムがlocalhost127.0.0.1
にバインドされ、たった今設定ファイルに加えた変更が反映されていることが分かります。その列に別のIPアドレス(例えば0.0.0.0
)が表示された場合、コメントを解除した行が間違っていないか再度確認し、Redisサービスを再起動します。
Redisインストールがlocalhostのみlistenするようになったため、悪意のある攻撃者がサーバーにリクエストを送信したり、サーバーにアクセスしたりすることはさらに困難になります。ただし、Redisはまだ、ユーザーが自身の設定や保持するデータを変更する前に、自分自身の認証を要求する設定にはなっていません。これを改善するために、Redisでは、Redisクライアント(redis-cli
)を介して変更を行う前に、ユーザーにパスワード認証を要求することができます。
ステップ4 — Redisパスワードの設定
Redisパスワードを設定すると、2つのビルトインセキュリティ機能の1つであるauth
コマンドが有効になります。これは、クライアントがデータベースにアクセスするために認証要求するものです。 パスワードは、Redisの設定ファイル/etc/redis/redis/redis.conf
で直接設定されるため、任意のエディターでそのファイルをもう一度開きます。
- sudo nano /etc/redis/redis.conf
SECURITY
セクションまでスクロールして、次のコメント付きディレクティブを探します。
/etc/redis/redis.conf
. . .
# requirepass foobared
. . .
#
を削除してコメント解除し、foobared
を安全なパスワードに変更します。
注:redis.conf
ファイル内のrequirepass
ディレクティブの上に、コメントアウトされた次の警告があります。
/etc/redis/redis.conf
. . .
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
. . .
したがって、パスワードとして非常に強力で非常に長い値を指定することが重要です。パスワードを自身で作成するよりも、次の例のとおり、openssl
コマンドを使用すれば、ランダムなパソワードを生成できます。ここに示されるように、1つ目のコマンドの出力を2つ目のopenssl
コマンドにパイプすることで、1つ目のコマンドで生じた改行が削除されます。
- openssl rand 60 | openssl base64 -A
出力は次のように見えるはずです。
Output
RBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE
そのコマンド出力をrequirepass
の新しい値としてコピー&ペーストすると、次のように表示されます。
/etc/redis/redis.conf
requirepass RBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE
パスワードを設定したら、ファイルを保存して閉じ、Redisを再起動します。
- sudo systemctl restart redis.service
パスワードが機能するかテストするには、Redisクライアントを開きます。
以下、Redisパスワードが機能するかどうかテストするために使用される一連のコマンドを示します。 最初のコマンドは、認証する前に鍵を値に設定しようとします。
認証しなかったため機能しません。そのため、Redisはエラーを返します。
Output
(error) NOAUTH Authentication required.
次のコマンドは、Redis設定ファイルで指定されたパスワードで認証します。
Redisが承認します。
Output
OK
その後、前のコマンドを再度実行すると成功します。
Output
OK
get key1
はRedisに新しいキーの値を問い合わせます。
Output
"10"
認証後にRedisクライアントでコマンドを実行できることを確認したら、redis-cli
を終了します。
次に、Redisコマンドの名前変更について説明します。Redisコマンドは、誤って入力したり、悪意のある攻撃者によって入力されると、マシンに重大な損傷を与えるおそれがあります。
ステップ5 — 危険なコマンドの名前変更
Redisに組み込まれたセキュリティ機能には他に、危険とみなされる特定のコマンドの名前を変更したり完全に無効化する機能があります。
そのようなコマンドは、権限のないユーザーに実行されると、データの再設定、破棄、または消去に利用されかねません。コマンドの名前の変更・無効化は、認証パスワードと同じく/etc/redis/redis.conf
ファイルのSECURITY
セクションで設定します。
危険とみなされるコマンドには次のものがあります:FLUSHDB
、FLUSHALL
、KEYS
、PEXPIRE
、DEL
、CONFIG
、SHUTDOWN
、BGRRITEAOF
、BGSAVE
、SAVE
、SPOP
、SREM
、RENAME
、DEBUG
この一覧がすべてを網羅しているわけではありませんが、一覧の各コマンドを名前変更・無効化することは、Redisサーバーのセキュリティを強化するための良い出発点となります。
コマンドを無効にするか名前を変更するかは、特定のニーズまたはサイトのニーズによって異なります。悪用されるおそれのあるコマンドで使用しないことがわかっているものは、無効化できます。 それ以外の場合は、名前を変更するのが得策でしょう。
Redisコマンドを名前変更・無効化するには、設定ファイルをもう一度開きます。
- sudo nano /etc/redis/redis.conf
警告:次のステップで示されるコマンドを無効化・名前変更する方法は一例です。自分にとって意味のあるコマンドのみ無効化・名前変更してください。redis.io/commandsで全コマンド一覧を自身で見直し、どのように誤用されうるかを見極めます。
コマンドを無効にするには、以下に示すように、空の文字列(間に文字を含まない引用符のペアで指定)に名前を変更するだけです。
/etc/redis/redis.conf
. . .
# It is also possible to completely kill a command by renaming it into
# an empty string:
#
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
. . .
コマンドの名前を変更するには、次の例に示すように別の名前を付けます。変更されたコマンドの名前は、覚えやすくて推測されにくいものである必要があります。
/etc/redis/redis.conf
. . .
# rename-command CONFIG ""
rename-command SHUTDOWN SHUTDOWN_MENOT
rename-command CONFIG ASC12_CONFIG
. . .
変更を保存してファイルを閉じます。
コマンドの名前を変更した後、Redisを再起動して変更を適用します。
- sudo systemctl restart redis.service
新しいコマンドをテストするには、Redisコマンドラインを入力します。
次に、認証をおこないます。
Output
OK
前の例のように、CONFIG
コマンドをASC12_CONFIG
に名前変更したと仮定しましょう。最初に、元のCONFIG
コマンドを使用してみてください。名前を変更したため、失敗するはずです。
Output
(error) ERR unknown command `config`, with args beginning with:
また一方、名前を変更したコマンドの呼び出しは成功するはずです。大文字と小文字の区別はありません。
- asc12_config get requirepass
Output
1) "requirepass"
2) "your_redis_password"
最後に、redis-cli
を終了します。
既にRedisコマンドラインを使用していて、Redisを再起動する場合は、再認証する必要があることに注意してください。再認証せずにコマンドを入力すると、このエラーが表示されます。
Output
NOAUTH Authentication required.
コマンドの名前変更の実践に関して、/etc/redis/redis.conf
のSECURITY
セクションの最後に次の注意書きが記されています。
/etc/redis/redis.conf
. . .
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to replicas may cause problems.
. . .
注:Redisプロジェクトは、「マスター」と「スレーブ」という用語を採択してしますが、DigitalOceanは一般的に別の呼称「プライマリ」と「セカンダリ」を使用します。 混乱を避けるために、ここではRedisドキュメントで使用される用語を採択しました。
つまり、名前を変更したコマンドがAOFファイルにない、あるいはあったとしてもAOFファイルがスレーブに送信されていない場合、問題ではありません。
したがって、コマンドの名前を変更する際には上記に留意してください。コマンドの名前を変更する最良のタイミングは、AOF永続性を使用していないときか、インストール直後、つまりRedisを使用するアプリケーションをインストールする前です。
AOFを使用してマスター・スレーブ構成のインストールを処理している場合は、プロジェクトのGitHub Issueページのこの回答を検討します。筆者の質問への回答は次のとおりです。
コマンドはAOFに書き込まれ、送られたのと同じ方法でスレーブに複製されます。このため、コマンドの名前が同様に変更されていないインスタンスでAOFをリプレイしようとすると、コマンドが実行できないため、不整合が発生する可能性があります(スレーブも同様)。
したがって、名前の変更を処理する最良の方法は、マスター・スレーブインストールのインスタンスすべてに、名前を変更したコマンドが適用されるようにすることです。
まとめ
このチュートリアルでは、Redisをインストールして設定し、Redisインストールが正しく機能しているか検証し、ビルトインセキュリティ機能を使用して悪意のある攻撃者からの攻撃に対する脆弱性を低減しました。
いったん誰かがサーバーにログインしてしまうと、装備したRedis固有のセキュリティ機能を簡単に回避できることに留意してください。したがって、Redisサーバーの最も重要なセキュリティ機能はファイアウォール(前提条件の初期サーバーセットアップチュートリアル通りに設定したファイアウォール)です。悪意のある攻撃者がそのフェンスを飛び越えることは極めて困難です。