Ubuntu 16.04でStunnelを使用してRedisへのトラフィックを暗号化する方法

前書き

Redisはオープンソースのキーと値のデータストアであり、永続化のためにオプションのディスク書き込みを伴うメモリ内ストレージモデルを使用します。 トランザクション、pub / subメッセージングパターン、および他の機能の中での自動フェールオーバーを備えています。 Redisには、ほとんどの言語で記述されたクライアントがあり、推奨されるクライアントはtheir websiteで紹介されています。

Redisは、独自の暗号化機能を提供しません。 信頼できる関係者のみがアクセスできる隔離されたプライベートネットワークに展開されているという前提の下で動作します。 ご使用の環境がその仮定と一致しない場合、Redisトラフィックを暗号化で個別にラップする必要があります。

このガイドでは、stunnelと呼ばれる安全なトンネリングプログラムを使用してRedisトラフィックを暗号化する方法を示します。 Redisクライアントとサーバー間のトラフィックは、専用のSSL暗号化トンネルを介してルーティングされます。 2台のUbuntu 16.04サーバーを使用してデモを行います。

前提条件

開始するには、各マシンでsudo特権が構成されたroot以外のユーザーが必要です。 さらに、このガイドでは、基本的なファイアウォールが設定されていることを前提としています。 これらの要件を満たすために、Ubuntu 16.04 initial server setup guideをたどることができます。

続行する準備ができたら、以下に従ってください。

スタンネルとは何ですか?

基本的な暗号化通信の場合、stunnelユーティリティのインストールと構成は簡単です。 2台のマシン間で暗号化された転送を可能にします。 クライアントはローカルポートに接続し、stunnelはそれを暗号化でラップしてからリモートサーバーに転送します。 サーバー側では、stunnelは構成されたポートをリッスンし、トラフィックを復号化してからローカルポート(この場合、Redisサーバーがリッスンするポート)に転送します。

stunnelを使用する利点は次のとおりです。

  • Ubuntuは、デフォルトのリポジトリにstunnelのパッケージを保持しています

  • Ubuntuには、ブート時にプロセスを自動的に開始するinitスクリプトが含まれています

  • 設定は簡単で直感的です

  • 目的ごとに新しいトンネルが使用されます。 これは状況によっては不利かもしれませんが、アクセスをきめ細かく制御できます。

欠点は次のとおりです。

  • クライアントは、デフォルトではないローカルポートに接続することでリモートマシンに接続しますが、これは最初は直感的ではない場合があります。

  • レプリケーションまたはクラスタリングのために2つのRedisサーバーを接続する場合、サーバー間通信用に各マシンで2つのトンネルを構成する必要があります(1つは送信トラフィック用、もう1つは受信トラフィック用)。

これらの特性を念頭に置いて、始めましょう。

Redisサーバーおよびクライアントパッケージをインストールする

始める前に、1台のマシンにRedisサーバーをインストールし、もう1台のマシンにクライアントパッケージを用意する必要があります。 これらのいずれかまたは両方がすでに設定されている場合は、お気軽にスキップしてください。

[.note]#Note: Redisサーバーの命令は、後で接続をテストするために使用されるテストキーを設定します。 すでにRedisサーバーがインストールされている場合は、接続をテストするときに、このキーを設定するか、他の既知のキーを使用できます。

Redisサーバーのインストール

Chris Lea’s Redis server 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に設定しました。 stunnelを構成した後、クライアントマシンからこのキーにアクセスしようとします。

Redisクライアントのインストール

他のUbuntu 16.04マシンはクライアントとして機能します。 必要なすべてのソフトウェアは、デフォルトのリポジトリのredis-toolsパッケージで入手できます。

sudo apt-get update
sudo apt-get install redis-tools

リモートRedisサーバーのデフォルト構成とファイアウォールがアクティブになっているため、現在、テストするためにリモートRedisインスタンスに接続することはできません。

各コンピューターにstunnelをインストールして有効にする

