如何在 Ubuntu 20.04 上使用 Iptables 实施基本防火墙模板

介绍

实施防火墙是确保服务器安全的重要步骤,其中很大一部分是决定将流量限制强加于您的网络的个别规则和政策。

在本指南中,您将学习如何构建可以作为更复杂的规则集的基础的防火墙,该防火墙将主要集中于提供合理的默认值,并建立一个鼓励扩展性的框架。

前提条件

要完成本教程,您将需要访问一个 Ubuntu 20.04 服务器,具有非root配置的用户,具有sudo特权. 您可以通过遵循我们 Ubuntu 20.04 初始服务器安装指南中描述的所有步骤来完成,除了 Step 4,因为我们将在本教程中设置防火墙。

此外,我们建议您查看您想要实施的防火墙策略,您可以遵循此指南(https://andsky.com/tech/tutorials/how-to-choose-an-effective-firewall-policy-to-secure-your-servers),以便更好地了解该考虑的内容。

安装永久性防火墙服务

首先,更新本地包缓存:

1sudo apt update

现在安装iptables-persistent包,这样你就可以保存你的规则集并在启动时自动应用:

1sudo apt install iptables-persistent

在安装过程中,您将被问及是否要保存当前的规则,选择 . 请注意,您将运行netfilter-persistent命令来执行iptables永久性防火墙服务。

关于IPv6的注意事项在本指南中

在我们开始之前,我们将简要讨论IPv4和IPv6。iptables命令只处理IPv4流量。对于IPv6流量,使用一个名为ip6tables的单独伴侣工具。规则存储在单独的表和链条中。对于netfilter-persistent命令,IPv4规则被写成和从/etc/iptables/rules.v4读取,而IPv6规则被存储在/etc/iptables/rules.v6中。

本指南假定您在服务器上没有积极使用IPv6;如果您的服务不利用IPv6,则更安全地完全阻止访问,正如本指南所示。

实施基本防火墙政策(快速方式)

为了尽快开始运行,我们将向您展示如何直接编辑规则文件,并复制和粘贴完成的防火墙策略。

要实施防火墙的策略和框架,您将编辑 /etc/iptables/rules.v4/etc/iptables/rules.v6 文件。 在您偏好的文本编辑器中打开 rules.v4 文件。在这里,我们将使用 nano:

1sudo nano /etc/iptables/rules.v4

内部,文件将包含以下内容:

1[label /etc/iptables/rules.v4]
2# Generated by iptables-save v1.8.4 on Tue Mar 1 19:03:10 2022
3*filter
4:INPUT ACCEPT [0:0]
5:FORWARD ACCEPT [0:0]
6:OUTPUT ACCEPT [0:0]
7COMMIT
8# Completed on Tue Mar 1 19:03:10 2022

删除这些内容并用以下内容取代它们:

 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,然后按YENTER来做到这一点。

您可以通过运行以下命令来测试文件的语法错误,如果您收到任何语法错误,请确保修复:

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

接下来,打开 /etc/iptables/rules.v6 文件来修改 IPv6 规则:

1sudo nano /etc/iptables/rules.v6

此文件将具有以下内容:

1[label /etc/iptables/rules.v6]
2# Generated by ip6tables-save v1.8.4 on Tue Mar 1 19:03:10 2022
3*filter
4:INPUT ACCEPT [0:0]
5:FORWARD ACCEPT [0:0]
6:OUTPUT ACCEPT [0:0]
7COMMIT
8# Completed on Tue Mar 1 19:03:10 2022

您可以通过用以下配置取代文件的内容来阻止所有 IPv6 流量:

 1[label /etc/iptables/rules.v6]
 2*filter
 3:INPUT DROP [0:0]
 4:FORWARD DROP [0:0]
 5:OUTPUT DROP [0:0]
 6COMMIT
 7
 8*raw
 9:PREROUTING DROP [0:0]
10:OUTPUT DROP [0:0]
11COMMIT
12
13*nat
14:PREROUTING DROP [0:0]
15:INPUT DROP [0:0]
16:OUTPUT DROP [0:0]
17:POSTROUTING DROP [0:0]
18COMMIT
19
20*security
21:INPUT DROP [0:0]
22:FORWARD DROP [0:0]
23:OUTPUT DROP [0:0]
24COMMIT
25
26*mangle
27:PREROUTING DROP [0:0]
28:INPUT DROP [0:0]
29:FORWARD DROP [0:0]
30:OUTPUT DROP [0:0]
31:POSTROUTING DROP [0:0]
32COMMIT

保存并关闭文件。

要测试此文件的语法错误,请使用ip6tables-restore命令与-t选项:

1sudo ip6tables-restore -t /etc/iptables/rules.v6

当两个规则文件报告没有语法错误时,您可以执行您设置的规则:

1sudo service netfilter-persistent reload
1[secondary_label Output]
2 * Loading netfilter rules...
3run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start
4run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start
5                                                                              	[ OK ]

这将立即实施文件中描述的策略. 您可以通过列出当前使用的iptables规则来验证这一点。

1sudo iptables -S
 1[secondary_label Output]
 2-P INPUT DROP
 3-P FORWARD DROP
 4-P OUTPUT ACCEPT
 5-N ICMP
 6-N TCP
 7-N UDP
 8-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
 9-A INPUT -i lo -j ACCEPT
10-A INPUT -m conntrack --ctstate INVALID -j DROP
11-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
12-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
13-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
14-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
15-A INPUT -p tcp -j REJECT --reject-with tcp-reset
16-A INPUT -j REJECT --reject-with icmp-proto-unreachable
17-A TCP -p tcp -m tcp --dport 22 -j ACCEPT

然后检查当前的IPv6规则:

1sudo ip6tables -S
1[secondary_label Output]
2-P INPUT DROP
3-P FORWARD DROP
4-P OUTPUT DROP

这些防火墙规则将在每次启动时再次应用,测试它,以确保您仍然可以登录,并阻止所有其他访问。

解释我们的总体防火墙策略

在基于上一节规则构建的基本防火墙中,我们创建了一个可扩展的框架,可以调整以添加或删除规则。对于IPv4流量,我们主要关心在过滤表中的INPUT链条。这个链条将处理为我们的服务器设计的所有包。我们还允许所有输出流量,并拒绝了所有包转发,这只适用于如果这个服务器作为其他主机的路由器。

一般来说,我们的规则设置了一个防火墙,默认情况下会拒绝流量,然后我们为我们希望从本政策中排除的服务和流量类型创建例外。

例如,我们总是希望拒绝被认为是无效的包,我们总是希望允许在本地循环接口的流量和与已建立的连接相关的数据。

接下来,我们根据所使用的协议来匹配流量,并将其转移到特定协议的链条中。 这些特定协议的链条旨在保留符合并允许特定服务的规则。 在本示例中,我们允许的唯一服务是TCP链中的SSH。

任何不符合通用规则或协议特定链条的服务规则的流量都由INPUT链条的最后几条规则来处理。我们已经为我们的防火墙设置了默认策略为DROP,这将拒绝违反我们的规则的软件包。

对于IPv6流量,我们放弃了所有的流量. 我们的服务器不使用这个协议,所以最安全的是根本不参与流量。

使用iptables命令实现您的防火墙

现在你了解了我们构建的策略背后的总体想法,我们将讨论如何使用iptables命令创建这些规则。我们将最终使用我们上面指定的相同的规则,但我们将通过反复添加规则来创建我们的规则。

重置您的防火墙

首先,重置防火墙规则,以便您可以从命令行查看如何构建策略。

1sudo service netfilter-persistent flush

现在检查您的规则是否已重置:

1sudo iptables -S

您应该有输出显示过滤器表中的规则已经消失,默认策略在所有链条上设置为接受:

1[secondary_label Output]
2-P INPUT ACCEPT
3-P FORWARD ACCEPT
4-P OUTPUT ACCEPT

创建特定协议链

接下来,您将创建所有特定于协议的链条,这些链条将被用来保留对您想要暴露的服务拒绝策略的例外的规则。

1sudo iptables -N UDP

然后再说一个TCP:

1sudo iptables -N TCP

还有一个关于ICMP:

1sudo iptables -N ICMP

接下来,为 SSH 流量添加例外。SSH 使用 TCP,因此您将添加一个规则来接受为端口 22’ 指定的 TCP’ 流量到 TCP 链:

1sudo iptables -A TCP -p tcp --dport 22 -j ACCEPT

如果您想要添加额外的 TCP 服务,您现在可以通过重复命令以更换端口号来做到这一点。

创建通用目的接受和否定规则

INPUT链中,所有的流量都开始过滤,我们需要添加我们的一般用途规则,这些是我们的防火墙的基线,通过接受低风险的流量(与我们已经检查的连接相关的本地流量和流量)和放弃明显无用的流量(无效的包)。

首先,创建一个例外来接受所有属于已建立的连接或与已建立的连接相关的流量:

1sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

这个规则使用了conntrack扩展,它提供内部跟踪,以便iptables具有它需要评估包作为较大的连接的一部分而不是作为一个分散,无关的包的流程的背景。TCP是一种基于连接的协议,因此建立的连接是相当明确的。对于UDP和其他无关联的协议,建立的连接是指已经看到响应的流量(原始包的来源将是响应包的目的地,反之亦然)。

您还希望允许来自本地环绕接口的所有流量. 这是由服务器生成的流量,用于服务器。

1sudo iptables -A INPUT -i lo -j ACCEPT

最后,否定所有无效的包. 包可能因多种原因而无效。 它们可能指不存在的连接,它们可能针对不存在的接口、地址或端口,或者它们可能被错误组成。

1sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

创建对特定协议链的跳跃规则

到目前为止,我们已经在INPUT链中创建了一些一般规则,以及我们协议特定的链内特定可接受的服务的一些规则。

现在,您需要将INPUT链中的流量导向到相应的协议特定的链路中,您可以匹配协议类型,将其发送到正确的链路中,并确保该包代表一个新的连接(任何已建立或相关的连接都应该早些时候处理)。

1sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP

接下來,執行以下命令「TCP」流量. 請注意,在 TCP 套件中,您將添加額外的要求,即該套件是 SYN 套件,這是啟動 TCP 連線的唯一有效類型:

1sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

然后为ICMP流量运行以下操作:

1sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

拒绝所有剩余的流量

如果一个被传递到特定协议链的数据包不匹配其中任何规则,则控制将被传回INPUT链。

您将使用REJECT目标来拒绝流量,该目标会向客户端发送响应消息,这允许您指定输出消息,以便您可以模仿如果客户端试图将包发送到常规关闭的端口时会得到的响应。

尝试到达一个封闭的UDP端口会导致一个ICMP消息表示端口无法到达

1sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable

试图在封闭的端口上建立TCP连接,在 TCP RST 响应中会产生以下结果:

1sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

对于所有其他包,您可以发送一个ICMP``协议无法访问消息,表示服务器不响应此类型的包:

1sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

调整默认政策

您添加的最后三个规则应该处理INPUT链中剩余的所有流量,但是,您应该作为预防措施将默认策略设置为DROP,如下所示:

1sudo iptables -P INPUT DROP

您还应该在前进链中设置此策略,如果该服务器未配置为其他机器的路由器:

1sudo iptables -P FORWARD DROP

<$>[警告] 警告: 您的策略设置为DROP,如果您用sudo iptables -F清除您的iptables,您的当前SSH连接将被放弃!使用sudo netfilter-persistent flush清除规则是清除规则的更好方法,因为它也将重置默认策略

要匹配您的 IPv6 流量排除策略,您可以使用以下ip6tables命令,从INPUT开始:

1sudo ip6tables -P INPUT DROP

然后运行以下前进:

1sudo ip6tables -P FORWARD DROP

通过为OUTPUT设置策略来完成:

1sudo ip6tables -P OUTPUT DROP

这应该复制您设定的规则相当紧密。

保存iptables规则

在此时,你应该测试你的防火墙规则,并确保它们阻止你想要的流量,而不会妨碍你的正常访问。

保存当前的规则(IPv4 和 IPv6),执行以下操作:

1sudo service netfilter-persistent save

这将重写您的/etc/iptables/rules.v4/etc/iptables/rules.v6文件,用您在命令行上创建的策略。

结论

通过遵循本指南,或将您的防火墙规则直接粘贴到配置文件中,或通过手动应用并将其保存到命令行上,您已经创建了一个良好的启动防火墙配置。

本指南所建立的框架应该允许您进行调整,并有助于澄清您现有的策略. 查看我们的其他一些指南,如何使用一些流行的服务来构建您的防火墙策略:

Published At
Categories with 技术
comments powered by Disqus