【実務・中級編】 セキュリティとハードニング – Redis

Redis要塞化計画:デフォルト設定のまま本番稼働させる愚行を断つ

テックリードの私だ。
今日のコードレビューで、新人が書いたコンテナ定義ファイルを見て冷や汗をかいた。本番環境のRedis接続文字列にパスワードがなく、`bind 0.0.0.0`が平然と設定されていたのだ。

「動けばいい」というフェーズは、開発環境のローカルホストで終わらせろ。
インメモリデータベースであるRedisは、その爆発的なパフォーマンスと引き換えに、セキュリティ設定を怠れば「全世界に向けてデータを全公開する踏み台」になり下がる。事実、インターネット上に野晒しにされたRedisが暗号化身代金要求(Ransomware)の標的になった事件は枚挙に暇がない。

今回は、実務の現場でインフラ・バックエンドを預かるエンジニアが、絶対に押さえておくべきRedisのハードニング(要塞化)の極意を授ける。

—

1. ネットワーク分離:そもそも「外」に出さない

セキュリティの第一歩は、ファイアウォールとバインド設定だ。Redisをパブリックなネットワークに露出させるなど、実弾を装填した銃を子供に渡すようなものだ。

`bind` ディレクティブの厳格化

デフォルトのままである `bind 127.0.0.1` はローカルからのみのアクセスを強要するが、コンテナ環境(DockerやKubernetes)ではコンテナ間通信のために設定変更が求められる。その際、安易に `0.0.0.0`(全インターフェース受付)にしてはならない。

redis.conf
信頼されたプライベートIP、または特定の内部ブリッジネットワークのみを指定する
bind 127.0.0.1 10.0.1.50

ポートフォワーディングの排除とセキュリティグループ

クラウド環境(AWSならSecurity Group、GCPならVPC防火壁)において、Redisのデフォルトポートである `6379` は、いかなる外部IPからもアクセス不可に設定すること。アプリケーションサーバーが稼働するサブネットからのトラフィックのみを許可し、ロードバランサーや踏み台サーバーですら直通させないのが鉄則だ。

—

2. 認証の徹底:単なるパスワードから「脱却」する

昔ながらの `requirepass` による全体パスワード認証は、現代の本番運用では不十分だ。どのアプリケーションも同じ「root権限」で全データにアクセスできてしまうからだ。

ここで導入すべきが、Redis 6以降のACL(Access Control List)である。

モダンなACL設計パターン

実務では、アプリケーションごとに専用のユーザーを切り、触れるべきキー空間(Key Space)とコマンドを制限する「最小権限の原則」を適用する。

例えば、キャッシュを扱う `app_cache` ユーザーと、セッションを扱う `app_session` ユーザーを次のように定義する。

redis.conf または ACLファイル(users.acl)での定義

1. キャッシュ用ユーザー:キャッシュキー(cache:)のみ操作可能、危険なコマンドは禁止
user app_cache on >SecureCachePassword202X ~cache: +@read +@write -FLUSHALL -FLUSHDB

2. セッション用ユーザー:セッションキー(session:)のみ、ハッシュ系コマンドに限定
user app_session on >SecureSessionPassword202X ~session: +hset +hget +hdel +expire

  • `on / off`: ユーザーの有効/無効
  • `>`: パスワードの設定(ハッシュ化して保存することも可能)
  • `~`: アクセス可能なキーのパターン(プレフィックス制御)
  • `+@read` / `-FLUSHALL`: コマンドカテゴリの許可と個別拒否

これにより、仮にセッション用のアプリケーションが脆弱性を突かれても、キャッシュデータや他のデータベース領域を破壊されるリスクを隔離できる。

—

3. 危険なコマンドの無効化(リネームと封殺)

Redisには、実行されるとシステム全体に致命的な影響を与える「神コマンド」が存在する。これらはデフォルトでは誰でも実行可能になっており、非常に危険だ。

対象となる代表格:

  • `FLUSHALL` / `FLUSHDB`: 全データの一括消去
  • `CONFIG`: サーバー設定の動的変更・参照
  • `KEYS`: 本番環境でのフルスキャン(O(N)でシングルスレッドを完全にブロックする)
  • `DEBUG`: デバッグ用クラッシュ・メモリ調査

対策:コマンドのリネームによる無効化

これらを完全に封じるには、`redis.conf` で空文字列にリネームするのが最も確実な設計パターンのひとつだ。

redis.conf
存在しないコマンド名(あるいは推測不可能なランダム文字列)にリネームして無効化する
rename-command FLUSHALL “”
rename-command FLUSHDB “”
rename-command CONFIG “A_VERY_LONG_AND_UNGUESSABLE_SECRET_STRING_CONFIG”

特に `CONFIG` コマンドは、実行されるとサーバー上の設定ファイルパスやログファイルの場所などが露出するため、本番環境では原則として封殺すべきである。

—

4. パフォーマンスとセキュリティのトレードオフを理解する

「セキュリティを厳しくすると、パフォーマンスが落ちるのではないか?」
優秀なエンジニアなら当然そう疑うはずだ。結論から言えば、ACLや認証のオーバーヘッドは、CPUキャッシュにヒットするレベルで極小であり、実用上のパフォーマンス低下は無視できるレベルだ。

ただし、設計上の罠が1つある。

⚠️ 注意すべきアンチパターン:`KEYS` コマンドの罠と `SCAN` への移行

セキュリティやモニタリングの文脈で、キーの一覧を取得したくなる衝動に駆られるが、前述の通り `KEYS ` はシングルスレッドのRedisにおいて、数百万件のキーが存在する場合に数秒〜数十秒のブロック(応答停止)を引き起こす。

もし運用ツールやセキュリティ監査スクリプトでキーを走査する必要があるなら、絶対に `KEYS` は使わず、カーソルベースの非同期イテレーションである `SCAN` コマンド を使わせる設計にすること。

良い例:カーソルを使った安全な走査(ブロッキングを回避)
SCAN 0 MATCH session: COUNT 100

ACLを設定する際も、監査用ユーザーに無制限の `keys` コマンドを許可せず、`+scan` のみを許可するべきだ。

—

チーフアーキテクトからの総括

セキュリティとは、「何重もの防壁(ディフェンス・イン・デプス)」の構築に他ならない。
「内ネットだから大丈夫」「コンテナの中だから安全」という甘えは、システム障害やデータ流出という形で、必ず最悪のタイミングでツケを払わされる。

今日からお前のプロジェクトでも以下のチェックリストを即座に実行しろ。

1. `bind` 設定を見直し、外向きインターフェースを遮断したか?
2. 全体パスワード運用を捨て、ACLで最小権限のユーザーを切り分けたか?
3. `FLUSHALL` や `CONFIG` などの劇薬コマンドを無効化したか?
4. アプリケーションからの接続に、専用ユーザーの認証情報が正しく渡されているか?

コードレビューでこれらがクリアされていないコードを見かけたら、容赦なくプルリクエストをフェイル(Reject)させろ。それが、プロフェッショナルなエンジニアリングチームの矜持だ。

コメント

タイトルとURLをコピーしました