開発者ドキュメント

Ubuntu16.04でOpenVPNとDockerを使用して安全なMongoDBサーバーを実行する方法

MongoDB は、オープンソースのNoSQLデータベースです。 従来のMongoDBセットアップには、データセキュリティが心配な場合に必要なセキュリティ機能がいくつかありません。

データベースを実行するサーバーを保護するには、いくつかの方法があります。 まず、VPNを設定し、VPNに接続されているクライアントのみにアクセスを制限できます。 次に、クライアントとサーバー間のトランスポート層を証明書で暗号化できます。 このチュートリアルでは両方を行います。 さらに、 Docker を使用してMongoDBインスタンスを実行するため、複数のサーバー間でMongoDB構成と証明書の再利用性を確保できます。

前提条件

このチュートリアルを完了するには、次のものが必要です。

ステップ1—プライベートIPアドレスに転送するようにVPNを構成する

前提条件のOpenVPNの記事に従っている場合は、リクエストをパブリックネットワークインターフェイスに転送するようにサーバーを構成している可能性がありますが、プライベートネットワークインターフェイスには転送していません。 このチュートリアルでは、MongoDBサーバーを構成して、VPN接続を介してのみアクセスできるプライベートインターフェイスでのみアクセスできるようにします。 VPNクライアントからのトラフィックもプライベートネットワークにルーティングされるように、VPNサーバーのIP転送ルールを変更する必要があります。

OpenVPNサーバーに接続します。

ssh sammy@vpn_server_public_ip

次に、DigitalOceanダッシュボードに移動し、VPNドロップレットを選択して、そのプライベートIPアドレスを見つけます。

プライベートIPアドレスを取得したら、VPNドロップレットで次のコマンドを実行して、そのIPアドレスを使用するネットワークインターフェイスを特定します。

  1. sudo nano /etc/ufw/before.rules
  2. ip route | grep vpn_server_private_ip

次のような出力が表示されます。

Output
10.132.0.0/16 dev eth1 proto kernel scope link src vpn_server_private_ip

出力のネットワークインターフェイスに注意してください。 この例では、インターフェースはeth1ですが、実際のインターフェースは異なる場合があります。

プライベートネットワークインターフェイスを特定したら、ファイル/etc/ufw/before.rulesを編集します。

  1. sudo nano /etc/ufw/before.rules

前提条件のチュートリアルで定義したセクションを見つけます。これは次のようになります。

/etc/ufw/before.rules
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
COMMIT
# END OPENVPN RULES

プライベートネットワークインターフェイスの新しいルールを追加します。

/etc/ufw/before.rules
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0] 
# Allow traffic from OpenVPN client to eth0
-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
-A POSTROUTING -s 10.8.0.0/8 -o eth1 -j MASQUERADE
COMMIT
# END OPENVPN RULES

必ずeth1をプライベートネットワークのインターフェースに置き換えてください。 次に、ファイルを保存してエディターを終了します。

ファイアウォールを無効にしてから再度有効にします。

  1. sudo ufw disable
  2. sudo ufw enable

次に、VPNサーバーからログアウトします。

  1. exit

次に、ローカルコンピューターからVPNサーバーへのVPN接続を確立します。 このチュートリアル全体を通して、この接続を維持してください。

次に、プライベートIPアドレスを使用してMongoDBサーバーに接続し、ファイアウォールを構成しましょう。

ステップ2–MongoDBサーバーのファイアウォールを設定する

プライベートIPアドレスを使用してMongoDBサーバーに接続します。 お持ちでない場合は、DigitalOceanダッシュボードに戻り、MongoDBDockerDropletのプライベートIPアドレスを見つけてください。 ここではこれを使用してサーバーに接続し、その後、データベースサーバーへのアクセスをVPNクライアントに制限しようとしているため、これを使用してMongoDBに直接接続します。 このようにして、データベースを公開することを回避できます。これは、必須のセキュリティ対策です。

VPNに接続していることを確認し、プライベートIPを使用してMongoDBサーバーにSSHで接続します。

ssh sammy@mongodb_server_private_ip

ログインしたら、既存のファイアウォールルールをすべて削除して、外部からのアクセスを防止します。

  1. sudo ufw delete limit ssh
  2. sudo ufw delete allow 2375/tcp
  3. sudo ufw delete allow 2376/tcp

次に、VPNに接続されているコンピューターからのみSSHとMongoDBへのアクセスを許可する2つの新しいルールを追加します。 これを行うには、オリジンIPにVPNサーバーのプライベートIPアドレスを使用します。

  1. sudo ufw allow from vpn_server_private_ip to any port 22 proto tcp
  2. sudo ufw allow from vpn_server_private_ip to any port 28018 proto tcp

構成されているルールが2つだけであることを確認してください。

  1. sudo ufw status

次の出力が表示されます。

