Ubuntu 18.04にRedisをインストールして保護する方法

このチュートリアルの以前のバージョンはJustin Ellingwoodによって書かれました

前書き

Redisは、柔軟性、パフォーマンス、および幅広い言語サポートで知られるメモリ内のKey-Valueストアです。 このチュートリアルでは、Ubuntu 18.04サーバーでRedisをインストール、構成、および保護する方法を示します。

前提条件

このガイドを完了するには、sudo権限を持つroot以外のユーザーがいて、基本的なファイアウォールが構成されているUbuntu18.04サーバーにアクセスする必要があります。 これは、Initial Server Setup guideに従って設定できます。

開始する準備ができたら、sudoユーザーとしてUbuntu 18.04サーバーにログインし、以下を続行します。

[[step-1 -—- installing-and-configuring-redis]] ==ステップ1—Redisのインストールと構成

Redisの最新バージョンを入手するために、aptを使用して公式のUbuntuリポジトリからインストールします。

ローカルのaptパッケージキャッシュを更新し、次のように入力してRedisをインストールします。

sudo apt update
sudo apt install redis-server

これにより、Redisとその依存関係がダウンロードおよびインストールされます。 これに続いて、Redis構成ファイルで行う重要な構成変更が1つあります。これは、インストール中に自動的に生成されました。

任意のテキストエディターでこのファイルを開きます。

sudo nano /etc/redis/redis.conf

ファイル内で、supervisedディレクティブを見つけます。 このディレクティブを使用すると、Redisをサービスとして管理するinitシステムを宣言でき、その操作をより詳細に制御できます。 supervisedディレクティブは、デフォルトでnoに設定されています。 systemd initシステムを使用する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構成ファイルに加える必要があるのはこれだけなので、完了したら保存して閉じます。 次に、Redisサービスを再起動して、構成ファイルに加えた変更を反映します。

sudo systemctl restart redis.service

これで、Redisをインストールして設定し、マシンで実行しています。 ただし、使用を開始する前に、Redisが正しく機能しているかどうかを最初に確認することをお勧めします。

[[step-2 -—- testing-redis]] ==ステップ2—Redisのテスト

新しくインストールされたソフトウェアの場合と同様に、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 Wed 2018-06-27 18:48:52 UTC; 12s ago
     Docs: http://redis.io/documentation,
           man:redis-server(1)
  Process: 2421 ExecStop=/bin/kill -s TERM $MAINPID (code=exited, status=0/SUCCESS)
  Process: 2424 ExecStart=/usr/bin/redis-server /etc/redis/redis.conf (code=exited, status=0/SUCCESS)
 Main PID: 2445 (redis-server)
    Tasks: 4 (limit: 4704)
   CGroup: /system.slice/redis-server.service
           └─2445 /usr/bin/redis-server 127.0.0.1:6379
. . .

ここでは、Redisが実行されており、既に有効になっていることがわかります。つまり、サーバーが起動するたびに起動するように設定されています。

[。注意]##

Note:この設定は、Redisの多くの一般的なユースケースに適しています。 ただし、サーバーを起動するたびに手動でRedisを起動する場合は、次のコマンドでこれを構成できます。

sudo systemctl disable redis

Redisが正しく機能していることをテストするには、コマンドラインクライアントを使用してサーバーに接続します。

redis-cli

次のプロンプトで、pingコマンドを使用して接続をテストします。

ping
OutputPONG

この出力は、サーバー接続がまだ生きていることを確認します。 次に、次を実行してキーを設定できることを確認します。

set test "It's working!"
OutputOK

次のように入力して値を取得します。

get test

すべてが機能していると仮定すると、保存した値を取得できます。

Output"It's working!"

値を取得できることを確認したら、Redisプロンプトを終了してシェルに戻ります。

exit

最終テストとして、Redisが停止または再起動した後でもデータを保持できるかどうかを確認します。 これを行うには、まずRedisインスタンスを再起動します。

sudo systemctl restart redis

次に、コマンドラインクライアントにもう一度接続し、テスト値がまだ利用可能であることを確認します。

redis-cli
get test

キーの値には引き続きアクセスできる必要があります。

Output"It's working!"

終了したら、シェルを再度終了します。

exit

これにより、Redisインストールが完全に動作し、使用できる状態になります。 ただし、デフォルトの構成設定の一部は安全ではないため、悪意のあるアクターがサーバーとそのデータに攻撃してアクセスする機会を提供します。 このチュートリアルの残りの手順では、official Redis websiteで規定されているように、これらの脆弱性を軽減する方法について説明します。 これらの手順はオプションであり、従わないことを選択した場合でもRedisは機能しますが、システムのセキュリティを強化するために、これらの手順を完了することをお勧めします。

