如何设置 Iptables 防火墙以保护服务器之间的流量

介绍

将应用程序设置中的分离组件部署到不同的节点是减少负载并开始水平扩展的一种常见方法. 一个典型的例子是将数据库配置在应用程序的单独服务器上。

在本指南中,我们将展示如何在分布式设置中在每个服务器上设置防火墙,我们将配置我们的策略以允许我们组件之间的预期流量,同时拒绝其他流量。

您还可以配置 DigitalOcean’s Cloud Firewalls,这些防火墙作为DigitalOcean基础设施上的服务器的额外外层运行,因此您不需要在服务器上自行配置防火墙。

对于本指南中的演示,我们将使用两个Ubuntu 22.04服务器。一个将有一个与Nginx服务的Web应用程序,另一个将为该应用程序托管MySQL数据库。

前提条件

要开始,你需要两个新的 Ubuntu 22.04 服务器。 添加一个常规用户帐户,每个用户都有sudo特权。 要做到这一点,请遵循我们的 Ubuntu 22.04 初始服务器设置指南

我們將要確保的應用程式設定是基於 本指南。 如果您想跟隨這個例子,請按本教程所示設定您的應用程式和資料庫伺服器。

步骤1:设置防火墙

您将通过为每个服务器实施基线防火墙配置来开始。我们将实施的策略采用安全第一方法. 我们将锁定除了SSH流量之外的几乎所有东西,然后为我们的特定应用程序填补防火墙中的洞。

此指南遵循iptables语法。iptables在Ubuntu 22.04上使用nftables后端自动安装,因此您不应该安装任何额外的软件包。

使用nano或您最喜欢的文本编辑器,打开/etc/iptables/rules.v4文件:

1sudo nano /etc/iptables/rules.v4

从防火墙模板指南中粘贴配置:

 1[label /etc/iptables/rules.v4]
 2*filter
 3# Allow all outgoing, but drop incoming and forwarding packets by default
 4:INPUT DROP [0:0]
 5:FORWARD DROP [0:0]
 6:OUTPUT ACCEPT [0:0]
 7
 8# Custom per-protocol chains
 9:UDP - [0:0]
10:TCP - [0:0]
11:ICMP - [0:0]
12
13# Acceptable UDP traffic
14
15# Acceptable TCP traffic
16-A TCP -p tcp --dport 22 -j ACCEPT
17
18# Acceptable ICMP traffic
19
20# Boilerplate acceptance policy
21-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
22-A INPUT -i lo -j ACCEPT
23
24# Drop invalid packets
25-A INPUT -m conntrack --ctstate INVALID -j DROP
26
27# Pass traffic to protocol-specific chains
28## Only allow new connections (established and related should already be handled)
29## For TCP, additionally only allow new SYN packets since that is the only valid
30## method for establishing a new TCP connection
31-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
32-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
33-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
34
35# Reject anything that's fallen through to this point
36## Try to be protocol-specific w/ rejection message
37-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
38-A INPUT -p tcp -j REJECT --reject-with tcp-reset
39-A INPUT -j REJECT --reject-with icmp-proto-unreachable
40
41# Commit the changes
42COMMIT
43
44*raw
45:PREROUTING ACCEPT [0:0]
46:OUTPUT ACCEPT [0:0]
47COMMIT
48
49*nat
50:PREROUTING ACCEPT [0:0]
51:INPUT ACCEPT [0:0]
52:OUTPUT ACCEPT [0:0]
53:POSTROUTING ACCEPT [0:0]
54COMMIT
55
56*security
57:INPUT ACCEPT [0:0]
58:FORWARD ACCEPT [0:0]
59:OUTPUT ACCEPT [0:0]
60COMMIT
61
62*mangle
63:PREROUTING ACCEPT [0:0]
64:INPUT ACCEPT [0:0]
65:FORWARD ACCEPT [0:0]
66:OUTPUT ACCEPT [0:0]
67:POSTROUTING ACCEPT [0:0]
68COMMIT

如果您正在使用nano,请按Ctrl+X,然后在提示时按Y,然后按Enter

如果您在实时环境中实现此操作,请不要重新加载您的防火墙规则。下载此处描述的规则将立即降低应用程序和数据库服务器之间的连接,您需要在重新加载之前调整规则以反映我们的运营需求。

步骤 2 – 发现您的服务使用的端口

您可以通过检查您的配置文件来找到正确的网络端口,但寻找正确的端口的应用程序性方法只是检查哪些服务在我们的每个机器上听取连接。

您可以使用netstat工具来查找这一点,因为您的应用程序仅通过IPv4进行通信,我们会添加4参数,但如果您正在使用IPv6也可以删除。

这些论点可以分为如下:

●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●

1sudo netstat -4plunt