次に、各サーバーとクライアントにstunnelをインストールする必要があります。 Ubuntuには、デフォルトのリポジトリにstunnel4と呼ばれるバージョン4のユーティリティが含まれています。 前のセクションで何もインストールする必要がなかった場合は、インストールする前に、必ずsudo apt-get updateコマンドを含めてパッケージインデックスを更新してください。

# sudo apt-get update
sudo apt-get install stunnel4

Ubuntuのstunnelサービスは、起動に古いSysVinitスクリプトを使用します。これは、systemdで管理できます。 ネイティブのsystemdメソッドを使用するのではなく、起動時に開始するようにサービスを構成するには、/etc/default/stunnel4ファイルを変更する必要があります。

sudo nano /etc/default/stunnel4

ENABLEDオプションを「1」に設定して、サービスが起動時に開始できるようにします。

/etc/default/stunnel4

. . .
ENABLED=1
. . .

各サーバーでファイルを保存して閉じます。

次に、通信の暗号化に使用される自己署名SSL証明書とキーを作成します。

Redisサーバーで自己署名SSL証明書とキーを作成する

Redisサーバーで、自己署名SSL証明書とキーを/etc/stunnelディレクトリに作成します。 これは、stunnelの2つのインスタンス間の接続を暗号化するために使用されます。 redis-serverという名前を使用して、証明書とキーファイルを参照します。

sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/stunnel/redis-server.key -out /etc/stunnel/redis-server.crt

作成する証明書に関する情報の入力を求められます。 これは内部でのみ使用されるため、値はそれほど重要ではないので、好きなものを入力してください。 あなたは以下の例を見ることができます:

Redis server output. . .
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean
Organizational Unit Name (eg, section) []:Community
Common Name (e.g. server FQDN or YOUR name) []:redis-server
Email Address []:[email protected]

次のように入力して、生成された.keyファイルへのアクセスを制限します。

sudo chmod 600 /etc/stunnel/redis-server.key

SSL証明書とキーができたので、Redisサーバーのstunnel構成ファイルを作成できます。

Redisサーバーのstunnel設定ファイルを作成する

開始するには、Redisサーバーの/etc/stunnelディレクトリ内の.confで終わるファイルを開きます。

sudo nano /etc/stunnel/redis.conf

内部では、メインセクションでPIDファイルを書き込む場所を指定します。 /runディレクトリは、これらのタイプのファイルを格納するように設計されているため、次のものを使用します。

/etc/stunnel/redis.conf

pid = /run/stunnel-redis.pid

次に、Redisサービスへのアクセスを構成するセクションを作成します。 これは好きなように呼び出すことができます(redis-serverと呼びます)。 このセクションでは、この構成を、後でこのマシンで構成する必要がある他のトンネルから分離します。

certディレクティブとkeyディレクティブをそれぞれ使用して、Redisサーバー自体の証明書とキーの場所を指定する必要があります。

ここでは、着信データのトンネルも定義します。 暗号化されたトラフィックを、Redisサーバーの外部IPアドレスのデフォルトのRedisポート(ポート6379)にacceptします。 次に、そのトラフィックをlocalインターフェイスのデフォルトのRedisポートにconnectして、復号化されたトラフィックをデポジットします。 これは、Redisサービスが実際にリッスンしている場所です。

/etc/stunnel/redis.conf

pid = /run/stunnel-redis.pid

[redis-server]
cert = /etc/stunnel/redis-server.crt
key = /etc/stunnel/redis-server.key
accept = redis_servers_public_IP:6379
connect = 127.0.0.1:6379

終了したら、ファイルを保存して閉じます。

stunnelを再起動してファイアウォールを構成する

Redisサーバーでstunnelが構成されたので、次のように入力してサービスを再起動できます。

sudo systemctl restart stunnel4.service

Redisサーバーで接続をリッスンしているサービスを確認すると、パブリックインターフェイスのポート6379でリッスンしているstunnelが表示されます。 また、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/stunnel4
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

