SSHトンネルを使用した3層Railsアプリケーションでの通信の保護
序章
Webアプリケーションは、多くの場合、次の3つの異なる層で設計されています。
- 最初の層はプレゼンテーション層で、これはユーザーに表示されるものです。
- 次は、アプリケーションのビジネスロジックを提供するアプリケーション層です。
- 最後に、データレイヤーは、アプリケーションに必要なデータを格納します。
Ruby on Rails アプリケーションでは、これはプレゼンテーション層用のWebサーバー、アプリケーション層用のRailsサーバー、およびデータ層用のデータベースに大まかにマップされます。 この設定では、アプリケーション層はデータ層と通信してアプリケーションのデータを取得し、プレゼンテーション層を介してユーザーに表示されます。
これらすべてのアプリケーションを単一のサーバーにインストールすることは可能ですが、各レイヤーを独自のサーバーに配置すると、アプリケーションのスケーリングが容易になります。 たとえば、Railsサーバーがボトルネックになった場合、他の2つのレイヤーに影響を与えることなくアプリケーションサーバーを追加できます。
このチュートリアルでは、3つの別々のサーバーに独自のソフトウェアセットをインストールし、各サーバーとそのコンポーネントが通信して機能するように構成し、SSHトンネルを使用してサーバー間の接続を保護することにより、Railsアプリを3層構成でデプロイします。 ソフトウェアスタックでは、プレゼンテーション層のWebサーバーとして Nginx 、アプリケーション層のRailsアプリケーションサーバーとして Puma 、アプリケーション層のPostgreSQLを使用します。データ層のデータベース。
前提条件
このチュートリアルを完了するには、3台のUbuntu16.04サーバーを起動する必要があります。 これらにweb-server、 app-server 、および database-server という名前を付け、それぞれでプライベートネットワークを有効にする必要があります。
3つのサーバーにはそれぞれ、sudo
権限を持つroot以外のユーザーと、SSH接続を許可するように構成されたファイアウォール(初期サーバーセットアップガイドを使用して構成できます)が必要です。 このチュートリアルのコンテキストでは、各サーバーのsudo
ユーザーの名前はsammyです。
さらに、3つのサーバーには、それぞれ独自の構成要件があります。
-
Webサーバーの場合:
- NginxWebサーバーをインストールして構成します。 これを行うには、 Ubuntu16.04にNginxをインストールする方法に関するチュートリアルに従ってください。
-
app-server の場合:
- Ubuntu 16.04 にNode.jsをインストールする方法で説明されているように、公式PPAを使用してNode.jsをインストールします。 アセットパイプラインなどのいくつかのRails機能はJavaScriptランタイムに依存しており、Node.jsがこの機能を提供します。
- RubyonRailsフレームワークをインストールします。 これを行うには、 Ubuntu16.04でrbenvを使用してRubyonRailsをインストールする方法に関するガイドに従ってください。 このチュートリアルに従うときは、Rubyの最新バージョン(この記事の執筆時点ではRuby 2.5.1)を必ずインストールしてください。
- チュートリアルUbuntu14.04のRubyonRailsアプリケーションでPostgreSQLを使用する方法の最初のセクションに示されているようにPostgreSQLをインストールします。 このセクションでは、この3層セットアップに必要な別のパッケージである
libpq-dev
のインストール方法についても説明します。 - Pumaを使用してRailsアプリをデプロイします。 デプロイする独自のアプリがない場合は、PumaとNginxを使用してRailsアプリをデプロイする方法のガイドに従ってサンプルアプリをデプロイしてください。 この前提条件の「rbenv-varsプラグインのインストール」セクションで、database-serverにPostgreSQLをインストールするときに使用する値を反映するようにデータベースユーザーとパスワードを設定する必要があることに注意してください。 また、「本番データベースの作成」セクションが機能するには、ポート
3000
がファイアウォールを通過できるようにする必要があります。 最後に、この前提条件チュートリアルの最後の2つのステップである「PumaUpstartスクリプトの作成」と「Nginxのインストールと構成」を完了する必要はありません。
-
データベースサーバーの場合:
- PostgreSQLデータベースソフトウェアをインストールして構成します。 これを行う方法については、 Ubuntu16.04にPostgreSQLをインストールして使用する方法に関するガイドに従ってください。 この前提条件のチュートリアルに従うときに、
superuser
権限を持つRailsアプリのPostgreSQLロールと、PostgreSQLロールと同じ名前のデータベースを作成します。 このチュートリアル全体を通して、PostgreSQLの役割とデータベースは両方ともsammyと呼ばれます。 - 新しく作成されたPostgreSQLロールのパスワードを設定します。 Pumaチュートリアルの「CreateProductionDatabase User 」セクションの最初のコマンド( app-server のセットアップにも使用)をスキップし、残りのコマンドに従います。データベースユーザーのパスワードを変更するセクション。 database-server に設定するPostgreSQLロールの名前とパスワードは、app-serverのPostgreSQLインストールで設定したものと同じである必要があることに注意してください。
- PostgreSQLデータベースソフトウェアをインストールして構成します。 これを行う方法については、 Ubuntu16.04にPostgreSQLをインストールして使用する方法に関するガイドに従ってください。 この前提条件のチュートリアルに従うときに、
ステップ1—SSHトンネルのユーザーを作成する
SSHトンネルは暗号化された接続であり、あるサーバーのポートから別のサーバーのポートにデータを送信できるため、2番目のサーバーのリスニングプログラムが最初のサーバーで実行されているように見えます。 SSHトンネル専用のユーザーがいると、セットアップのセキュリティが向上します。侵入者がいずれかのサーバーの sammy ユーザーにアクセスした場合、侵入者は他のサーバーにアクセスできなくなります。 3層のセットアップ。 同様に、侵入者が tunnel ユーザーにアクセスした場合、Railsアプリディレクトリ内のファイルを編集したり、sudo
コマンドを使用したりすることはできません。
各サーバーで、tunnelという名前の追加ユーザーを作成します。 tunnel ユーザーの唯一の機能は、サーバー間の通信を容易にするSSHトンネルを作成することです。したがって、 sammy とは異なり、 tunnel sudo
を指定しないでください。特権。 また、 tunnel ユーザーは、Railsアプリディレクトリへの書き込みアクセス権を持ってはなりません。 各サーバーで次のコマンドを実行して、tunnelユーザーを追加します。
- sudo adduser tunnel
web-server マシンで、tunnelユーザーに切り替えます。
- sudo su tunnel
tunnel ユーザーとして、SSHキーペアを生成します。
- ssh-keygen
キーをデフォルトの場所に保存し、キーのパスフレーズを作成しないでください。パスフレーズを作成すると、後でサーバー間にSSHトンネルを作成するときに認証が複雑になる可能性があります。
キーペアを作成したら、sammyユーザーに戻ります。
- exit
次に、 app-server に切り替えて、同じコマンドを再度実行します。
- sudo su tunnel
- ssh-keygen
- exit
これで、チュートリアルの残りの部分で必要になるすべてのユーザーが構成されました。 ネットでは、SSHトンネルの作成プロセスを合理化するために、tunnelユーザーごとに/etc/hosts
ファイルにいくつかの変更を加えます。
ステップ2—Hostsファイルの構成
このチュートリアル全体を通して、コマンドでapp-serverまたはdatabase-serverのいずれかのIPアドレスを参照する必要がある場合がよくあります。 これらのIPアドレスを毎回覚えて入力する必要はなく、app-serverおよびdatabase-serverのプライベートIPを各サーバーの/etc/hosts
に追加できます。ファイル。 これにより、後続のコマンドでアドレスの代わりに名前を使用できるようになり、SSHトンネルの設定プロセスがはるかにスムーズになります。
簡単にするために、このチュートリアルでは、app-serverとdatabase-serverのプライベートIPアドレスの両方を/etc/hosts
に追加するように指示していることに注意してください。 ]3つのサーバーのそれぞれにファイルします。 技術的には、 app-serverまたはdatabase-serverのプライベートIPアドレスを独自のhosts
ファイルに追加する必要はありませんが、追加する必要はありません。 t問題を引き起こします。 ここで説明する方法は、速度と利便性のために選択されたものです。
まず、app-serverとdatabase-serverのプライベートIPアドレスを見つけます。 DigitalOceanドロップレットを使用している場合は、コントロールパネルに移動して、これらのドロップレットの名前をクリックします。 ドロップレット固有のページでは、パブリックIPアドレスとプライベートIPアドレスの両方がページの上部に表示されます。
次に、各サーバーで、お気に入りのテキストエディタで/etc/hosts
ファイルを開き、次の行を追加します。
- sudo nano /etc/hosts
. . .
app-server_private_ip app-server
database-server_private_ip database-server
各サーバーのこのファイルにこれらの行を追加することにより、通常これらのサーバーのIPアドレスを使用する必要があるコマンドでapp-serverおよびdatabase-serverという名前を使用できます。 この機能を使用してSSHキーを設定し、各tunnelユーザーが他のサーバーに接続できるようにします。
ステップ3—SSHログインの設定
これで、 tunnel ユーザーと、3つのサーバーすべてに更新された/etc/hosts
ファイルができたので、サーバー間のSSH接続の作成を開始する準備が整いました。
この手順を実行するときは、ピラミッドのような3つの層について考えてください。下部にデータベースサーバー、中央にアプリサーバー、があります。上部にあるweb-server。 Railsアプリに必要なデータにアクセスするには、app-serverがdatabase-serverに接続できる必要があり、web-serverが必要です。 app-server に接続できるので、ユーザーに何かを提示できます。
したがって、各 tunnel ユーザーのSSH公開キーをその「下」のサーバーに追加するだけで済みます。つまり、 web-server tunnelユーザーを追加する必要があります。 app-server に公開鍵を設定し、 app-server tunnelユーザーの公開鍵をdatabase-serverに追加します。 これにより、階層間に暗号化されたSSHトンネルを確立し、ネットワーク上の盗聴者が階層間を通過するトラフィックを読み取らないようにすることができます。
このプロセスを開始するには、/home/tunnel/.ssh/id_rsa.pub
にあるweb-serverのtunnelユーザーの公開鍵を上の/home/tunnel/.ssh/authorized_keys
ファイルにコピーします。 app-server。
web-server で、次のコマンドを使用して、ターミナルにtunnelユーザーの公開鍵を表示します。
- sudo cat /home/tunnel/.ssh/id_rsa.pub
テキスト出力を選択し、システムのクリップボードにコピーします。
別のターミナルセッションでapp-serverにSSHで接続し、トンネルユーザーに切り替えます。
- sudo su tunnel
システムのクリップボードのキーをapp-serverのauthorized_keys
ファイルに追加します。 次のコマンドを使用して、1つのステップでこれを行うことができます。 tunnel_ssh_publickey_copied_from_web_server
をシステムのクリップボードの公開鍵に置き換えることを忘れないでください。
- echo "tunnel_ssh_publickey_copied_from_web-server" >> /home/tunnel/.ssh/authorized_keys
その後、authorized_keys
ファイルのアクセス許可を変更して、ファイルへの不正アクセスを防止します。
- chmod 600 /home/tunnel/.ssh/authorized_keys
次に、sammyユーザーに戻ります。
- exit
次に、 app-server (/home/tunnel/.ssh/id_rsa.pub
にあります)に tunnel ユーザーの公開鍵を表示し、/home/tunnel/.ssh/authorized_keys
ファイルに貼り付けます。 データベースサーバー:
- sudo cat /home/tunnel/.ssh/id_rsa.pub
- sudo su tunnel
database-server でSSHキーペアを生成しなかったため、/home/tunnel/.ssh
フォルダーを作成し、そのアクセス許可を調整する必要があります。
- mkdir /home/tunnel/.ssh
- chmod 700 /home/tunnel/.ssh
次に、 app-serverの公開鍵をauthorized_keys
ファイルに追加し、そのアクセス許可を調整します。
- echo "tunnel_ssh_publickey_copied_from_app-server" >> /home/tunnel/.ssh/authorized_keys
- chmod 600 /home/tunnel/.ssh/authorized_keys
次に、sammyユーザーに戻ります。
- exit
次に、SSHを使用して最初の接続をテストし、web-serverからtunnelユーザーとしてapp-serverに接続します。
- sudo su tunnel
- ssh tunnel@app-server
web-serverからapp-serverに初めて接続すると、接続しているマシンが信頼できることを確認するように求めるメッセージが表示されます。 「yes」と入力して、app-serverの信頼性を受け入れます。
OutputThe authenticity of host '111.111.11.111 (111.111.11.111)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
app-server からウェルカムバナーが表示され、コマンドプロンプトにapp-serverにログインしていることが示されます。 これにより、web-serverからapp-serverへのSSH接続が正しく機能していることが確認されます。
app-server へのSSH接続を終了し、 tunnel ユーザーを終了して、web-serverの
- exit
- exit
次に、次の同じ手順に従って、app-serverからdatabase-serverへのSSH接続をテストします。
- sudo su tunnel
- ssh tunnel@database-server
database-serverの信頼性も受け入れます。 database-server からウェルカムバナーとコマンドプロンプトが表示されると、app-serverからdatabase-serverへのSSH接続がわかります。期待どおりに動作しています。
database-server へのSSH接続を終了してから、tunnelユーザーを終了します。
- exit
- exit
手順で設定したSSH接続は、3つのサーバー層間の安全な通信を可能にするSSHトンネルの基礎を形成します。 ただし、現在の形式では、これらの接続はクラッシュに対して脆弱であるため、信頼性は低くなります。 ただし、いくつかの追加ソフトウェアをインストールし、サービスとして機能するようにトンネルを構成することで、これらの脆弱性を軽減できます。
ステップ4—データベースサーバーへの永続的なSSHトンネルを設定する
最後の手順では、ローカルサーバーからリモートサーバーのコマンドプロンプトにアクセスしました。 SSHトンネルを使用すると、ローカルホストのポートからリモートホストのポートにトラフィックをトンネリングすることで、これ以上のことができます。 ここでは、SSHトンネルを使用して、app-serverとdatabase-serverの間の接続を暗号化します。
このチュートリアルのすべての前提条件を順守すると、app-serverとdatabase-serverの両方にPostgreSQLがインストールされます。 ポート番号の衝突を防ぐには、これらのサーバー間のSSHトンネルを構成して、app-serverのポート5433
から[のポート5432
に接続を転送する必要があります。 X187X]データベースサーバー