[[step-3 -—- binding-to-localhost]] ==ステップ3—localhostへのバインド

デフォルトでは、Redisはlocalhostからのみアクセスできます。 ただし、これとは異なるチュートリアルに従ってRedisをインストールおよび構成した場合は、どこからでも接続できるように構成ファイルを更新した可能性があります。 これは、localhostへのバインドほど安全ではありません。

これを修正するには、Redis構成ファイルを開いて編集します。

sudo nano /etc/redis/redis.conf

この行を見つけて、コメントが外されていることを確認します(#が存在する場合は削除します)。

/etc/redis/redis.conf

bind 127.0.0.1 ::1

終了したら、ファイルを保存して閉じます(CTRL + XYENTERの順に押します)。

次に、サービスを再起動して、systemdが変更を読み取ることを確認します。

sudo systemctl restart redis

この変更が有効になったことを確認するには、次のnetstatコマンドを実行します。

sudo netstat -lnp | grep redis
Outputtcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      14222/redis-server
tcp6       0      0 ::1:6379                :::*                    LISTEN      14222/redis-server

この出力は、構成ファイルに加えた変更を反映して、redis-serverプログラムがlocalhost127.0.0.1)にバインドされていることを示しています。 その列に別のIPアドレス(たとえば、0.0.0.0)が表示されている場合は、正しい行のコメントを解除したことを再確認して、Redisサービスを再起動する必要があります。

Redisインストールがlocalhostのみをリッスンしているため、悪意のあるアクターがサーバーにリクエストを送信したり、サーバーにアクセスしたりすることがより困難になります。 ただし、Redisは現在、ユーザーが自身の構成または保持しているデータを変更する前に自分自身を認証することを要求するように設定されていません。 これを解決するために、Redisでは、Redisクライアント(redis-cli)を介して変更を加える前に、ユーザーにパスワードによる認証を要求することができます。

[[step-4 -—- configuring-a-redis-password]] ==ステップ4—Redisパスワードの設定

Redisパスワードを設定すると、2つの組み込みセキュリティ機能の1つであるauthコマンドが有効になります。このコマンドでは、クライアントがデータベースにアクセスするために認証する必要があります。 パスワードはRedisの構成ファイル/etc/redis/redis.confで直接構成されているため、お好みのエディターでそのファイルを再度開きます。

sudo nano /etc/redis/redis.conf

SECURITYセクションまでスクロールし、次のようなコメント付きディレクティブを探します。

/etc/redis/redis.conf

# requirepass foobared

#を削除してコメントを解除し、foobaredを安全なパスワードに変更します。

[。注意]##

Note:redis.confファイルのrequirepassディレクティブの上に、コメント付きの警告があります。

# 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コマンドを使用してランダムなパスワードを生成できます。 ここに示すように、最初のコマンドの出力を2番目のopensslコマンドにパイプすることにより、最初のコマンドによって生成された改行をすべて削除します。

openssl rand 60 | openssl base64 -A

出力は次のようになります。

OutputRBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE

そのコマンドの出力をrequirepassの新しい値としてコピーして貼り付けた後、次のようになります。

/etc/redis/redis.confrequirepass RBOJ9cCNoGCKhlEBwQLHri1g+atWgn4Xn4HwNUbtzoVxAYxkiYBi7aufl4MILv1nxBqR4L6NNzI0X6cE

パスワードを設定したら、ファイルを保存して閉じ、Redisを再起動します。

sudo systemctl restart redis.service

パスワードが機能することをテストするには、Redisコマンドラインにアクセスします。

redis-cli

以下は、Redisパスワードが機能するかどうかをテストするために使用される一連のコマンドを示しています。 最初のコマンドは、認証前にキーを値に設定しようとします。

set key1 10

認証されなかったため機能しません。そのため、Redisはエラーを返します。

Output(error) NOAUTH Authentication required.

次のコマンドは、Redis構成ファイルで指定されたパスワードで認証します。

auth your_redis_password

Redisは次のことを認めます:

OutputOK

その後、前のコマンドを再度実行すると成功します:

set key1 10
OutputOK

get key1は、Redisに新しいキーの値を照会します。

get key1
Output"10"

認証後にRedisクライアントでコマンドを実行できることを確認したら、redis-cliを終了できます。

quit

次に、Redisコマンドの名前の変更について説明します。Redisコマンドは、誤って入力した場合や悪意のあるアクターによって入力された場合、マシンに重大な損傷を与える可能性があります。