stunnelはパブリックインターフェイスでリッスンしていますが、ファイアウォールはトラフィックを通過させるように構成されていない可能性があります。

ポート6379へのすべてのトラフィックを許可するには、次を入力します。

sudo ufw allow 6379

これにより、stunnelがリッスンしているパブリックインターフェイスのポート6379へのアクセスが開かれます。 stunnelポートは、暗号化されたトラフィックのみを受け入れます。

証明書をクライアントに配布する

各Redisクライアントには、Redisサーバーの証明書ファイルのコピーが必要です。 .crtファイルを配布する最も簡単な方法は、ファイルの内容をサーバーに出力してから、接続しているマシンの対応するファイルに内容をコピーすることです。

次のように入力して、Redisサーバー上の.crtファイルの内容を出力します。

cat /etc/stunnel/redis-server.crt
Redis server output-----BEGIN CERTIFICATE-----
MIIEGTCCAwGgAwIBAgIJALUdz8P8q8UPMA0GCSqGSIb3DQEBCwUAMIGiMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxFjAUBgNVBAcMDU5ldyBZb3JrIENp

. . .

Tq7WJk77tk4nPI8iGv1WuK8xTAm5aOncxP16VoMpsDMV+GB1p3nBkMQ/GKF8pPXU
fn6BnDWKmeZqAlBM+MGYAfkbZWdBslrWasCJzs+tehTqL0LLJ6d3Gi9biBPb
-----END CERTIFICATE-----

表示された証明書including the lines marked BEGIN CERTIFICATE and END CERTIFICATEをクリップボードにコピーします。

クライアントマシンで、/etc/stunnelディレクトリにある同じ名前のファイルを開きます。

sudo nano /etc/stunnel/redis-server.crt

Redisサーバーからコピーしたコンテンツを貼り付けます。 完了したら、ファイルを保存して閉じます。

Redis Client stunnel設定ファイルを作成します

クライアントがサーバーの証明書のコピーを持っているので、stunnel構成のクライアント側を構成できます。

クライアントマシンの/etc/stunnelディレクトリにある.confで終わるファイルを開きます。 ファイルを再度redis.confと呼びます。

sudo nano /etc/stunnel/redis.conf

内部では、サービスがプロセスIDを再度保存するPIDファイルを指定します。

/etc/stunnel/redis.conf

pid = /run/stunnel-redis.pid

次に、送信データ用のトンネルを構成するセクションを追加します。 これには任意の名前を付けることができます(これをredis-clientと呼びます)。 このセクションでは、この構成を、後でこのマシンで構成する必要がある他のトンネルから分離します。

clientディレクティブを使用して、このセクションをクライアント構成として明示的にマークする必要があります。 acceptディレクティブを設定して、ローカルインターフェイスの未使用のポートをリッスンし、ローカルRedisクライアントからの接続を処理します(この例ではポート8000​​を使用します)。 connectディレクティブをRedisサーバーのパブリックIPアドレスと開いたポートに設定します。

次に、CAfileを使用して、Redisサーバーの証明書のコピーをポイントします。 また、verifyを4に設定する必要があります。これにより、stunnelは、証明書チェーンに関係なく証明書のみをチェックします(証明書に自己署名したため)。

/etc/stunnel/redis.conf

pid = /run/stunnel-redis.pid

[redis-client]
client = yes
accept = 127.0.0.1:8000
connect = remote_server_IP_address:6379
CAfile = /etc/stunnel/redis-server.crt
verify = 4

完了したら、ファイルを保存して閉じます。

Client Serviceの再起動と接続のテスト

クライアントでstunnelサービスを再起動して、変更を実装します。

sudo systemctl restart stunnel4.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      3809/stunnel4
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1714/sshd
tcp6       0      0 :::22                   :::*                    LISTEN      1714/sshd

ご覧のとおり、stunnelはローカルポート8000​​で接続をリッスンしています。

これで、クライアントがローカルインターフェースのポート8000​​を指すようにすることで、リモートRedisインスタンスに接続できるようになります。

