如何使用DigitalOcean云防火墙配置安全的Web应用程序基础架构
介绍
DigitalOcean Cloud Firewalls 在网络级别提供强大的防火墙服务,让您的服务器可以自由地为您的应用程序提供服务并存储您的数据。 在本教程中,我们将调整两台服务器的 Wordpress 和 MySQL 设置以使用云防火墙,并展示该服务可以提供的一些优势。 如果您在开始之前想了解更多有关此防火墙服务的背景信息,请阅读我们的 DigitalOcean Cloud Firewalls 教程。
先决条件
在开始本教程之前,您需要创建 如何设置远程数据库以在 Ubuntu 16.04 上使用 MySQL 优化站点性能中概述的基础架构。 这将为您留下两台服务器,一台安装了 PHP 和 WordPress 的 Nginx Web 服务器,以及一台独立的 MySQL 服务器。 在本教程中,我们将分别称这些服务器为 frontend-01 和 database-01。
我们目前的防火墙情况
现在,我们的两台服务器都使用 ufw
实用程序设置了防火墙。 ufw
是一个易于使用的 Linux iptables 防火墙引擎包装器。 现在登录到两台服务器,让我们检查防火墙的状态:
首先,在 Web 服务器上,frontend-01:
sudo ufw status verbose
OutputStatus: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22/tcp (OpenSSH) ALLOW IN Anywhere 80,443/tcp (Nginx Full) ALLOW IN Anywhere 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) 80,443/tcp (Nginx Full (v6)) ALLOW IN Anywhere (v6)
在输出中,在 Default:
之后,我们看到防火墙默认拒绝所有传入连接并允许所有传出连接。 此外,我们有四个规则允许传入 IPv4 和 IPv6 TCP 连接 (ALLOW IN
) 到端口 22 (SSH)、80 (HTTP) 和 443 (HTTPS)。
让我们在数据库服务器 database-01 上做同样的事情:
sudo ufw status verbose
OutputStatus: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- 22/tcp (OpenSSH) ALLOW IN Anywhere 3306 ALLOW IN Anywhere 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) 3306 (v6) ALLOW IN Anywhere (v6)
这个输出是相似的,除了我们将两个 Nginx 端口交换为端口 3306,这是标准 MySQL 端口。 现在我们知道了我们当前的设置,让我们计划我们的替换。
我们的云防火墙计划
虽然我们可以只制作两个云防火墙,一个为每个特定服务器量身定制,一个应用于 frontend-01,另一个应用于 database-01,但我们将采取更多灵活的方法来组织我们的规则。
首先,我们希望为将来可能需要向该系统添加第三种类型的服务(可能是缓存服务器)做好准备。 因此,我们将根据角色而不是物理服务器来拆分防火墙规则。 我们可以为每个 Droplet 应用多个 Cloud Firewalls,因此使这些防火墙细粒度和模块化不是问题。
注意:如果您想更深入地探索有关构建云防火墙的最佳实践,请阅读如何组织DigitalOcean云防火墙。
如果我们稍微分解一下,我们会注意到我们的两个服务器实际上都有多种功能。 主要功能是提供网页或数据库信息,还有一个由 SSH 服务提供的管理功能。 对我们来说,创建一个管理防火墙、一个前端防火墙和一个数据库防火墙是很有意义的。
为了处理将来我们将 Web 或数据库服务扩展到多个主机的场景,我们将使用 DigitalOcean 的标记功能按角色组织我们的 Droplets。 标签是简单的标签,我们可以将它们应用于 Droplet 以对它们进行分类并同时处理整个服务器组。 Cloud Firewall 服务可以将防火墙规则应用于标签中的所有 Droplet,从而可以轻松地为新的 Droplet 提供正确的防火墙规则。
另一个好处——使用 ufw
以动态方式很难做到的事情——是云防火墙可以根据标签限制入站访问。 例如,我们的 数据库 服务器只需要从我们的 前端 服务器访问。 当前的 ufw
设置使数据库对网络上的任何人开放。 我们将把它锁定到只有带有 frontend 标记的 Droplets。
让我们用简单的语言总结一下我们需要设置的三个防火墙:
- 管理: 允许从任何主机到 TCP 端口 22 的入站流量
- 前端: 允许从任何主机到 TCP 端口 80 和 443 的入站流量
- Database: 只允许从 frontend 标记的服务器到 TCP 端口 3306 的入站流量
在本教程中,我们根本不会限制出站流量。 这不是一个坏主意,但确实需要注意确保您不会破坏底层操作系统的自动更新机制和其他关键功能。
现在我们已经为我们的新防火墙制定了计划,让我们开始吧。
第 1 步 — 标记我们的服务器
首先,我们将按角色标记我们的液滴,为我们的防火墙规则做准备。 导航到 DigitalOcean 控制面板。 默认视图是您的 Droplet 的列表。 点击 frontend-01 Droplet 右侧的 More 按钮,然后选择 Add tags:
将弹出一个文本框,您可以在其中输入此 Droplet 的标签。 输入前端,点击添加标签按钮:
对你的数据库服务器做同样的事情,给它一个 database 标签。 标签将显示在您的 Droplet 列表中:
在创建未来的 Droplet 时,您可以在初始配置过程中应用这些标签。 然后,Droplet 将自动继承相应的防火墙规则。
我们将在下一步中设置这些规则。
第 2 步 — 创建云防火墙
我们现在要设置我们的云防火墙。 我们先做前端防火墙,然后是数据库,然后是管理。 此命令不会对您的网站访问者造成服务中断,但我们将暂时失去建立新 SSH 连接的能力。 这不会影响已经建立的连接。
防火墙服务在 DigitalOcean 控制面板的 Networking 部分下可用。 在那里,单击 Firewalls 选项卡,然后单击 Create Firewall 按钮开始使用。
创建前端防火墙
在创建防火墙页面,我们需要填写一个名称,配置我们的入站规则,并选择要应用防火墙的Droplet。 我们将保持 Outbound Rules 部分不变。
我们首先创建 frontend 防火墙,因此将 frontend-fw 放入 Name 字段。
注意: 我们将在防火墙名称的末尾添加 -fw 以消除歧义。 尽管控制面板界面使用图标来区分资源类型,但如果您使用命令行或 API 并且有多个 前端 项目,它可能会让人感到困惑。
接下来,我们需要从 Inbound Rules 部分删除默认的 SSH 规则。 为了灵活性,我们将把这条规则分解到 management 防火墙中。 现在使用页面右侧的 Delete 链接删除 SSH 规则。
然后,单击 New rule 下拉菜单并选择 HTTP。 这将自动填充正确的协议 (TCP) 和端口 (80),默认情况下允许来自所有 IPv4 和 IPv6 地址的流量。 这就是我们想要的。
如果您启用了 HTTPS,请重复上述过程以创建第二条规则,这次选择 HTTPS。 您的 入站规则 部分最终将如下所示:
最后,在 Apply to Droplets 字段中,开始输入 frontend,然后在自动建议时选择 frontend 标签。
单击创建防火墙按钮。 新防火墙将被创建并应用于任何带有 frontend 标签的 Droplet。 您将返回到更新的防火墙摘要页面,显示您的新防火墙:
现在我们将创建 数据库 防火墙。
创建数据库防火墙
在防火墙页面上,再次单击创建防火墙。 该过程与我们的 前端 防火墙基本相同。
在 Name 字段中键入 database-fw。
在入站规则中,删除默认的SSH规则。 然后,使用下拉菜单创建一个新规则,选择 MySQL。 将创建一个默认的 MySQL 规则,允许从所有 IP 访问端口 3306。 从 Sources 字段中删除 All IPv4 和 All IPv6。 我们只希望我们的前端服务器能够访问数据库。 开始在 Sources 框中输入 frontend,并在自动建议时选择 frontend 标签。 现在,任何应用了该标签的 Droplet 都将被允许访问数据库服务器。 所有其他 IP 都被阻止。
保持 Outbound Rules 不变。 在 Apply to Droplets 下,将此防火墙应用到 database 标签,然后点击 Create Firewall。 再次,您将返回到防火墙摘要页面:
请注意,两个防火墙都显示它们各自应用于一个 Droplet。 如果您加载您的网站,它应该仍然可以正常加载。 现在让我们通过 SSH 重新启用管理。
创建管理防火墙
最后一次点击【X6X】创建防火墙【X25X】。 将 management-fw 添加到 Name 字段。
默认的 SSH 规则就是我们需要的防火墙。 这将允许任何 IP 连接到端口 22。
或者,您可以将 SSH 规则的 Sources 字段更改为您将要连接的特定 IP。 例如,如果您的办公室有一个静态 IP,并且您希望将 SSH 访问限制为仅来自办公室的连接,则将该 IP 放入 Sources,替换 All IPv4 和 所有 IPv6 。 如果您的 IP 将来发生变化,您只需更新这条规则即可恢复管理访问权限,这是提前规划并使我们的规则模块化的另一个优势。
在 Apply to Droplets 下,添加 frontend 和 database 标签,然后点击 Create Firewall。 让我们看一下我们最终的防火墙总结:
此时,我们的云防火墙应该可以正常工作,但我们仍然有基于主机的 ufw
防火墙处于活动状态。 让我们禁用这些,然后测试我们的连接。
第 3 步 — 删除主机防火墙
我们需要禁用两台主机上的 ufw
防火墙。 首先,在 frontend-01 上:
sudo ufw disable
OutputFirewall stopped and disabled on system startup
然后在 database-01 上:
sudo ufw disable
OutputFirewall stopped and disabled on system startup
这会停止当前防火墙,清除所有规则,并防止规则在启动时重新启用。
此时,我们所有的连接都应该恢复。 尝试为您的其中一台服务器创建一个新的 SSH 会话。 然后加载您的网站以验证 Web 服务器是否仍在连接到数据库并将网页返回到浏览器。
能够连接到我们所有的服务实际上并不能证明防火墙正在运行。 让我们做更多的测试来验证我们的防火墙是否真的到位。
第 4 步 — 测试我们的防火墙
为了测试我们的防火墙,我们将登录到第三台服务器,并使用一个名为 nmap
的实用程序来扫描我们的 Web 和数据库服务器。 nmap
是一个端口扫描器,它将扫描我们的主机并告诉我们哪些端口是打开、关闭或过滤的。
登录到与 frontend-01 和 database-01 服务器位于同一区域的另一台 Ubuntu 16.04 服务器。 然后安装nmap
:
sudo apt-get update sudo apt-get install nmap
然后,使用 nmap
扫描 Web 服务器的公网 IP:
nmap -Pn frontend-01_public_ip
OutputStarting Nmap 7.01 ( https://nmap.org ) at 2017-06-05 17:08 UTC Nmap scan report for 203.0.113.11 Host is up (0.0022s latency). Not shown: 997 filtered ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http 443/tcp open https Nmap done: 1 IP address (1 host up) scanned in 4.54 seconds
注意关于 filtered ports
的输出。 如果防火墙不起作用,这些将显示为 closed ports
。 Filtered 表示 nmap
连连接都无法判断端口是打开还是关闭。
另请注意,我们看到我们的 SSH、HTTP 和 HTTPS 端口按预期打开。
接下来,我们将扫描数据库服务器。 如果您以这种方式设置,请务必使用 Droplet 的私有 IP,因为这就是 MySQL 数据库将监听的内容:
nmap -Pn database-01_private_ip
OutputStarting Nmap 7.01 ( https://nmap.org ) at 2017-06-05 17:21 UTC Nmap scan report for 198.51.100.20 Host is up (0.0024s latency). Not shown: 999 filtered ports PORT STATE SERVICE 22/tcp open ssh Nmap done: 1 IP address (1 host up) scanned in 8.17 seconds
我们看到大多数端口都像以前一样被过滤。 但是,我们只看到 SSH 端口处于打开状态,没有可用的 MySQL 端口。 回想一下,我们将数据库访问限制为仅标记为 frontend 的那些服务器。 切换回 DigitalOcean 控制面板并将 frontend 标签添加到您正在使用 nmap
的服务器。 然后重新运行命令:
nmap -Pn database-01_private_ip
OutputStarting Nmap 7.01 ( https://nmap.org ) at 2017-06-05 17:22 UTC Nmap scan report for 198.51.100.20 Host is up (0.0033s latency). Not shown: 998 filtered ports PORT STATE SERVICE 22/tcp open ssh 3306/tcp open mysql Nmap done: 1 IP address (1 host up) scanned in 4.46 seconds
MySQL 端口现在显示为打开。 我们已经验证我们的两台服务器现在都受到我们的云防火墙规则的保护。 您现在可以通过返回控制面板并删除 Droplet 的 frontend 标签来恢复此测试服务器的原始防火墙设置。
结论
在本教程中,我们将 ufw
防火墙设置替换为灵活且强大的基于网络的云防火墙配置。 有关通过 doctl
或 DigitalOcean API 使用云防火墙的更多信息,请参阅以下文章: