背景:なぜRedisは頻繁に攻撃の標的となるのか?
本番インフラ環境において、Redisはそのインメモリアーキテクチャにより毎秒数万件ものリクエストを処理します。この圧倒的な高速性は、Redisがパフォーマンスを極限まで最適化し、煩雑なアクセス制御レイヤーの多くを排除していることによって実現されています。元来、Redisの設計思想は「完全に隔離された信頼できる内部ネットワーク上でのみ実行される」ことを前提としていました。
しかし、実際の運用現場は異なります。Shodanなどの検索エンジンでは、パスワードすら設定されずにポート6379がインターネット上に直接公開されているRedisサーバーが、定常的に3万台以上検出されています。わずか数秒のポートスキャンを行うだけで、攻撃者はインスタンスへ容易に侵入できてしまうのが現状です。
被害はユーザーセッションやAPIトークンの漏洩だけにとどまりません。代表的な例として仮想通貨マイニングマルウェア「Kinsing」の攻撃キャンペーンが挙げられます。攻撃者はRedisの書き込み権限を悪用し、CONFIG SET dir /var/spool/cron/crontabs や /root/.ssh といったコマンドを実行してリバースシェルを埋め込み、Linuxサーバーのroot権限を完全に奪取します。そのため、サーバープロビジョニングの初期段階からRedisを適切に保護することが不可欠です。
環境準備
本ガイドの手順はUbuntu 22.04 LTSを前提としています。Debian 11/12やRocky Linux/RHEL 9でもほぼ同様の設定が可能です。なお、ACLやネイティブTLS機能をフル活用するには、Redis 6.0以上のバージョンが必要となります。
Redis Serverと証明書生成用のOpenSSLパッケージをインストールします:
sudo apt update
sudo apt install redis-server openssl -y
# バージョンの確認(6.0以上が必須)
redis-server -v
systemdサービスが正常に動作していることを確認します:
sudo systemctl status redis-server
Redisセキュリティ設定の手順
1. ネットワークインターフェースの制限とProtected Modeの有効化
Redisにおけるセキュリティインシデントの多くは、安易に 0.0.0.0 へバインドしていることが原因です。ループバックアドレスまたはVPCサブネット内のプライベートIP(例:10.0.1.5)のみを正確に指定してください。
設定ファイルを開きます:
sudo nano /etc/redis/redis.conf
次の2つのパラメータを探し、適切に更新します:
bind 127.0.0.1 ::1
protected-mode yes
バックエンドアプリケーションがRedisと同一サーバー上に同居している場合、上記の設定で十分です。protected-mode yes が有効になっていると、認証パスワードが設定されていない場合、Redisは外部からのすべての接続を自動的に遮断します。
2. 危険なコマンドの無効化またはリネーム
Redisの一部の管理コマンドは極めて高いリスクを伴います。例えば FLUSHALL コマンドは、瞬時に数百万件ものキャッシュキーを完全消去してしまう可能性があります。また CONFIG コマンド群は、ランタイム設定の上書きやファイルシステムへの介入を可能にします。
/etc/redis/redis.conf に以下のディレクティブを追加します:
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
rename-command CONFIG "SYS_ADMIN_CONFIG_8f9a2b"
空のダブルクォーテーション "" を指定すると、そのコマンドは完全に無効化されます。CONFIG コマンドについては、直接管理を行うシステム管理者のみがランタイムで調査できるよう、ランダムな文字列へリネームしておきます。
3. ACL(Access Control Lists)によるアプリケーション別のきめ細かな権限管理
Redis 6.0より前は、requirepass ディレクティブによってすべてのクライアントに単一の共通パスワードが割り当てられていました。そのため、Webアプリ、バックグラウンドワーカー、cronジョブに至るまで、すべてのサービスが共通の最高権限を使用していました。
ACL機能はこの課題を根本的に解決します。アプリケーションごとに専用ユーザーを作成し、許可された特定のキープレフィックスに対してのみ読み書きを許可することが可能です。
権限管理用の独立したファイルを作成します:
sudo touch /etc/redis/users.acl
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 600 /etc/redis/users.acl
/etc/redis/redis.conf 内でこのファイルを読み込むよう定義します:
aclfile /etc/redis/users.acl
/etc/redis/users.acl を開き、ユーザーを定義します:
sudo nano /etc/redis/users.acl
設定例:
# パスワードのないデフォルトユーザーを無効化
user default off
# Webアプリ用ユーザー: app:cache: プレフィックスのみ操作可能、危険なコマンドをすべて禁止
user web_app on >K9#mX2$pL9vQ!wZ ~app:cache:* +@read +@write -@dangerous
# 管理者ユーザー: すべての操作を許可
user sysadmin on >T7@vR5*bN1#cE8! ~* +@all
ACL構文の主な構成要素は以下の通りです:
user default off: デフォルトアカウントを無効化します。>Password: プレーンテキストでパスワードを設定します(Redisはメモリ保存時に自動的にSHA-256でハッシュ化します)。~app:cache:*: ネームスペースを制限します。Webサービスはこのプレフィックスを持つキーのみ操作可能となり、他サービスのセッションや課金データの不正読み取りを防ぎます。+@read +@write -@dangerous: 通常の読み取り/書き込みコマンドグループを許可し、サーバーのハングアップや設定変更を引き起こす危険なコマンドをすべて除外します。
4. TLSによるサーバー間通信の暗号化
Redisプロトコルはデフォルトで平文通信を行います。バックエンドとRedisが内部ネットワーク上の異なるサーバーに配置されている場合、ネットワークスイッチへの不正侵入やARPスプーフィングなどにより、回線を流れるセッションキーなどの情報が盗聴されるリスクがあります。
TLSを有効にすると、5%〜12%程度のCPUオーバーヘッドが発生し、レイテンシが0.1ms〜0.3msほど増加します。しかし、引き換えにネットワーク上を流れるすべてのペイロードを安全に保護することができます。
秘密鍵と証明書(内部オレオレ認証局/プライベートCA)を生成します:
sudo mkdir -p /etc/redis/tls
cd /etc/redis/tls
# プライベートCAの作成
sudo openssl genrsa -out ca.key 4096
sudo openssl req -x509 -new -nodes -sha256 -key ca.key -days 3650 -subj '/CN=Internal-Redis-CA' -out ca.crt
# Redisサーバー用の秘密鍵と証明書の作成
sudo openssl genrsa -out redis.key 2048
sudo openssl req -new -sha256 -key redis.key -subj '/CN=redis-server' -out redis.csr
sudo openssl x509 -req -in redis.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out redis.crt -days 365
# 秘密鍵ファイルの権限設定
sudo chown -R redis:redis /etc/redis/tls
sudo chmod 600 /etc/redis/tls/*.key
sudo chmod 644 /etc/redis/tls/*.crt
/etc/redis/redis.conf を更新します:
# 平文ポートを無効化
port 0
# TLS暗号化ポートを有効化
tls-port 6379
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients no
設定を反映させるためにサービスを再起動します:
sudo systemctl restart redis-server
動作確認とセキュリティ監査
1. redis-cliによるACL権限の検証
先ほど作成した web_app ユーザーでTLS接続を行います:
redis-cli --tls --cacert /etc/redis/tls/ca.crt -a 'K9#mX2$pL9vQ!wZ' --user web_app
検証のためにサンプルの操作を実行します:
# 1. 許可されたプレフィックスに対する操作 -> 成功
SET app:cache:session_user_99 "authenticated"
GET app:cache:session_user_99
# 2. プレフィックス外に対する操作 -> 即座に拒否される
SET config:jwt_secret "my-secret-key"
# 出力: (error) NOPERM this user has no permissions to access the 'config:jwt_secret' key
# 3. ブラックリストに含まれるコマンドの実行 -> ブロックされる
KEYS *
# 出力: (error) NOPERM this user has no permissions to run the 'keys' command
2. セキュリティ違反のリアルタイムモニタリング
Redisにはランタイム監査用の強力なツール ACL LOG が備わっています。クライアントが誤ったパスワードを入力したり、禁止されたコマンドを呼び出したり、許可外のキーパターンにアクセスしたりするたびに、タイムスタンプ、クライアントIP、違反コマンドが記録されます:
127.0.0.1:6379> ACL LOG 5
特定の不審なIPから auth-error や key-perm といったエラーが継続的に記録されている場合、システムがポートスキャンなどの攻撃を受けているか、ワーカーサービスの設定ミスが発生している可能性が考えられます。
併せて、証明書の読み込みエラーや接続リセットを検知するためにサービスログも確認してください:
sudo tail -f /var/log/redis/redis-server.log
ネットワークの隔離(bind/ポート設定)、最小権限の原則(ACL)、通信経路の暗号化(TLS)という3層の多層防御を組み合わせることで、外部からのサイバー攻撃と内部的なデータ漏洩リスクの双方に対して強固なRedisインスタンスを構築できます。