redis-cli -p 8000 ping
Redis client outputPONG

このガイドの冒頭で設定したテストキーを照会します。

redis-cli -p 8000 get test
Redis client output"success"

これにより、リモートデータベースに正常にアクセスできることが確認されます。

トンネルを使用せずにリモートRedisサーバーと通信するunableであることを確認するために、リモートポートへの直接接続を試みることができます。

redis-cli -h redis_server_public_IP -p 6379 ping
Redis client outputError: Connection reset by peer

ご覧のとおり、トラフィックは、トンネルを介して正しく暗号化されている場合にのみ、リモートRedisポートで受け入れられます。

マルチクライアントおよびサーバー間通信の上記の例を拡張する

上記で概説した例では、単一のRedisサーバーと単一のクライアントの簡単な例を使用しました。 ただし、これらの同じ方法は、より複雑な相互作用に適用できます。

この例を拡張して複数のクライアントを処理するのは簡単です。 上記の以下のアクションを実行する必要があります。

  • 新しいクライアントにRedisクライアントソフトウェアとstunnelパッケージをインストールします

  • stunnelソフトウェアが起動時に開始できるようにする

  • サーバーの証明書ファイルを/etc/stunnelディレクトリにコピーします

  • stunnelクライアント構成ファイルを新しいクライアントマシンにコピーします

  • stunnelサービスを再起動します

安全なサーバー間通信をセットアップするには(たとえば、レプリケーションまたはクラスタリング用)、2つの並列トンネルをセットアップする必要があります。

  • 新しいサーバーに、Redisサーバーパッケージとstunnelをインストールします

  • stunnelソフトウェアが起動時に開始できるようにする

  • 新しいRedisサーバー用の新しい証明書とキーファイルを生成します(ファイルには一意の名前を使用します)

  • 各証明書ファイルを1つのサーバーから別のサーバーに/etc/stunnelディレクトリにコピーします

  • 各サーバー(既存のサーバーを含む)でstunnel構成ファイルを編集または作成して、次のものが含まれるようにします。

    • 外部ポートをローカルRedisにマッピングするサーバーセクション

    • ローカルポートをリモートサーバーの公開ポートにマッピングするクライアントセクション

  • 新しいRedisサーバーのファイアウォールで外部ポートを開きます

  • Redis構成ファイルを調整して、各Redisインスタンスがローカルにマッピングされたポートに接続してリモートサーバーにアクセスするように構成します(必要なディレクティブはサーバーの関係によって異なります。 詳細については、Redisのドキュメントを参照してください。

両方のサーバーのstunnel構成ファイルは次のようになります。

サーバー間通信用のstunnel構成ファイル

pid = /run/stunnel-redis.pid

[redis-server]
cert = /etc/stunnel/this_servers_certificate.crt
key = /etc/stunnel/this_servers_key.key
accept = this_servers_public_IP:6379
connect = 127.0.0.1:6379

[redis-client]
client = yes
accept = 127.0.0.1:arbitrary_local_port
connect = remote_servers_public_IP:6379
CAfile = /etc/stunnel/remote_servers_certificate.crt
verify = 4

必要に応じて、各マシンで複数のクライアントセクションを構成して、ローカルポートをリモートサーバーにマップできます。 このような場合は、リモートサーバーごとにacceptディレクティブを使用して異なる未使用のローカルポートを選択してください。

結論

Redisは強力で柔軟なツールであり、多くの展開にとって非常に貴重です。 ただし、Redisを安全でない環境で運用することは、サーバーやデータを攻撃や盗難に対して脆弱なままにする大きな問題です。 信頼できる関係者のみが存在する分離されたネットワークがない場合は、他の手段でトラフィックを保護することが不可欠です。 このガイドで概説されている方法は、Redisパーティ間の通信を保護するための1つの方法にすぎません。 他のオプションには、tunneling with spipedまたはsetting up a VPNが含まれます。

Related