如何在 Ubuntu 16.04 上使用 OpenVPN 和 Docker 运行安全的 MongoDB 服务器

MongoDB是一个开源的NoSQL数据库. 传统的MongoDB设置缺乏一些安全功能,如果你担心数据安全,你会想要的。

有几种方法可以保护运行数据库的服务器。 首先,您可以设置VPN并限制只对连接到VPN的客户端的访问。 然后您可以使用证书加密客户端和服务器之间的传输层。 在本教程中,您将做这两件事。 此外,您将使用Docker(https://www.docker.com/)来运行您的MongoDB实例,以确保您的MongoDB配置和证书在多个服务器上可重复使用。

前提条件

要完成这个教程,你需要:

  • 一个 OpenVPN 服务器,你可以根据教程(How To Set Up an OpenVPN Server on Ubuntu 16.04)(https://andsky.com/tech/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04)来设置,请确保你在创建服务器时检查 私人网络
  • 安装了 Docker 的 Ubuntu 16.04 机器。这就是你将创建你的 MongoDB Docker 图像的地方,你将在容器中运行 MongoDB。 要创建它,请单击 Create Droplet 在 DigitalOcean 管理控制台中,选择 One-click 应用程序,然后选择 Docker 1.x 在 16.04 上。 也可以在这个服务器上启用私人网络 一个在两个服务器上具有 sudo 特权的非根基用户。 [Inaliti

步骤 1 – 将VPN配置为私人IP地址

如果你遵循了OpenVPN文章的先决条件,你很可能会配置你的服务器将请求转发到公共网络接口,但不是私人接口. 在本教程中,我们将配置MongoDB服务器,以便它只能通过其私人接口访问,我们只能通过我们的VPN连接访问。

连接到你的OpenVPN服务器。

1[environment local]
2ssh sammy@vpn_server_public_ip

然后进入DigitalOcean仪表板,选择您的VPN Droplet,并找到其私人IP地址。

一旦你有私人IP地址,在VPN Droplet上执行此命令,以识别使用该IP地址的网络接口:

1[environment second]
2sudo nano /etc/ufw/before.rules
3ip route | grep vpn_server_private_ip

你应该看到类似于以下的输出:

1[secondary_label Output]
2[environment second]
310.132.0.0/16 dev eth1 proto kernel scope link src vpn_server_private_ip

在此示例中,接口为eth1,但您的接口可能不同。

一旦您确定了私人网络接口,请编辑文件 /etc/ufw/before.rules:

1[environment second]
2sudo nano /etc/ufw/before.rules

在先决条件教程中找到您定义的部分,它看起来像这样:

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

添加私人网络接口的新规则:

 1[label /etc/ufw/before.rules]
 2# START OPENVPN RULES
 3# NAT table rules
 4*nat
 5:POSTROUTING ACCEPT [0:0] 
 6# Allow traffic from OpenVPN client to eth0
 7-A POSTROUTING -s 10.8.0.0/8 -o eth0 -j MASQUERADE
 8-A POSTROUTING -s 10.8.0.0/8 -o eth1 -j MASQUERADE
 9COMMIT
10# END OPENVPN RULES

请确保用您的私人网络的界面代替eth1,然后保存文件并退出编辑器。

禁用和重新启用防火墙:

1[environment second]
2sudo ufw disable
3sudo ufw enable

然后退出您的VPN服务器。

1[environment second]
2exit

现在,从您的本地计算机建立一个VPN连接到您的VPN服务器。

现在让我们使用其私人 IP 地址连接到 MongoDB 服务器并配置其防火墙。

步骤 2 – 设置 MongoDB 服务器的防火墙

我们将使用其私有 IP 地址连接到 MongoDB 服务器。如果您没有它,请回到 DigitalOcean 仪表板并找到 MongoDB Docker Droplet 的私有 IP 地址。您将使用它在这里连接到服务器,然后使用它直接连接到 MongoDB,因为我们将限制访问数据库服务器给 VPN 客户端。

确保您已连接到 VPN,并使用其私人 IP 将 SSH 连接到 MongoDB 服务器:

1[environment local]
2ssh sammy@mongodb_server_private_ip

一旦登录,请删除所有现有的防火墙规则,以防止来自外部世界的访问:

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

然后添加两个新的规则,允许SSH和MongoDB仅从连接到您的VPN的计算机访问。

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

确保这些是唯一配置的两个规则:

1sudo ufw status

你应该看到以下结果:

1[secondary_label Output]
2To Action From
3--                         ------      ----
422/tcp ALLOW vpn_server_private_ip
528018/tcp ALLOW vpn_server_private_ip

启用防火墙并退出服务器:

1sudo ufw enable
2exit

然后重新登录到 MongoDB 服务器,以确保在启用 IP 过滤器后仍然可以访问服务器。

1[environment local]
2ssh sammy@mongodb_server_private_ip

如果您无法建立 SSH 连接,请确保您已连接到 VPN,并已设置 VPN 服务器来在私人网络中传输流量。如果这不起作用,请使用 DigitalOcean Console登录并检查防火墙规则。

若要了解更多有关UFW的信息,请参阅 DigitalOcean UFW 教程

现在你已经配置了基本的安全措施,继续配置 MongoDB。

步骤 3 – 创建 MongoDB 配置文件

在此步骤中,我们将创建一个自定义的 MongoDB 配置,将 MongoDB 配置为使用 SSL 证书。

我们将创建一个名为mongoconf的目录,然后为我们的配置文件创建一个config目录。

使用以下命令创建结构:

1mkdir -p ~/mongoconf/config/ssl

然后切换到 ~/mongoconf/config 文件夹:

1cd ~/mongoconf/config

使用您的文本编辑器打开名为 `mongod.conf’的新文件:

1nano mongod.conf

首先,将数据库设置为连接到每个网络接口上的端口 28018。 连接到 0.0.0.0 在这种情况下不是安全问题,因为防火墙不会允许来自外部世界的连接,但我们需要允许VPN内部的客户端连接。

1[label mongodb.conf]
2net: 
3  bindIp: 0.0.0.0 
4  port: 28018

此外,在net部分,设置到SSL证书的路径并指定证书passphrase. 我们将很快创建实际的证书文件和passphrase。

1[label mongodb.conf]
2net: 
3. . .
4  ssl: 
5    CAFile: /etc/mongo/ssl/client.pem
6    PEMKeyFile: /etc/mongo/ssl/server.pem
7    PEMKeyPassword: test
8    mode: requireSSL

最后,设置默认存储目录并启用日志。

1[label mongodb.conf]
2. . .
3storage: 
4  dbPath: /mongo/db
5  journal: 
6    enabled: true

要了解所有可用的配置选项,请阅读MongoDB的文档(https://docs.mongodb.com/manual/reference/configuration-options/)。

现在,保存文件并退出编辑器,是时候生成我们将使用的SSL证书了。

第4步:生成SSL证书

为了确保数据传输,您需要为 MongoDB 生成两个 SSL 证书 - 一个用于服务器,一个用于访问数据库的客户端。

<$>[注] **注:**我们在本教程中创建自签证书.在生产环境中,您将使用可信证书权威来生成它们。

要做到这一点,您需要 设置私人 DNS 解析器。然后, 使用 Let's Encrypt DNS 挑战来验证新创建的内网域名并为其发行证书。

首先,切换到 ~/mongoconf/config/ssl 目录并生成服务器证书密钥对。 请用您所选择的信息填写提示书。 请注意 Common Name 和 `PEM Passphrase' 字段。

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

您将看到以下输出,并将被要求在途中提供一些细节:

1[secondary_label Server certificate-key generation]
2. . .
3Enter PEM pass phrase: test
4Verifying - Enter PEM pass phrase: test
5. . .
6Common Name (e.g. server FQDN or YOUR name) []: mongodb_server_private_ip
7. . .

当您被要求使用 PEM 通行语句时,请确保您在上一步中使用了 MongoDB 配置文件中的相同值。

MongoDB 不接受单独的密钥和证书文件,所以将它们合并为一个单一的.pem 文件:

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

接下来,为客户端生成证书密钥对:

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

您将遵循与之前相同的过程,但这一次,使用VPN服务器的私人IP。

1[secondary_label Client certificate-key generation]
2. . .
3Enter PEM pass phrase: secret_password
4Verifying - Enter PEM pass phrase: secret_password
5. . .
6Common Name (e.g. server FQDN or YOUR name) []: vpn_server_private_ip
7. . .

将您刚刚生成的文件合并为一个单一的 .pem 文件:

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

接下来,将两个证书文件复制到您的本地机器,以便您可以远程连接到 MongoDB 服务器。

1[environment local]
2scp sammy@mongodb_server_private_ip:/home/sammy/mongoconf/config/ssl/\{client.pem,server.pem\} .

或者,您可以按照教程(How To Use SFTP to Secure Transfer Files with a Remote Server)(https://andsky.com/tech/tutorials/how-to-use-sftp-to-securely-transfer-files-with-a-remote-server)将client.pemserver.pem文件传输到本地机器。

现在,让我们创建Docker图像并在容器中运行数据库引擎,以便此配置更便携式。

步骤 5 — 创建 MongoDB Docker 图像并运行容器

您已经创建了一个安全的 MongoDB 配置并生成证书,现在让我们用 Docker 将其进行便携。我们将为 MongoDB 创建一个自定义图像,但当我们运行容器时,我们将通过我们的配置文件和证书。

要创建一个图像,你需要一个Dockerfile。

<$>[注] :要在没有sudo的情况下运行docker,请将 sammy添加到 docker组:

1sudo usermod -aG docker sammy

然后退出服务器并再次登录,以便新的组权限生效 <$>

切换到项目的根目录,并在编辑器中打开一个空的Dockerfile:

1cd ~/mongoconf
2nano Dockerfile

将以下内容添加到新文件中:

 1[label Dockerfile]
 2FROM ubuntu:xenial
 3
 4RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6
 5RUN 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
 6RUN apt-get update && apt-get install -y mongodb-org
 7RUN mkdir -p /mongo/db /etc/mongo
 8
 9EXPOSE 28018
10ENTRYPOINT ["mongod", "--config", "/etc/mongo/mongod.conf"]

这个文件告诉Docker创建基于Ubuntu 16.04 Xenial的图像,下载最新的MongoDB二进制,并创建一些目录,在那里我们将存储配置文件和数据库。

<$>[注] **注:**为了简单,我们的图像是基于Ubuntu的,但是,建在Alpine Linux等轻量级发行版上的容器使用更少的磁盘空间。

保存文件并离开编辑器,然后构建图像:

1docker build -t mongo .

一旦图像被构建,运行一个基于图像的容器. 我们将安装config目录作为容器内部的卷,以便我们的自定义配置和密钥可见于容器内部的MongoDB实例:

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

现在你有一个运行 MongoDB 实例,可以从本地计算机访问它。

步骤 6 – 访问 MongoDB

在本地计算机上的新终端中,使用 MongoDB 服务器的私人 IP 地址连接到数据库,您将提供您下载到本地计算机的 client.pem 和 server.pem 文件,以及您创建客户端证书时使用的密码短语。

1[environment local]
2mongo \
3--ssl \
4--sslCAFile path_to_server_pem \
5--sslPEMKeyFile path_to_client_pem \
6--sslPEMKeyPassword pem_key_passphrase \
7--host mongodb_server_private_ip \
8--port 28018

如果一切顺利,你应该看到MongoDB提示。

如果出现错误,请双重检查您是否正在连接到MongoDB服务器的私人IP,而不是VPN服务器的IP地址。

结论

现在你有一个自定义 MongoDB 运行在 Docker 容器中。它的安全性通过 SSL 客户端服务器身份验证和运输加密提供。你通过配置防火墙来增加额外的安全性,以限制连接到 VPN 服务器的客户端的数据库连接。

虽然这个设置是测试的最佳,但请记住,在生产环境中,你应该使用可信的证书权威和签名的证书。此外,你必须分析你的安全需求,并相应地采取行动。例如,你可能希望在数据库中设置用户,密码和角色。

Published At
Categories with 技术
comments powered by Disqus