Output
To Action From -- ------ ---- 22/tcp ALLOW vpn_server_private_ip 28018/tcp ALLOW vpn_server_private_ip

ファイアウォールを有効にして、サーバーからログアウトします。

  1. sudo ufw enable
  2. exit

次に、MongoDBサーバーに再度ログインして、IPフィルターを有効にした後もサーバーにアクセスできることを確認します。

ssh sammy@mongodb_server_private_ip

SSH接続を確立できない場合は、VPNに接続していることと、プライベートネットワークでトラフィックを転送するようにVPNサーバーを設定していることを確認してください。 それでも問題が解決しない場合は、 DigitalOcean Console を使用してログインし、ファイアウォールルールを確認してください。 MongoDBサーバーのプライベートIPではなく、VPNサーバーのプライベートIPをルールで指定していることを確認してください。

UFWの詳細については、このDigitalOceanUFWチュートリアルをご覧ください。

基本的なセキュリティ対策を構成したので、MongoDBの構成に進みます。

ステップ3—MongoDB構成ファイルを作成する

このステップでは、SSL証明書を使用するようにMongoDBを構成するカスタムMongoDB構成を作成します。

構成ファイルと関連ファイルを保持するディレクトリ構造を作成しましょう。 mongoconfというディレクトリを作成し、その中に構成ファイル用のconfigディレクトリを作成します。 configディレクトリ内に、sslというディレクトリを作成し、そこに証明書を保存します。

次のコマンドを使用して構造を作成します。

  1. mkdir -p ~/mongoconf/config/ssl

次に、~/mongoconf/configフォルダーに切り替えます。

  1. cd ~/mongoconf/config

テキストエディタでmongod.confという新しいファイルを開きます。

  1. nano mongod.conf

まず、ポート28018のすべてのネットワークインターフェイスにバインドするようにデータベースを設定します。 この場合、ファイアウォールは外部からの接続を許可しないため、0.0.0.0へのバインドはセキュリティの問題ではありません。 ただし、VPN内のクライアントからの接続を許可する必要があります。 ファイルに以下を追加します。

mongodb.conf
net: 
  bindIp: 0.0.0.0 
  port: 28018

また、netセクションで、SSL証明書へのパスを設定し、証明書のパスフレーズを指定します。 実際の証明書ファイルとパスフレーズをまもなく作成します。

mongodb.conf
net: 
. . .
  ssl: 
    CAFile: /etc/mongo/ssl/client.pem
    PEMKeyFile: /etc/mongo/ssl/server.pem
    PEMKeyPassword: test
    mode: requireSSL

最後に、デフォルトのストレージディレクトリを設定し、ジャーナリングを有効にします。

mongodb.conf
. . .
storage: 
  dbPath: /mongo/db
  journal: 
    enabled: true

利用可能なすべての構成オプションについては、MongoDBのドキュメントをお読みください。

今のところ、ファイルを保存してエディターを終了します。 使用するSSL証明書を生成するときが来ました。

ステップ4—SSL証明書の生成

データ転送を保護するには、MongoDB用に2つのSSL証明書を生成する必要があります。1つはサーバー用で、もう1つはデータベースにアクセスするクライアント用です。

注:このチュートリアルでは、自己署名証明書を作成します。 実稼働環境では、信頼できる認証局を使用してそれらを生成します。

これを行うには、プライベートDNSリゾルバーを設定する必要があります。 次に、 Let’s Encrypt DNSチャレンジを使用して、新しく作成されたイントラネットドメインを検証し、それらの証明書を発行します。

まず、~/mongoconf/config/sslディレクトリに移動し、サーバーの証明書とキーのペアを生成します。 プロンプトに選択した情報を入力します。 Common NameおよびPEM Passphraseフィールドに注意してください。

  1. cd ~/mongoconf/config/ssl
  2. openssl req -new -x509 -days 365 -out server.crt -keyout server.key

次の出力が表示され、途中で詳細を入力するように求められます。

Server certificate-key generation
. . . Enter PEM pass phrase: test Verifying - Enter PEM pass phrase: test . . . Common Name (e.g. server FQDN or YOUR name) []: mongodb_server_private_ip . . .

PEMパスフレーズの入力を求められたら、前の手順でMongoDB構成ファイルで使用したのと同じ値を使用していることを確認してください。

MongoDBは個別のキーファイルと証明書ファイルを受け入れないため、それらを1つの.pemファイルに結合します。

  1. cat server.crt server.key >> server.pem

次に、クライアントの証明書とキーのペアを生成します。

  1. openssl req -new -x509 -days 365 -out client.crt -keyout client.key

以前と同じプロセスに従いますが、今回はVPNサーバーのプライベートIPを使用します。 PEMパスフレーズは、このステップで好きなものにすることができます。

Client certificate-key generation
. . . Enter PEM pass phrase: secret_password Verifying - Enter PEM pass phrase: secret_password . . . Common Name (e.g. server FQDN or YOUR name) []: vpn_server_private_ip . . .