[[step-5 -—- renaming-dangerous-commands]] ==ステップ5—Dangerousコマンドの名前を変更する

Redisに組み込まれている他のセキュリティ機能には、危険と見なされる特定のコマンドの名前変更または完全な無効化が含まれます。

権限のないユーザーが実行すると、そのようなコマンドを使用してデータを再構成、破棄、または消去することができます。 認証パスワードと同様に、コマンドの名前変更または無効化は、/etc/redis/redis.confファイルの同じSECURITYセクションで構成されます。

危険と見なされるコマンドには、FLUSHDBFLUSHALLKEYSPEXPIREDELCONFIGSHUTDOWNが含まれます。 s、BGREWRITEAOFBGSAVESAVESPOPSREMRENAME、およびDEBUG。 これは包括的なリストではありませんが、そのリスト内のすべてのコマンドの名前を変更または無効にすることは、Redisサーバーのセキュリティを強化するための良い出発点です。

コマンドを無効にするか名前を変更するかは、特定のニーズまたはサイトのニーズによって異なります。 悪用される可能性のあるコマンドを使用しないことがわかっている場合は、無効にすることができます。 それ以外の場合は、名前を変更することをお勧めします。

Redisコマンドを有効または無効にするには、構成ファイルをもう一度開きます。

sudo nano  /etc/redis/redis.conf

[.warning]#Warning:コマンドを無効にして名前を変更する方法を示す次の手順は例です。 自分にとって意味のあるコマンドを無効にするか、名前を変更することだけを選択する必要があります。 コマンドの完全なリストを自分で確認し、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コマンドラインを入力します。

redis-cli

次に、認証します。

auth your_redis_password
OutputOK

前の例のように、CONFIGコマンドの名前をASC12_CONFIGに変更したと仮定します。 まず、元のCONFIGコマンドを使用してみてください。 名前を変更したため、失敗するはずです。

config get requirepass
Output(error) ERR unknown command 'config'

ただし、名前を変更したコマンドの呼び出しは成功します。 大文字と小文字は区別されません。

asc12_config get requirepass
Output1) "requirepass"
2) "your_redis_password"

最後に、redis-cliを終了できます。

exit

既にRedisコマンドラインを使用していて、Redisを再起動する場合は、再認証する必要があることに注意してください。 それ以外の場合、コマンドを入力するとこのエラーが発生します。

OutputNOAUTH Authentication required.

[。警告]##

コマンドの名前変更の慣行に関して、/etc/redis/redis.confSECURITYセクションの最後に次のような注意事項があります。

Please note that changing the name of commands that are logged into the AOF file or transmitted to slaves may cause problems.

注意: Redisプロジェクトでは、「マスター」と「スレーブ」という用語を使用することを選択しますが、DigitalOceanは通常、「プライマリ」と「セカンダリ」の代替を好みます。混乱を避けるために、ここのRedisドキュメントで使用されている用語を使用することを選択しました。

つまり、名前を変更したコマンドがAOFファイルにない場合、またはAOFファイルがスレーブに送信されていない場合は、問題はありません。

したがって、コマンドの名前を変更しようとするときは、そのことに留意してください。 コマンドの名前を変更する最適なタイミングは、AOF永続性を使用していないとき、またはインストール直後、つまりRedisを使用するアプリケーションがデプロイされる前です。

AOFを使用していて、マスタースレーブのインストールを処理している場合は、this answer from the project’s GitHub issue pageを考慮してください。 以下は、著者の質問への返信です。

コマンドはAOFに記録され、送信されたのと同じ方法でスレーブに複製されるため、同じ名前変更を持たないインスタンスでAOFを再生しようとすると、コマンドを実行できないため、不整合が発生する可能性があります(スレーブについても同じ)。

したがって、そのような場合に名前の変更を処理する最良の方法は、名前が変更されたコマンドがマスタースレーブインストールのすべてのインスタンスに適用されることを確認することです。

結論

このチュートリアルでは、Redisをインストールして構成し、Redisインストールが正しく機能していることを検証し、組み込みのセキュリティ機能を使用して、悪意のある攻撃者からの攻撃に対する脆弱性を減らしました。

サーバーに誰かがログインすると、導入したRedis固有のセキュリティ機能を簡単に回避できることに注意してください。 したがって、Redisサーバーで最も重要なセキュリティ機能はファイアウォール(前提条件のInitial Server Setupチュートリアルに従った場合に構成したもの)です。これにより、悪意のある攻撃者がそのフェンスを飛び越えることが非常に困難になります。