Ubuntu16.04でSpipedを使用してRedisへのトラフィックを暗号化する方法
序章
RedisはオープンソースのKey-Valueデータストアであり、永続性のためにオプションのディスク書き込みを備えたインメモリストレージモデルを使用しています。 トランザクション、Pub / Subメッセージングパターン、自動フェイルオーバーなどの機能を備えています。 Redisには、ほとんどの言語で記述されたクライアントがあり、推奨される言語はそのWebサイトに掲載されています。
Redisは、独自の暗号化機能を提供していません。 信頼できる関係者のみがアクセスできる、分離されたプライベートネットワークに展開されていることを前提として動作します。 ご使用の環境がその仮定に一致しない場合は、Redisトラフィックを暗号化で個別にラップする必要があります。
このガイドでは、spiped
と呼ばれる安全な配管プログラムを使用してRedisトラフィックを暗号化する方法を示します。 Redisクライアントとサーバー間のトラフィックは、専用のSSHトンネルと同様に、専用の暗号化されたトンネルを介してルーティングされます。 デモのために2台のUbuntu16.04サーバーを使用します。
前提条件
開始するには、各マシンでsudo
権限が設定されたroot以外のユーザーが必要です。 さらに、このガイドでは、基本的なファイアウォールが設定されていることを前提としています。 Ubuntu 16.04初期サーバーセットアップガイドに従って、これらの要件を満たすことができます。
続行する準備ができたら、以下に従ってください。
何が吐き出されますか?
spiped
ユーティリティは、インストールが簡単で、2つのネットワークソケット(通常のネットワークポートまたはUnixソケット)間の安全な通信用に構成されています。 2つのリモートサーバー間の暗号化通信を構成するために使用できます。 クライアントはローカルポートに接続し、spiped
はそれを暗号化でラップしてから、リモートサーバーに転送します。 サーバー側では、spiped
は構成されたポートをリッスンし、トラフィックを復号化してからローカルポート(この場合はRedisサーバーがリッスンするポート)に転送します。
spiped
を使用する利点は次のとおりです。
- Ubuntuは、デフォルトのリポジトリに
spiped
のパッケージを保持しています。 - Redisプロジェクトは現在、が
spiped
を使用してトラフィックを暗号化することを提案しています。 - 構成は簡単で直感的です。
- 目的ごとに新しいパイプが使用されます。 これは状況によっては不利になる場合がありますが、アクセスをきめ細かく制御できます。
いくつかの欠点は次のとおりです。
- クライアントは、デフォルト以外のローカルポートに接続することでリモートマシンに接続します。これは、最初は直感的ではない場合があります。
- レプリケーションまたはクラスタリングのために2つのRedisサーバーを接続する場合、サーバー間通信用に各マシンに2つのトンネルを構成する必要があります(1つはアウトバウンドトラフィック用、もう1つはインバウンドトラフィック用)。
- initスクリプトは含まれていないため、起動時に必要な接続を自動的に作成するには、initスクリプトを作成する必要があります。
これらの特性を念頭に置いて、始めましょう。
Redisサーバーとクライアントパッケージをインストールする
始める前に、一方のマシンにRedisサーバーをインストールし、もう一方のマシンでクライアントパッケージを利用できるようにする必要があります。 これらのいずれかまたは両方をすでに構成している場合は、スキップしてください。
注: Redisサーバーの命令は、後で接続をテストするために使用されるテストキーを設定します。 すでにRedisサーバーがインストールされている場合は、接続をテストするときに、このキーを設定するか、他の既知のキーを使用できます。
Redisサーバーのインストール
ChrisLeaのRedisサーバーPPAを使用して、最新バージョンのRedisをインストールします。 サードパーティのリポジトリを利用する場合は、常に注意してください。 この場合、Chris Leaは信頼できるパッケージャーであり、いくつかの人気のあるオープンソースプロジェクト向けに高品質で最新のパッケージを維持しています。
次のように入力して、PPAを追加し、Redisサーバーソフトウェアを最初のマシンにインストールします。
- sudo apt-add-repository ppa:chris-lea/redis-server
- sudo apt-get update
- sudo apt-get install redis-server
Enter と入力して、このプロセス中にプロンプトを受け入れます。
インストールが完了したら、次のように入力して、ローカルでRedisサービスに接続できることをテストします。
- redis-cli ping
ソフトウェアがインストールされて実行されている場合は、次のように表示されます。
Redis server outputPONG
後で使用できるキーを設定しましょう。
- redis-cli set test 'success'
testキーを値success
に設定しました。 spiped
を構成した後、クライアントマシンからこのキーにアクセスしようとします。
Redisクライアントのインストール
他のUbuntu16.04マシンはクライアントとして機能します。 必要なすべてのソフトウェアは、デフォルトのリポジトリのredis-tools
パッケージで入手できます。
- sudo apt-get update
- sudo apt-get install redis-tools
リモートRedisサーバーのデフォルト構成とファイアウォールがアクティブになっているため、現在、リモートRedisインスタンスに接続してテストすることはできません。
各コンピューターにspipedをインストールする
次に、各サーバーとクライアントにspiped
をインストールする必要があります。 前のセクションで何もインストールする必要がなかった場合は、インストールする前に、必ずsudo apt-get update
コマンドを含めてパッケージインデックスを更新してください。
- sudo apt-get install spiped
必要なソフトウェアがインストールされたので、spiped
が2台のマシン間のトラフィックを暗号化するために使用できる安全なキーを生成できます。
Redisサーバーで暗号化キーを生成する
次に、Redisサーバーの/etc
内にspiped
構成ディレクトリを作成して、暗号化用に生成するキーを保存します。
- sudo mkdir /etc/spiped
次のように入力して、安全なキーを生成します。
- sudo dd if=/dev/urandom of=/etc/spiped/redis.key bs=32 count=1
権限を調整して、生成されたキーファイルへのアクセスを制限します。
- sudo chmod 600 /etc/spiped/redis.key
Redisサーバーでキーを使用できるようになったので、systemdユニットファイルを使用してサーバーにspiped
を設定できます。
Redisサーバー用のsystemdユニットファイルを作成する
spiped
ユーティリティは非常にシンプルで、構成ファイルの読み取りをサポートしていません。 各パイプは手動で構成する必要があるため、Ubuntuパッケージには、起動時にパイプを自動的に開始するためのinitスクリプトが付属していません。
これらの問題を解決するために、単純なsystemdユニットファイルを作成します。 /etc/systemd/system
ディレクトリにある新しいユニットファイルを開いて開始します。
- sudo nano /etc/systemd/system/spiped-receive.service
内部に、[Unit]
セクションを作成してユニットを説明し、ネットワークが利用可能になった後にこのユニットが開始されるように順序を確立します。
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
次に、[Service]
セクションを開いて、実行する実際のコマンドを定義します。 spiped
では次のオプションを使用します。
-F
:フォアグラウンドで実行します。 systemd initシステムは、可能な場合にフォアグラウンドで実行されているサービスを管理するように設計されています。 フォアグラウンドで実行すると、必要な構成が簡素化されます。-d
:送信元ソケットからのトラフィックを復号化します。 これにより、spiped
に暗号化の方向が通知され、ソースからのトラフィックを復号化し、ターゲットからのトラフィックを暗号化することがわかります。-s
:これはソースソケットを定義します。 IPアドレスは角かっこで囲み、その後にコロン、ポートを続ける必要があります。 Redisサーバーの場合、これはパブリックIPアドレスとRedisポートに設定する必要があります。-t
:ターゲットソケット。 これは、復号化後にトラフィックが転送される場所です。 Redisはデフォルトでローカルホストのポート6379をリッスンするため、これを使用する必要があります。-k
:使用するキーファイルを指定します。 これは、前に生成した暗号化キーを指しているはずです。
これらのオプションはすべて、単一のExecStart
ディレクティブに含まれます。これは、このセクションで必要な唯一の項目です。
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -d -s [redis_server_public_IP]:6379 -t [127.0.0.1]:6379 -k /etc/spiped/redis.key
最後に、[Install]
セクションを含めて、有効になっている場合にユニットを自動的に起動するタイミングをsystemdに通知します。
[Unit]
Description=spiped receive for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -d -s [redis_server_public_IP]:6379 -t [127.0.0.1]:6379 -k /etc/spiped/redis.key
[Install]
WantedBy=multi-user.target
終了したら、ファイルを保存して閉じます。
spipedサービスを開始し、Redisサーバーでファイアウォールを調整します
次のように入力して、新しいspiped
ユニットを起動して有効にします。
- sudo systemctl start spiped-receive.service
- sudo systemctl enable spiped-receive.service
Redisサーバーで接続をリッスンしているサービスを確認すると、パブリックインターフェイスのポート6379でリッスンしているspiped
が表示されます。 また、Redisがローカルインターフェイスで同じポートをリッスンしていることも確認できます。
- sudo netstat -plunt
Redis server outputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 public_IP:6379 0.0.0.0:* LISTEN 4292/spiped
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 2679/redis-server 1
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1720/sshd
tcp6 0 0 :::22 :::* LISTEN 1720/sshd
spiped
はパブリックインターフェイスをリッスンしていますが、ファイアウォールはトラフィックを通過させるように構成されていない可能性があります。
ポート6379へのすべてのトラフィックを許可するには、次のように入力します。
- sudo ufw allow 6379
これにより、spiped
がリッスンしているパブリックインターフェイスのポート6379へのアクセスが可能になります。 spiped
ポートは、暗号化されたトラフィックのみを受け入れます。
暗号化キーをクライアントに転送する
暗号化キーをクライアントに転送するには、2つのサーバー間に安全な接続を確立する必要があります。 ssh
を使用します。これにより、既存の構成を活用できるようになります。
キーベースの認証を使用している場合は、SSHキーをRedisサーバーに転送して接続を確立する必要があります。 これは、パスワードベースのシステムでは必要ありません。
キーベースの認証のための追加の手順
Redisサーバーから切断します。
- exit
次に、ローカルマシンで、SSHエージェントが実行されていることと、SSHエージェントに秘密鍵が追加されていることを確認します。
- eval `ssh-agent`
- ssh-add
次に、Redisサーバーに再接続し、-A
フラグを追加してキーを転送します。
- ssh -A sammy@redis_server_public_IP
これで、以下の手順に進むことができます。
キーの転送
キーファイルにアクセスするにはローカルsudo
権限が必要なため、Redisサーバーからクライアントに接続します。 これでファイルを転送できます。以下のコマンドの最後にコロンが含まれていることを確認してください。
- sudo -E scp /etc/spiped/redis.key sammy@redis_client_public_IP:
scp
は、クライアントマシン上のユーザーのホームディレクトリに書き込みます。
キーを転送した後、クライアントマシンに/etc/spiped
ディレクトリを作成します。
- sudo mkdir /etc/spiped
暗号化キーを新しいディレクトリに移動します。
- sudo mv ~/redis.key /etc/spiped
アクセスを制限するには、アクセス許可をロックダウンします。
- sudo chmod 600 /etc/spiped/redis.key
クライアントがサーバーの暗号化キーのコピーを持っているので、spiped
構成のクライアント側を構成できます。
Redisクライアント用のsystemdユニットファイルを作成する
Redisサーバーで行ったのと同じように、クライアント側でspiped
のsystemdユニットファイルを作成する必要があります。
次のように入力して、新しいsystemdユニットファイルを開きます。
- sudo nano /etc/systemd/system/spiped-send.service
内部で、[Unit]
セクションを開いてサービスについて説明し、ネットワークの可用性に依存することを確認します。
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
次に、[Service]
セクションを開いて、spiped
プロセスを実行します。 ここで使用されるオプションは、Redisサーバーで使用されるオプションと非常に似ていますが、次の違いがあります。
-e
:送信元ソケットに入るトラフィックを暗号化する必要があることを指定します。 これにより、ソースソケットとターゲットソケットの関係が確立されます。-s
:以前と同様に、ソースソケットを定義します。 ただし、この場合、ソースは、ローカルRedisクライアントが接続できるローカルインターフェイス上の任意の使用可能なポートです。-t
:以前と同様に、ターゲットソケットを定義します。 クライアントの場合、これはリモートRedisサーバーのパブリックIPアドレスと開かれたポートになります。
これらは、ExecStart
ディレクティブを使用して再度設定されます。
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -e -s [127.0.0.1]:8000 -t [redis_server_public_IP]:6379 -k /etc/spiped/redis.key
最後に、[Install]
セクションを含めて、有効になっている場合にユニットがいつ起動するかを定義します。
[Unit]
Description=spiped sending for Redis
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/bin/spiped -F -e -s [127.0.0.1]:8000 -t [redis_server_public_IP]:6379 -k /etc/spiped/redis.key
[Install]
WantedBy=multi-user.target
終了したら、ファイルを保存して閉じます。
クライアントでspipedサービスを開始し、接続をテストします
これで、クライアントでspiped
サービスを開始し、起動時に自動的に開始できるようになります。
- sudo systemctl start spiped-send.service
- sudo systemctl enable spiped-send.service
クライアントのトンネルが正しく設定されていることを確認します。
- sudo netstat -plunt
Redis client outputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN 3264/spiped
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1705/sshd
tcp6 0 0 :::22 :::* LISTEN 1705/sshd
ご覧のとおり、spiped
はローカルポート8000で接続をリッスンしています。
これで、クライアントをローカルインターフェイスのポート8000にポイントすることで、リモートRedisインスタンスに接続できるようになります。
- redis-cli -p 8000 ping
Redis client outputPONG
このガイドの冒頭で設定したテストキーをクエリします。
- redis-cli -p 8000 get test
Redis client output"success"
これにより、リモートデータベースに正常にアクセスできることが確認されます。
トンネルを使用せずにリモートRedisサーバーと通信できない不可能であることを確認するために、リモートポートへの直接接続を試みることができます。
- redis-cli -h redis_server_public_IP -p 6379 ping
Redis client outputError: Protocol error, got "\xac" as reply type byte
ご覧のとおり、トラフィックは、トンネルを介して正しく暗号化されている場合にのみ、リモートRedisポートで受け入れられます。
マルチクライアントおよびサーバー間通信のための上記の例の拡張
上で概説した例では、単一のRedisサーバーと単一のクライアントの簡単な例を使用しました。 ただし、これらの同じ方法は、より複雑な相互作用に適用できます。
この例を拡張して複数のクライアントを処理するのは簡単です。 上記のアクションを実行する必要があります。
- 新しいクライアントにRedisクライアントソフトウェアと
spiped
パッケージをインストールします - 暗号化キーを新しいクライアントに転送します
spiped
systemdユニットファイルを新しいクライアントマシンにコピーしますspiped
サービスを開始し、起動時に開始できるようにします
安全なサーバー間通信をセットアップするには(たとえば、レプリケーションまたはクラスタリング用)、2つの並列トンネルをセットアップする必要があります。
-
新しいサーバーに、Redisサーバーパッケージと
spiped
をインストールします -
新しいRedisサーバーの新しい暗号化キーを生成します(ファイルに一意の名前を使用します)
-
暗号化キーを一方のサーバーからもう一方のサーバーに
/etc/spiped
ディレクトリにコピーします -
各サーバー(既存のサーバーを含む)に
spiped
systemdユニットファイルを作成して、各サーバーが各役割を果たすファイルを持つようにします。- 外部ポートをローカルRedisにマッピングする受信ユニットファイル
- ローカルポートをリモートサーバーの公開ポートにマッピングする送信ユニットファイル
-
新しいRedisサーバーのファイアウォールで外部ポートを開きます
-
Redis構成ファイルを調整して、ローカルにマップされたポートに接続してリモートサーバーにアクセスするように各Redisインスタンスを構成します(必要なディレクティブはサーバーの関係によって異なります)。 詳細については、Redisのドキュメントを参照してください)。
必要に応じて、各マシンに複数のクライアントユニットファイルを設定して、ローカルポートをリモートサーバーにマップできます。 このような場合は、送信ユニットファイルの送信元ソケット仕様で、必ず別の未使用のローカルポートを選択してください。
結論
Redisは、多くのデプロイメントにとって非常に貴重な強力で柔軟なツールです。 ただし、安全でない環境でRedisを操作することは、サーバーとデータを攻撃や盗難に対して脆弱なままにする大きな責任です。 信頼できる関係者だけがネットワークを構築していない場合は、他の手段でトラフィックを保護することが不可欠です。 このガイドで概説されている方法は、Redisパーティ間の通信を保護するための1つの方法にすぎません。 その他のオプションには、stunnelによるトンネリングまたはVPNのセットアップが含まれます。