生成したファイルを単一の.pemファイルに連結します。

  1. cat client.crt client.key >> client.pem

次に、両方の証明書ファイルをローカルマシンにコピーして、MongoDBサーバーにリモートで接続できるようにします。 これは、ローカルマシンのscpコマンドで実行できます。

  1. scp sammy@mongodb_server_private_ip:/home/sammy/mongoconf/config/ssl/\{client.pem,server.pem\} .

または、チュートリアル SFTPを使用してリモートサーバーでファイルを安全に転送する方法に従って、client.pemおよびserver.pemファイルをローカルマシンに転送することもできます。

次に、Dockerイメージを作成し、コンテナーでデータベースエンジンを実行して、この構成の移植性を高めましょう。

ステップ5—MongoDBDockerイメージの作成とコンテナーの実行

安全なMongoDB構成を作成し、証明書を生成しました。 それでは、Dockerで移植できるようにしましょう。 MongoDBのカスタムイメージを作成しますが、コンテナーを実行するときに構成ファイルと証明書を渡します。

イメージを構築するには、Dockerfileが必要です。

sudoなしでdockerを実行するには、sammydockerグループに追加します。

  1. sudo usermod -aG docker sammy

次に、サーバーからログアウトして再度ログインし、新しいグループのアクセス許可を有効にします。

プロジェクトのルートディレクトリに切り替えて、エディターで空のDockerfileを開きます。

  1. cd ~/mongoconf
  2. nano Dockerfile

新しいファイルに以下を追加します。

Dockerfile
FROM ubuntu:xenial

RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
RUN echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-3.4.list
RUN apt-get update && apt-get install -y mongodb-org
RUN mkdir -p /mongo/db /etc/mongo

EXPOSE 28018
ENTRYPOINT ["mongod", "--config", "/etc/mongo/mongod.conf"]

このファイルは、Ubuntu 16.04 Xenialに基づくイメージを作成し、最新のMongoDBバイナリをダウンロードし、構成ファイルとデータベースを保存するいくつかのディレクトリを作成するようにDockerに指示します。 コンテナのポート28018をホストで使用できるようにし、ユーザーがコンテナを再起動するたびにMongoを実行します。

注:わかりやすくするために、イメージはUbuntuに基づいています。 ただし、Alpine Linuxのような軽量ディストリビューションで構築されたコンテナは、使用するディスク容量が少なくなります。

ファイルを保存して、エディターを終了します。 次に、イメージを作成します。

  1. docker build -t mongo .

イメージがビルドされたら、イメージに基づいてコンテナーを実行します。 configディレクトリをコンテナー内のボリュームとしてマウントし、カスタム構成とキーがコンテナー内のMongoDBインスタンスに表示されるようにします。

  1. docker run \
  2. --detach \
  3. --publish 28018:28018 \
  4. --volume $PWD/config:/etc/mongo \
  5. --name mongodb \
  6. mongo

これで、実行中のMongoDBインスタンスができたので、ローカルコンピューターからアクセスします。

ステップ6—MongoDBへのアクセス

ローカルマシンの新しい端末で、MongoDBサーバーのプライベートIPアドレスを使用してデータベースに接続します。 ローカルマシンにダウンロードしたclient.pemファイルとserver.pemファイル、およびクライアント証明書の作成時に使用したパスフレーズを提供します。 次のコマンドを実行します。

  1. mongo \
  2. --ssl \
  3. --sslCAFile path_to_server_pem \
  4. --sslPEMKeyFile path_to_client_pem \
  5. --sslPEMKeyPassword pem_key_passphrase \
  6. --host mongodb_server_private_ip \
  7. --port 28018

すべてが正常であれば、MongoDBプロンプトが表示されます。

エラーが表示された場合は、VPNサーバーのIPアドレスではなく、MongoDBサーバーのプライベートIPに接続していることを再確認してください。 また、キーの場所とパスフレーズが正しいこと、およびVPNへの接続がまだ実行されていることを確認してください。

結論

これで、Dockerコンテナーで実行されているカスタム構成のMongoDBができました。 そのセキュリティは、SSLクライアントサーバー認証とトランスポート暗号化によって付与されます。 VPNサーバーに接続されているクライアントへのデータベース接続を制限するようにファイアウォールを構成することにより、セキュリティを強化しました。

この設定はテストに最適ですが、実稼働環境では、信頼できる認証局と署名付き証明書を使用する必要があることに注意してください。 さらに、セキュリティニーズを分析し、それに応じて行動する必要があります。 たとえば、データベースにユーザー、パスワード、および役割を設定したい場合があります。 チュートリアルUbuntu16.04にMongoDBをインストールして保護する方法には、ユーザーの作成に関する詳細情報があり、本番環境に対応したセットアップに向けた優れた次のステップです。

モバイルバージョンを終了