在您的 Web 服务器上,您的输出可能是这样的:

1[secondary_label Output]
2Active Internet connections (only servers)
3Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
4tcp 0 0 0.0.0.0:22 0.0.0.0:*               LISTEN 1058/sshd
5tcp 0 0 0.0.0.0:80 0.0.0.0:*               LISTEN 4187/nginx

第一个突出列显示的IP地址和端口是指向行末点突出的服务正在收听的,特殊的0.0.0.0地址意味着该服务正在收听所有可用的地址。

在您的数据库服务器上,您的输出可能会看起来如下:

1sudo netstat -4plunt
1[secondary_label Output]
2Active Internet connections (only servers)
3Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
4tcp 0 0 0.0.0.0:22 0.0.0.0:*               LISTEN 1097/sshd
5tcp 0 0 192.0.2.30:3306 0.0.0.0:*               LISTEN 3112/mysqld

在本示例中,192.0.2.30地址代表了数据库服务器的私人IP地址。

请注意在此步骤中找到的值,这些是您需要调整防火墙配置的网络细节。

在您的 Web 服务器上,您需要确保下列端口可访问:

  • 所有地址上的端口 80 所有地址上的端口 22 (已在防火墙规则中考虑)

您的数据库服务器必须确保下列端口可访问:

  • 端口 3306 在地址 192.0.2.30 (或与之相关的接口)
  • 端口 22 在所有地址(已经在防火墙规则中考虑)

步骤 3 – 调整 Web 服务器防火墙规则

现在你有所需的端口信息,你会调整你的网页服务器的防火墙规则设置。

1sudo nano /etc/iptables/rules.v4

在 Web 服务器上,您需要将端口 80 添加到可接受的流量列表中,因为服务器正在收听所有可用的地址 - 网页服务器通常希望可以从任何地方访问 - 您不会根据接口或目的地地址限制规则。

您的网页访问者将使用 TCP 协议连接。 您的框架已经有一个名为TCP的自定义链,用于 TCP 应用程序的例外。

1[label /etc/iptables/rules.v4]
2*filter
3. . .
4
5# Acceptable TCP traffic
6-A TCP -p tcp --dport 22 -j ACCEPT
7-A TCP -p tcp --dport 80 -j ACCEPT
8
9. . .

您的网页服务器将启动与您的数据库服务器的连接,您的出发流量在您的防火墙中不受限制,与已建立的连接相关的输入流量是允许的,因此我们不需要在该服务器上打开任何额外的端口来允许这种连接。

当您完成时,将文件保存并关闭. 您的 Web 服务器现在有一个防火墙策略,将允许所有合法的流量,同时阻止其他一切。

测试您的规则文件以检测语法错误:

1sudo iptables-restore -t < /etc/iptables/rules.v4

如果没有出现语法错误,请重新加载防火墙以执行新的规则集:

1sudo service iptables-persistent reload

步骤 4 – 调整数据库服务器防火墙规则

在您的数据库服务器上,您需要允许访问服务器的私人IP地址上的端口3306。在这种情况下,该地址是192.0.2.30

若要找到与该地址相关联的网络接口,请运行ip -4 addr show scope global:

1ip -4 addr show scope global
1[secondary_label Output]
22: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
3    inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0
4       valid_lft forever preferred_lft forever
53: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
6    inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1
7       valid_lft forever preferred_lft forever

突出的区域显示eth1接口与该地址相关联。

接下来,您将调整数据库服务器上的防火墙规则。

1sudo nano /etc/iptables/rules.v4

再次,您将为我们的TCP链添加一个规则,以形成您的网络和数据库服务器之间的连接的例外。

若要根据实际地址限制访问,则可以添加如下规则:

1[label /etc/iptables/rules.v4]
2*filter
3. . .
4
5# Acceptable TCP traffic
6-A TCP -p tcp --dport 22 -j ACCEPT
7-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT
8
9. . .

如果您更愿意允许基于该地址的接口的例外,则可以添加类似此规则:

1[label /etc/iptables/rules.v4]
2*filter
3. . .
4
5# Acceptable TCP traffic
6-A TCP -p tcp --dport 22 -j ACCEPT
7-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT
8
9. . .

保存并关闭文件,当你完成。

用这个命令检查语法错误:

1sudo iptables-restore -t < /etc/iptables/rules.v4

当你准备好时,重新加载防火墙规则:

1sudo service iptables-persistent reload

现在,您的两个服务器都应该受到保护,而不会限制它们之间的必要数据流。

结论

虽然我们通过使用运行 Nginx 和 MySQL 的两个服务器展示了此配置,但上面展示的技术无论您的特定技术选择如何都适用。

要了解更多关于防火墙和具体的iptables,请查看以下指南:

Published At
Categories with 技术
Tagged with
comments powered by Disqus