安全性是最好分层完成的事情之一。我们称之为深度安全。因此,在任何给定的公司网络上,您都会发现一个防火墙设备,将互联网与您的面向互联网的服务器所在的非军事区 ( 非军事区)隔开。您还可以在非军事区和内部局域网之间找到一个防火墙设备,以及安装在每台服务器和客户机上的防火墙软件。我们希望尽可能让入侵者难以在我们的网络中到达他们的最终目的地。
然而,有趣的是,在所有主要的 Linux 发行版中,只有 SUSE 发行版和红帽类型发行版已经安装并启用了 firewalld。当您查看您的 Ubuntu 虚拟机时,您会发现它是完全开放的,就好像它在向任何潜在的入侵者表示衷心的欢迎。
由于本书的重点是加固我们的 Linux 服务器,我们将在这一章集中讨论最后一层防御:服务器和客户端上的防火墙。我们将涵盖所有主要的命令行防火墙接口,从 iptables 到新的 kid on blocknftables。
在本章中,我们将涵盖以下主题:
- 防火墙概述
- iptables 概述
- Ubuntu 系统的简单防火墙
在下一章中,我们将讨论 nftables 和 firewalld。
本章的代码文件可以在这里找到:https://github . com/packt publishing/Mastering-Linux-Security-and-Harding-第二版。
在典型的业务环境中,尤其是在大型企业中,您可能会在不同的地方遇到各种类型的防火墙,它们可以提供各种类型的功能。一些例子如下:
- 将互联网与内部网络分开的边缘设备将可路由的公共 IP 地址转换为不可路由的私有 IP 地址。他们还可以提供各种类型的访问控制来阻止未经授权的人。通过还提供各种类型的数据包检查服务,它们可以帮助防止对内部网络的攻击,防范恶意软件,并防止敏感信息从内部网络泄漏到互联网。
- 大型企业网络通常分为子网或子网,每个公司部门都有一个属于自己的子网。最佳做法是用防火墙分隔子网。这有助于确保只有授权人员才能访问任何给定的子网。
- 当然,您还可以在单独的服务器和工作站上运行 firewalld。通过提供一种形式的访问控制,它们可以帮助防止入侵者从一台机器向网络上的另一台机器进行横向移动。它们还可以配置为防止某些类型的端口扫描和拒绝服务 ( DoS )攻击。
对于前面列表中的前两个项目,您可能会看到专门的防火墙设备和防火墙管理员团队在处理它们。列表中的第三项是你,Linux 专业人员,进入图片的地方。在这一章和下一章中,我们将看看 Linux 服务器和 Linux 工作站发行版附带的防火墙技术。
一个常见的误解是 iptables 是 Linux 防火墙的名称。实际上,Linux 防火墙的名字是 netfilter,每个 Linux 发行版都内置了它。我们所知道的是,iptables 只是我们可以用来管理 netfilter 的几个命令行实用程序之一。它最初是作为 Linux 内核 2.6 版本的一个特性引入的,所以它已经存在了很长时间。使用 iptables,您确实有一些优势:
- 它已经存在了足够长的时间,大多数 Linux 管理员已经知道如何使用它。
- 很容易在 shell 脚本中使用 iptables 命令来创建自己的自定义防火墙配置。
- 它具有很大的灵活性,因为您可以使用它来设置简单的端口过滤器、路由器或虚拟专用网络。
- 几乎每个 Linux 发行版都预装了它,尽管大多数发行版都没有预配置它。
- 它被很好地记录下来,并且在互联网上有免费的、书籍长度的教程。
但是,您可能知道,也有一些缺点:
- IPv4 和 IPv6 都需要自己特殊的 iptables 实现。因此,如果您的组织在迁移到 IPv6 的过程中仍然需要运行 IPv4,那么您必须在每台服务器上配置两个防火墙,并为每台服务器运行一个单独的守护程序(一个用于 IPv4,另一个用于 IPv6)。
- 如果你需要做 MAC 桥接,那就需要 ebtables,它是 iptables 的第三个组件,有自己独特的语法。
- arptables 是 iptables 的第四个组件,也需要自己的守护进程和语法。
- 每当您向正在运行的 iptables 防火墙添加规则时,必须重新加载整个 iptables 规则集,这可能会对性能产生巨大影响。
直到最近,普通 iptables 还是每个 Linux 发行版的默认防火墙管理器。它仍然在大多数发行版上,但是红帽企业版 Linux 7 及其所有后代现在都使用新的 firewalld 作为更容易使用的前端来配置 iptables 规则。Ubuntu 自带简单防火墙 ( ufw ),这也是一个易于使用的 iptables 前端。我们将探索的一项更新的技术是 nftables,它在 Debian/Ubuntu 系统上作为一个选项提供。在红帽 8/CentOS 8 系统上,nftables 已经取代 iptables 成为 firewalld 的默认后端。(如果这一切听起来令人困惑,不要担心——一切都会在适当的时候变得清晰。)
在本章中,我们将讨论为 IPv4 和 IPv6 设置 iptables 防火墙规则。
iptables 由五个规则表组成,每个表都有自己独特的用途:
- 过滤表:为了对我们的服务器和客户端进行基本保护,这可能是我们唯一使用的表。
- 网络地址转换(NAT)表 : NAT 用于将公共互联网连接到专用网络。
- 破坏表:这是用来在网络数据包通过防火墙时改变数据包的。
- 原始表:这是针对不需要连接跟踪的数据包。
- 安全表:安全表只用于安装了 SELinux 的系统。
因为我们目前只对基本的主机保护感兴趣,所以我们暂时只看过滤表。(过一会儿,我将向您展示一些我们可以用轧伤台完成的奇特技巧。)每个表由规则链组成,过滤表由INPUT
、FORWARD
和OUTPUT
链组成。由于我们的 CentOS 机器使用红帽的防火墙,我们将在我们的 Ubuntu 机器上看到这一点。
While it's true that Red Hat Enterprise Linux 7/8 and their offspring do come with the iptables service already installed, it's disabled by default so that we can use firewalld. It's not possible to have both the iptables service and the firewalld service running at the same time, because they're two totally different animals that are completely incompatible. So, if you need to run the iptables service on a Red Hat 7/8 system, you can do so, but you must disable firewalld first.
However, if your organization is still running its network with version 6 of either Red Hat or CentOS, then your machines are still running with iptables, since firewalld isn't available for them.
首先,我们将通过使用sudo iptables -L
命令来查看我们当前的配置:
donnie@ubuntu:~$ sudo iptables -L
[sudo] password for donnie:
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
还记得我们说过您需要 iptables 的单独组件来处理 IPv6 吗?在这里,我们将使用sudo ip6tables -L
命令:
donnie@ubuntu:~$ sudo ip6tables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
在这两种情况下,你可以看到没有规则,机器是完全开放的。不像 SUSE 和红帽的人,Ubuntu 的人期望你做所有设置防火墙的工作。我们将首先创建一个规则,允许我们将主机请求连接的服务器传入的数据包传递到:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
下面是这个命令的分解:
-A INPUT
:-A
在指定链的末端放置一个规则,在本例中是INPUT
链。如果我们想将规则放在链的开头,我们会使用-I
。-m
:这在 iptables 模块中调用。在这种情况下,我们调用 conntrack 模块来跟踪连接状态。例如,这个模块允许 iptables 确定我们的客户端是否已经连接到另一台机器。--ctstate
:我们的规则中的 ctstate 或 connection state 部分在寻找两件事。首先,它寻找客户端与服务器建立的连接。然后,它寻找从服务器返回的相关连接,以便允许它连接到客户端。因此,如果用户使用网络浏览器连接到网站,该规则将允许来自网络服务器的数据包通过防火墙到达用户的浏览器。-j
:这个代表跳跃。规则跳转到一个特定的目标,在这种情况下是ACCEPT
。(请不要问我这个术语是谁想出来的。)因此,此规则将接受客户端请求连接的服务器返回的数据包。
我们的新规则集如下所示:
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
接下来,我们将打开端口22
,这样我们就可以通过安全外壳进行连接:
sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT
细分如下:
-A INPUT
:和之前一样,我们想把这个规则放在INPUT
链的末端,加上-A
。-p tcp
:-p
表示该规则影响的协议。此规则影响 TCP 协议,安全外壳是该协议的一部分。--dport ssh
:当一个选项名称由多个字母组成时,我们需要在前面加两个破折号,而不是只有一个。--dport
选项指定我们希望此规则运行的目的端口。(注意,我们也可以将这部分规则列为--dport 22
,因为 22 是 SSH 端口的号码。)-j ACCEPT
:如果我们把这些都和-j ACCEPT
放在一起,那么我们就有了一个规则,允许其他机器通过 Secure Shell 连接到这个机器。
现在,假设我们希望这台机器成为一台 DNS 服务器。为此,我们需要为 TCP 和 UDP 协议打开端口53
:
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT
最后,我们的INPUT
链有了一个几乎完整的可用规则集:
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere ctstate
RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
然而,这只是几乎完成,因为还有一件小事我们忘记了。也就是说,我们需要允许环回接口的流量。这没问题,因为这给了我们一个很好的机会,如果我们不想在最后插入规则,我们可以看看如何在我们想要的地方插入规则。在这种情况下,我们将在INPUT 1
处插入规则,这是INPUT
链的第一个位置:
sudo iptables -I INPUT 1 -i lo -j ACCEPT
Before you inserted the ACCEPT
rule for the lo
interface, you may have noticed that sudo commands were taking a long time to complete and that you were getting sudo: unable to resolve host. . .Resource temporarily unavailable
messages. That's because sudo needs to know the machine's hostname so that it can know which rules are allowed to run on a particular machine. It uses the loopback interface to help resolve the hostname. If the lo
interface is blocked, it takes longer for sudo to resolve the hostname.
我们的规则集现在如下所示:
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:domain
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
注意端口53
是如何被列为域端口的。要查看端口号而不是端口名称,我们可以使用-n
开关:
donnie@ubuntu3:~$ sudo iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu3:~$
现在,就目前的情况来看,我们仍然允许一切通过,因为我们仍然没有创建一个规则来阻止我们没有明确允许的事情。不过,在此之前,让我们再看一些我们可能希望允许的事情。
在你职业生涯的大部分时间里,你可能听说过的传统观点是,我们需要阻止来自互联网控制消息协议 ( ICMP )的所有数据包。你可能被告知的想法是通过阻止 ping 数据包使你的服务器对黑客不可见。当然,还有一些与 ICMP 相关的漏洞,例如:
- 通过使用僵尸网络,黑客可以同时用来自多个来源的 ping 数据包淹没您的服务器,耗尽您的服务器的应对能力。
- 与 ICMP 协议相关的某些漏洞可能允许黑客获得您系统的管理权限,将您的流量重定向到恶意服务器,或者使您的操作系统崩溃。
- 通过使用一些简单的黑客工具,有人可以在 ICMP 数据包的数据字段中嵌入敏感数据,以便从您的组织中秘密泄露这些数据。
然而,虽然阻止某些类型的 ICMP 数据包是好的,但阻止所有 ICMP 数据包是坏的。严酷的现实是,某些类型的 ICMP 消息对于网络的正常运行是必要的。由于我们最终创建的丢弃所有不允许的规则也会阻止 ICMP 数据包,因此我们需要创建一些允许我们必须拥有的 ICMP 消息类型的规则。所以,这是:
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 3 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 11 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 12 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
细分如下:
-m conntrack
:和之前一样,我们使用conntrack
模块来允许处于某种状态的数据包。不过,这一次,我们不仅仅允许来自我们的服务器所连接的主机(ESTABLISHED,RELATED
)的数据包,我们还允许其他主机向我们的服务器发送NEW
数据包。-p icmp
:这里指的是 ICMP 协议。--icmp-type
:ICMP 消息有很多种类型,接下来我们将对其进行概述。
我们希望允许的三种 ICMP 消息如下:
type 3
:这些是目的地无法到达的消息。他们不仅可以告诉你的服务器它无法到达某个主机,还可以告诉它为什么。例如,如果服务器发出的数据包太大,网络交换机无法处理,交换机将发回一条 ICMP 消息,告诉服务器将该大数据包分段。如果没有 ICMP,服务器每次试图发送一个需要分解成碎片的大数据包时都会出现连接问题。type 11
:超时消息让您的服务器知道,它发出的数据包在到达目的地之前已经超过了其生存时间 ( TTL )值,或者在 TTL 到期日期之前无法重新组装碎片数据包。type 12
:参数问题消息表示服务器发送了一个 IP 头错误的数据包。换句话说,IP 报头要么缺少选项标志,要么长度无效。
我们的列表中明显缺少三种常见的消息类型:
type 0
和type 8
:这些就是臭名昭著的 ping 包。实际上,type 8
是你发送给 ping 主机的回显请求包,type 0
是主机返回的回显回复,让你知道它还活着。当然,允许 ping 数据包通过可能对排除网络问题有很大帮助。如果出现这种情况,您可以添加一些 iptables 规则来暂时允许 pings。type 5
:现在,我们有了臭名昭著的重定向消息。如果你有一台路由器,可以建议服务器使用更有效的路径,允许这些可能会很方便,但黑客也可以使用它们将你重定向到你不想去的地方。所以,挡住他们。
ICMP 消息类型比我在这里展示的要多得多,但这些是我们目前唯一需要担心的。
当我们使用sudo iptables -L
时,我们将看到我们的新规则集,就目前的情况而言:
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:domain
ACCEPT icmp -- anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp destination-unreachable
ACCEPT icmp -- anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp source-quench
ACCEPT icmp -- anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp time-exceeded
ACCEPT icmp -- anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp parameter-problem
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
看起来不错,是吧?不完全是。我们还没有用这个规则集阻止任何东西。所以,让我们来解决这个问题。
要开始阻止我们不想要的东西,我们必须做两件事之一。我们可以为INPUT
链设置默认的DROP
或REJECT
策略,或者我们可以将策略设置保留为ACCEPT
并在INPUT
链的末端创建一个DROP
或REJECT
规则。你选择哪一个真的是个人喜好的问题。(当然,在选择其中一个之前,您可能需要查看组织的政策手册,看看您的雇主是否有偏好。)
DROP
和REJECT
的区别在于DROP
会拦截数据包,而不会向发送方发回任何消息。REJECT
拦截数据包,然后向发送方发回一条消息,说明数据包被拦截的原因。就我们目前的目的而言,假设我们只是想要我们不想通过的DROP
数据包。
There are times when DROP
is better, and times when REJECT
is better. Use DROP
if it's important to make your host invisible. (Although, even that isn't that effective, because there are other ways to discover hosts.) If you need your hosts to inform other hosts about why they can't make a connection, then use REJECT
. The big advantage of REJECT
is that it will let connecting hosts know that their packets are being blocked so that they will know to immediately quit trying to make a connection. With DROP
, the host that's trying to make the connection will just keep trying to make the connection until it times out.
要在INPUT
链的末端创建DROP
规则,请使用以下代码:
donnie@ubuntu:~$ sudo iptables -A INPUT -j DROP
donnie@ubuntu:~$
要设置默认的DROP
策略,我们可以使用以下代码:
donnie@ubuntu:~$ sudo iptables -P INPUT DROP
donnie@ubuntu:~$
设置默认的DROP
或REJECT
政策的最大好处是,如果需要的话,可以更容易地添加新的ACCEPT
规则。这是因为如果我们决定保留默认的ACCEPT
策略,并创建一个DROP
或REJECT
规则,该规则必须在列表的底部。
由于 iptables 规则是按从上到下的顺序进行处理的,因此在DROP
或REJECT
规则之后的任何ACCEPT
规则都将无效。您需要在最终的DROP
或REJECT
规则之上插入任何新的ACCEPT
规则,这比仅仅能够将它们附加到列表的末尾稍微不方便一点。现在,为了说明我的下一点,我刚刚离开了默认的ACCEPT
策略,添加了DROP
规则。
当我们查看我们的新规则集时,我们会看到一些相当奇怪的东西:
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
. . .
. . .
ACCEPT icmp -- anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp parameter-problem
DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
. . .
. . .
INPUT
链的第一个规则和最后一个规则看起来是一样的,只是一个是DROP
,另一个是ACCEPT
。让我们用-v
(详细)选项再看一遍:
donnie@ubuntu:~$ sudo iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
67 4828 ACCEPT all -- lo any anywhere anywhere
828 52354 ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED
. . .
. . .
0 0 ACCEPT icmp -- any any anywhere anywhere ctstate NEW,RELATED,ESTABLISHED icmp parameter-problem
251 40768 DROP all -- any any anywhere anywhere
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
. . .
. . .
现在,我们可以看到lo
,对于环回,显示在第一个规则的in
列下,any
显示在最后一个规则的in
列下。我们还可以看到-v
开关显示了每个规则已经计数的数据包和字节的数量。因此,在前面的例子中,我们可以看到ctstate RELATED,ESTABLISHED
规则已经接受了 828 个数据包和 52,354 个字节。DROP all
规则已经阻止了 251 个数据包和 40,763 个字节。
这些看起来都很棒,只是如果我们现在重启机器,规则就会消失。我们需要做的最后一件事是使它们永久化。有几种方法可以做到这一点,但是在 Ubuntu 机器上最简单的方法是安装iptables-persistent
包:
sudo apt install iptables-persistent
在安装过程中,您将看到两个屏幕,询问您是否要保存当前的 iptables 规则集。第一个屏幕将显示 IPv4 规则,而第二个屏幕将显示 IPv6 规则:
您现在将在/etc/iptables
目录中看到两个新的规则文件:
donnie@ubuntu:~$ ls -l /etc/iptables*
total 8
-rw-r--r-- 1 root root 336 Oct 10 10:29 rules.v4
-rw-r--r-- 1 root root 183 Oct 10 10:29 rules.v6
donnie@ubuntu:~$
如果你现在重启机器,你会发现你的 iptables 规则仍然有效。iptables-persistent
唯一的小问题是,它不会保存您对规则所做的任何后续更改。不过,没关系。我稍后会告诉你如何处理。
您将在您的 Ubuntu 虚拟机上完成本实验。按照以下步骤开始:
- 关闭你的 Ubuntu 虚拟机并创建一个快照。备份引导后,通过使用以下命令查看 iptables 规则或缺少规则的情况:
sudo iptables -L
- 创建基本防火墙所需的规则,允许安全外壳访问、DNS 查询和区域传输以及适当类型的 ICMP。否认其他一切:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport ssh -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 3 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 11 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -m conntrack -p icmp --icmp-type 12 --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -j DROP
- 使用以下命令查看结果:
sudo iptables -L
- 哎呀–看起来您忘记了那个环回接口。在列表顶部为其添加规则:
sudo iptables -I INPUT 1 -i lo -j ACCEPT
- 使用以下两个命令查看结果。注意每个输出之间的差异:
sudo iptables -L
sudo iptables -L -v
- 安装
iptables-persistent
包,出现提示时选择保存 IPv4 和 IPv6 规则:
sudo apt install iptables-persistent
- 重新启动虚拟机,并验证您的规则仍然有效。
- 保留此虚拟机;在下一个实践实验中,您将添加更多内容。
本实验到此结束—祝贺您!
如果你在信息技术行业已经工作了很长时间,你很可能已经熟悉了传统的 TCP 三次握手。如果你不是,别担心。下面是简单的解释。
假设你坐在你的工作站上,你拉起火狐来访问一个网站。要访问该网站,您的工作站和 web 服务器必须建立连接。事情是这样的:
- 您的工作站向网络服务器发送仅设置了
SYN
标志的数据包。这是你的工作站说“你好,服务器先生”的方式。我想和你建立联系。” - 收到工作站的
SYN
包后,网络服务器发回一个设置了SYN
和ACK
标志的包。有了这个,服务器说,“是啊,兄弟。我在这里,我愿意和你联系。” - 收到
SYN-ACK
数据包后,工作站发回一个仅设置了ACK
标志的数据包。有了这个,工作站说,“酷交易,伙计。我很高兴和你联系。” - 收到
ACK
数据包后,服务器建立与工作站的连接,以便它们可以交换信息。
该序列的工作方式与设置任何类型的 TCP 连接相同。这包括涉及安全外壳、远程登录和各种邮件服务器协议等的连接。
然而,聪明的人可以使用各种工具用一些非常奇怪的标志组合来制作 TCP 数据包。有了这些所谓的无效数据包,可能会发生一些事情:
- 无效数据包可用于从目标机器引出响应,以找出它运行的是什么操作系统,运行的是什么服务,以及运行的是什么版本的服务。
- 无效数据包可用于触发目标机器上的某些安全漏洞。
- 其中一些无效数据包需要比正常数据包更多的处理能力,这可能使它们对执行 DoS 攻击有用。
现在,事实上,过滤器表的INPUT
链末端的DROP all
规则将阻止这些无效数据包中的一些。然而,这条规则可能会遗漏一些东西。即使我们可以指望它来阻止所有无效的东西,这仍然不是最有效的做事方式。依靠这个DROP all
规则,我们允许这些无效的数据包通过整个INPUT
链,寻找一个规则让它们通过。当没有为他们找到ALLOW
规则时,他们最终会被DROP all
规则所阻止,这是链条中的最后一条规则。那么,如果我们能找到一个更有效的解决方案呢?
理想情况下,我们希望在这些无效数据包通过整个INPUT
链之前阻止它们。我们可以用PREROUTING
链来实现,但是过滤表没有PREROUTING
链。因此,我们需要使用轧台的PREROUTING
链条来代替。让我们从添加这两条规则开始:
donnie@ubuntu:~$ sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
[sudo] password for donnie:
donnie@ubuntu:~$ sudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
donnie@ubuntu:~$
这些规则中的第一条将阻止大多数我们认为无效的*。然而,它仍然错过了一些东西。因此,我们增加了第二个规则,它会阻止所有不是SYN
数据包的NEW
数据包。现在,让我们看看我们有什么:*
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
嗯(表示踌躇等)...
我们看不到我们的新规则,是吗?这是因为,默认情况下,iptables -L
只显示过滤器表的规则。我们需要看到我们刚刚放入轧轧台的东西,所以让我们这样做:
donnie@ubuntu:~$ sudo iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
DROP all -- anywhere anywhere ctstate INVALID
DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN ctstate NEW
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
在这里,我们使用了-t mangle
选项来表示我们想要查看 mangle 表的配置。您可能已经注意到了一些非常奇怪的事情,iptables 是如何呈现由sudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
命令创建的规则的。出于某种原因,它呈现如下:
DROP tcp -- anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN ctstate NEW
这看起来很奇怪,但不要让它影响你。这仍然意味着它正在阻止不是SYN
数据包的NEW
数据包。
之前,我提到 iptables-persistent 包不会保存对 iptables 规则的后续更改。因此,就目前的情况来看,我们刚刚添加的破坏表规则将在我重新启动虚拟机后消失。为了使这些更改永久化,我将使用iptables-save
命令在我自己的主目录中保存一个新文件。然后,我将文件复制到/etc/iptables
目录,替换原来的文件:
donnie@ubuntu:~$ sudo iptables-save > rules.v4
[sudo] password for donnie:
donnie@ubuntu:~$ sudo cp rules.v4 /etc/iptables/
donnie@ubuntu:~$
为了测试这一点,我们将使用一个叫做 Nmap 的便利实用程序。这是一个免费的实用程序,你可以安装在你的 Windows、Mac 或 Linux 工作站上。或者,如果您不想在您的主机上安装它,您可以在您的一个 Linux 虚拟机上安装它。它在 Debian/Ubuntu、RHEL/CentOS 7 和 RHEL/CentOS 8 的普通存储库中。因此,只需使用适合您的发行版的安装命令来安装 Nmap 包。如果你想在你的 Windows 或 Mac 主机上安装 Nmap,你需要从 Nmap 网站下载。
You can download Nmap from the official website, which can be found here: https://nmap.org/download.html.
有了新的破坏表规则,让我们对 Ubuntu 机器进行一次 XMAS 扫描。我在我目前使用的 Fedora 工作站上安装了 Nmap,所以我现在就用这个。我可以这样做:
[donnie@fedora-teaching ~]$ sudo nmap -sX 192.168.0.15
[sudo] password for donnie:
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-26 21:20 EDT
Nmap scan report for 192.168.0.15
Host is up (0.00052s latency).
All 1000 scanned ports on 192.168.0.15 are open|filtered
MAC Address: 08:00:27:A4:95:1A (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 21.41 seconds
[donnie@fedora-teaching ~]$
默认情况下,Nmap 只扫描最常用的 1000 个端口。XMAS 扫描发送由 FIN、PSH 和 URG 标志组成的无效数据包。1000 个扫描端口全部显示为open|filtered
意味着扫描被阻止,Nmap 无法确定端口的真实状态。(现实中22
口是开着的。)我们可以查看结果,看看哪个规则执行了阻塞。(为了简化一点,我将只显示PREROUTING
链的输出,因为它是唯一一个可以做任何事情的破坏表链):
donnie@ubuntu:~$ sudo iptables -t mangle -L -v
Chain PREROUTING (policy ACCEPT 2898 packets, 434K bytes)
pkts bytes target prot opt in out source destination
2000 80000 DROP all -- any any anywhere anywhere ctstate INVALID
0 0 DROP tcp -- any any anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN ctstate NEW
. . .
. . .
donnie@ubuntu:~$
在这里,你可以看到第一个规则——第INVALID
规则——阻塞了 2000 个数据包和 80000 个字节。现在,让我们将计数器归零,以便进行另一次扫描:
donnie@ubuntu:~$ sudo iptables -t mangle -Z
donnie@ubuntu:~$ sudo iptables -t mangle -L -v
Chain PREROUTING (policy ACCEPT 22 packets, 2296 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- any any anywhere anywhere ctstate INVALID
0 0 DROP tcp -- any any anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN ctstate NEW
. . .
. . .
donnie@ubuntu:~$
这次我们来做一个Window
扫描,用ACK
包轰击目标机:
[donnie@fedora-teaching ~]$ sudo nmap -sW 192.168.0.15
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-26 21:39 EDT
Nmap scan report for 192.168.0.15
Host is up (0.00049s latency).
All 1000 scanned ports on 192.168.0.15 are filtered
MAC Address: 08:00:27:A4:95:1A (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 21.44 seconds
[donnie@fedora-teaching ~]$
和以前一样,扫描被阻止,消息显示所有 1,000 个扫描的端口都已被过滤。现在,让我们看看我们在目标 Ubuntu 机器上有什么:
donnie@ubuntu:~$ sudo iptables -t mangle -L -v
Chain PREROUTING (policy ACCEPT 45 packets, 6398 bytes)
pkts bytes target prot opt in out source destination
0 0 DROP all -- any any anywhere anywhere ctstate INVALID
2000 80000 DROP tcp -- any any anywhere anywhere tcp flags:!FIN,SYN,RST,ACK/SYN ctstate NEW
. . .
. . .
donnie@ubuntu:~$
这一次,我们可以看到我们的无效数据包通过了第一个规则,但被第二个规则阻止了。
现在,只是为了好玩,让我们清除混乱的表格规则,再次进行扫描。我们将使用-D
选项从损坏表中删除两个规则:
donnie@ubuntu:~$ sudo iptables -t mangle -D PREROUTING 1
donnie@ubuntu:~$ sudo iptables -t mangle -D PREROUTING 1
donnie@ubuntu:~$
删除规则时,必须指定规则编号,就像插入规则一样。这里,我指定了规则 1 两次,因为删除第一个规则会将第二个规则移到第一位。现在,让我们验证这些规则是否已经消失:
donnie@ubuntu:~$ sudo iptables -t mangle -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
. . .
. . .
donnie@ubuntu:~$
是的,他们是。酷。现在,让我们看看当我们执行另一个 XMAS 扫描时会得到什么:
[donnie@fedora-teaching ~]$ sudo nmap -sX 192.168.0.15
[sudo] password for donnie:
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-26 21:48 EDT
Nmap scan report for 192.168.0.15
Host is up (0.00043s latency).
All 1000 scanned ports on 192.168.0.15 are open|filtered
MAC Address: 08:00:27:A4:95:1A (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 21.41 seconds
[donnie@fedora-teaching ~]$
即使没有 mangle 表规则,它也表明我的扫描仍然被阻止。这是怎么回事?这是因为我在 INPUT 表的末尾还有DROP all
规则。让我们禁用它,看看我们在另一次扫描中得到什么。
首先,我需要了解规则编号:
donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
DROP all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
倒计时,我可以看到这是规则 4,所以我将删除它:
donnie@ubuntu:~$ sudo iptables -D INPUT 4
donnie@ubuntu:~$donnie@ubuntu:~$ sudo iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
donnie@ubuntu:~$
现在,对于 XMAS 扫描:
[donnie@fedora-teaching ~]$ sudo nmap -sX 192.168.0.15
Starting Nmap 7.70 ( https://nmap.org ) at 2019-07-26 21:49 EDT
Nmap scan report for 192.168.0.15
Host is up (0.00047s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
22/tcp open|filtered ssh
MAC Address: 08:00:27:A4:95:1A (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 98.76 seconds
[donnie@fedora-teaching ~]$
这一次,扫描显示 999 个端口关闭,SSH 端口22
打开或过滤。这表明扫描不再被任何东西阻挡。
当我使用iptables -D
命令时,我只从运行时配置中删除了规则,而没有从rules.v4
配置文件中删除。要恢复我删除的规则,我可以重新启动计算机或重新启动 netfilter-persistent 服务。后一种选择更快,所以我将用下面的代码激活它:
donnie@ubuntu:~$ sudo systemctl restart netfilter-persistent
[sudo] password for donnie:
donnie@ubuntu:~$
iptables -L
和iptables -t mangle -L
命令将显示所有规则现在都恢复生效。
在本实验中,您将使用与上一实验相同的虚拟机。你不会取代任何你已经有的规则。相反,你只需要添加几个。让我们开始吧:
- 看看过滤器和破坏表的规则。(请注意,
-v
选项向您显示被丢弃和拒绝规则阻止的数据包的统计信息。)然后,清零阻塞数据包计数器:
sudo iptables -L -v
sudo iptables -t mangle -L -v
sudo iptables -Z
sudo iptables -t mangle -Z
- 从您的主机或其他虚拟机,对虚拟机执行空和 Windows Nmap 扫描:
sudo nmap -sN ip_address_of_your_VM
sudo nmap -sW ip_address_of_your_VM
- 重复步骤 1 。您应该会看到过滤器表的
INPUT
链中被最终DROP
规则阻止的数据包数量大幅增加:
sudo iptables -L -v
sudo iptables -t mangle -L -v
- 通过使用 mangle 表的
PREROUTING
链来丢弃无效数据包,例如我们刚刚执行的两次 Nmap 扫描产生的数据包,使防火墙更有效地工作。使用以下两个命令添加两个必需的规则:
sudo iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
sudo iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
- 将新配置保存到您自己的主目录中。然后,将文件复制到正确的位置,并清空被阻止的数据包计数器:
sudo iptables-save > rules.v4
sudo cp rules.v4 /etc/iptables
sudo iptables -Z
sudo iptables -t mangle -Z
- 仅对虚拟机执行空扫描:
sudo nmap -sN ip_address_of_your_VM
- 查看 iptables 规则集,观察哪个规则是由 Nmap 扫描触发的:
sudo iptables -L -v
sudo iptables -t mangle -L -v
- 这一次,仅对虚拟机执行 Windows 扫描:
sudo nmap -sW ip_address_of_your_VM
- 观察此扫描触发了哪个规则:
sudo iptables -L -v
sudo iptables -t mangle -L -v
本实验到此结束—祝贺您!
我知道,你已经习惯了所有基于 IPv4 的网络,它的 IP 地址很好,很短,很容易使用。然而,考虑到世界现在没有新的 IPv4 地址,这不可能永远持续下去。IPv6 提供了更大的地址空间,这将持续很长一段时间。一些组织,尤其是无线运营商,要么正在切换到 IPv6,要么已经切换到 IPv6。
到目前为止,我们只讨论了如何使用 iptables 设置 IPv4 防火墙。但是记住我们之前说过的话。使用 iptables,您需要一个守护进程和一组规则用于 IPv4 网络,另一个守护进程和一组规则用于 IPv6。这意味着在使用 iptables 设置防火墙时,保护 IPv6 意味着每件事都要做两次。大多数 Linux 发行版都默认启用了 IPv6 网络,因此您需要用防火墙保护它或者禁用它。否则,您的 IPv6 地址仍然会受到攻击,因为您刚刚配置的 IPv4 防火墙不会保护它。即使您的服务器或设备面向 IPv4 互联网,也是如此,因为有多种方法可以通过 IPv4 网络隧道传输 IPv6 数据包。幸运的是,设置 IPv6 防火墙的命令与我们刚刚介绍的基本相同。最大的区别是不用iptables
命令,而是用ip6tables
命令。让我们从基本设置开始,就像我们对 IPv4 所做的那样:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -i lo -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p tcp --dport ssh -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p tcp --dport 53 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p udp --dport 53 -j ACCEPT
IPv4 和 IPv6 的另一个很大的区别是,对于 IPv6,您必须允许比 IPv4 更多类型的 ICMP 消息。这是由于以下原因:
- 有了 IPv6,新类型的 ICMP 消息已经取代了地址解析协议 ( ARP )。
- 对于 IPv6,动态 IP 地址分配通常是通过与其他主机交换 ICMP 发现消息来完成的,而不是通过 DHCP。
- 对于 IPv6,当您需要通过 IPv4 网络隧道传输 IPv6 数据包时,需要回声请求和回声回复,即臭名昭著的 ping 数据包。
当然,我们仍然需要与 IPv4 相同类型的 ICMP 消息。所以,让我们从他们开始:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 1 -j ACCEPT
[sudo] password for donnie:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 2 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 3 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 4 -j ACCEPT
donnie@ubuntu3:~$
这些消息类型按出现顺序如下:
- 无法到达目的地
- 数据包太大
- 超过时间
- 数据包报头的参数问题
接下来,我们将启用回送请求(类型 128)和回送响应(类型 129),以便 IPv6 在 IPv4 隧道上工作:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 129 -j ACCEPT
donnie@ubuntu3:~$
The Teredo protocol is one of a few different ways to tunnel IPv6 packets across an IPv4 network. This protocol is what requires echo requests and echo replies, the infamous ping packets, to be allowed through a firewall. However, if you search through your distro repositories for a Teredo package, you won't find it. That's because the Linux implementation of the Teredo protocol is called miredo. So, when installing the Teredo protocol on a Linux machine, you'll need to install the miredo
and miredo-server
packages.
接下来我们需要的四种 ICMP 消息类型是链路本地多播接收器通知消息:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 130
donnie@ubuntu3:~$ sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 131
donnie@ubuntu3:~$ sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 132
donnie@ubuntu3:~$ sudo ip6tables -A INPUT --protocol icmpv6 --icmpv6-type 143
donnie@ubuntu3:~$
按外观顺序排列如下:
- 侦听器查询
- 听众报告
- 监听器完成
- 侦听器报告 v2
接下来是邻居和路由器发现消息类型:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 134 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 135 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 136 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 141 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 142 -j ACCEPT
donnie@ubuntu3:~$
按外观顺序排列如下:
- 路由器招标
- 路由器广告
- 邻居恳求
- 邻居广告
- 反向邻居发现请求
- 反向邻居发现广告
篇幅不允许我详细介绍这些消息类型。所以,现在,让我们假设,为了让 IPv6 主机动态地为自己分配一个 IPv6 地址,它们是必需的。
当您使用安全证书验证连接到网络的路由器时,您还需要允许安全邻居发现 ( 发送)消息:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 148 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 149 -j ACCEPT
donnie@ubuntu3:~$
你的手指累了吗?如果是这样,不要害怕。下一组 ICMP 规则是最后一组。这一次,我们需要允许多播路由器发现消息:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 151 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 152 -j ACCEPT
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -p icmpv6 --icmpv6-type 153 -j ACCEPT
donnie@ubuntu3:~$
最后,我们将添加我们的DROP
规则来阻止其他一切:
donnie@ubuntu3:~$ sudo ip6tables -A INPUT -j DROP
donnie@ubuntu3:~$
现在,我知道你在想,哇,仅仅为了建立一个基本的防火墙*,就要跳过很多的障碍。*是的,你是对的,尤其是当你还需要为 IPv6 配置规则的时候。很快,我将向您展示 Ubuntu 人想出了什么让事情变得更简单。
You can get the whole scoop on how to use iptables on Ubuntu here: https://help.ubuntu.com/community/IptablesHowTo.
在本实验中,您将使用与之前 iptables 实验中相同的 Ubuntu 虚拟机。您将保留现有的 IPv4 防火墙设置,并为 IPv6 创建一个新的防火墙。让我们开始吧:
- 使用以下命令查看您的 IPv6 规则或缺少规则:
sudo ip6tables -L
- 创建 IPv6 防火墙。由于格式限制,我无法在此列出整个命令代码块。您可以在本章的目录中找到相应的命令,这些命令位于您可以从 Packt Publishing 网站下载的代码文件中。
- 使用以下命令查看新规则集:
sudo ip6tables -L
- 接下来,设置阻塞无效数据包的破坏表规则:
sudo ip6tables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP
sudo ip6tables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP
- 将新规则集保存到您自己的主目录中的文件,然后将规则文件传输到适当的位置:
sudo ip6tables-save > rules.v6
sudo cp rules.v6 /etc/iptables/
- 使用以下命令获取虚拟机的 IPv6 地址:
ip a
- 在安装了 Nmap 的计算机上,对虚拟机的 IPv6 地址执行 Windows 扫描。除了您自己的 IP 地址之外,该命令将如下所示:
sudo nmap -6 -sW fe80::a00:27ff:fe9f:d923
- 在虚拟机上,使用以下命令观察触发了哪个规则:
sudo ip6tables -t mangle -L -v
您应该看到其中一个规则的数据包计数器的非零数字。
- 在安装了 Nmap 的计算机上,对虚拟机的 IPv6 地址执行 XMAS 扫描。除了您自己的 IP 地址之外,该命令将如下所示:
sudo nmap -6 -sX fe80::a00:27ff:fe9f:d923
- 像以前一样,在虚拟机上,观察此扫描触发了哪个规则:
sudo ip6tables -t mangle -L -v
本实验到此结束–祝贺您!
到目前为止,你已经看到了 iptables 的好的、坏的和丑陋的一面。它非常灵活,iptables 命令中有很多功能。如果你擅长 shell 脚本,你可以创建一些相当复杂的 shell 脚本,用来在网络上的所有机器上部署 firewalld。
另一方面,做好每一件事可能相当复杂,尤其是如果您需要考虑您的机器必须同时运行 IPv4 和 IPv6,并且您为 IPv4 做的每一件事都必须再次为 IPv6 做。(如果你是受虐狂,你可能真的很享受。)
ufw 已经安装在 Ubuntu 16.04 和 Ubuntu 18.04 上。它仍然使用 iptables 服务,但它提供了一组大大简化的命令集。只需执行一个简单的命令来打开所需的端口,并执行另一个简单的命令来激活它,您就拥有了一个良好的基本防火墙。每当您执行ufw
命令时,它将自动配置 IPv4 和 IPv6 规则。光是这一点就能节省大量时间,默认情况下,我们已经用 iptables 手工配置了很多东西。
有一个图形前端,您可以在桌面计算机上使用,但是由于我们正在学习服务器安全性,我们将只在这里介绍命令行实用程序。
ufw is available for Debian, and other Debian-based distros, but it might not be installed. If that's the case, install it by using the sudo apt install ufw
command.
在 Ubuntu 18.04 和更高版本上,默认情况下已经启用了 ufw 系统服务,但是没有激活。换句话说,系统的服务正在运行,但它还没有执行任何防火墙规则。(在我们了解了如何打开您需要打开的端口之后,我将稍后向您展示如何激活它。)在其他 Linux 发行版上,例如旧的 Ubuntu 16.04,您可能会发现默认情况下 ufw 是禁用的。如果是这种情况,您需要启用它,如下所示:
sudo systemctl enable --now ufw
我们要做的第一件事是打开端口22
让它通过 Secure Shell 连接到机器,就像这样:
sudo ufw allow 22/tcp
通过使用sudo iptables -L
,您将看到新规则出现在ufw-user-input
链中:
Chain ufw-user-input (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
您还会看到这个命令的总输出相当长,因为我们用 iptables 做的很多事情已经用 ufw 完成了。事实上,这里有比我们用 iptables 做的更多的东西。例如,对于 ufw,我们已经有了速率限制规则来帮助保护我们免受 DoS 攻击,我们也有了记录关于已被阻止的数据包的日志消息的规则。这几乎是不大惊小怪,没有设置防火墙的混乱方式。(我一会儿就讲到差不多的部分。)
在前面的sudo ufw allow 22/tcp
命令中,我们必须指定 TCP 协议,因为 TCP 是我们安全外壳所需要的。我们也可以通过不指定协议来同时为 TCP 和 UDP 打开一个端口。例如,如果您正在设置一个 DNS 服务器,您将希望为两种协议打开端口53
(您将看到端口53
的条目被列为域端口):
sudo ufw allow 53
Chain ufw-user-input (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:domain
ACCEPT udp -- anywhere anywhere udp dpt:domain
如果您使用sudo ip6tables -L
,您将会看到前面两个示例都添加了 IPv6 规则。同样,您会看到我们对 ip6tables 命令所做的大部分工作已经得到了解决。(尤其令人高兴的是,我们不必为设置所有那些讨厌的 ICMP 规则而伤脑筋。)
现在我们已经打开了所需的端口,我们将激活ufw
,这样它将实际执行这些规则:
sudo ufw enable
要查看防火墙配置的快速摘要,请使用status
选项。输出应该如下所示:
donnie@ubuntu-ufw:~$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp LIMIT Anywhere
53 LIMIT Anywhere
22/tcp (v6) LIMIT Anywhere (v6)
53 (v6) LIMIT Anywhere (v6)
donnie@ubuntu-ufw:~$
接下来,我们将看看 ufw 防火墙文件。
可以在/etc/ufw
目录中找到 ufw 防火墙规则。如您所见,规则存储在几个不同的文件中:
donnie@ubuntu-ufw:/etc/ufw$ ls -l
total 48
-rw-r----- 1 root root 915 Aug 7 15:23 after6.rules
-rw-r----- 1 root root 1126 Jul 31 14:31 after.init
-rw-r----- 1 root root 1004 Aug 7 15:23 after.rules
drwxr-xr-x 3 root root 4096 Aug 7 16:45 applications.d
-rw-r----- 1 root root 6700 Mar 25 17:14 before6.rules
-rw-r----- 1 root root 1130 Jul 31 14:31 before.init
-rw-r----- 1 root root 3467 Aug 11 11:36 before.rules
-rw-r--r-- 1 root root 1391 Aug 15 2017 sysctl.conf
-rw-r--r-- 1 root root 313 Aug 11 11:37 ufw.conf
-rw-r----- 1 root root 3014 Aug 11 11:37 user6.rules
-rw-r----- 1 root root 3012 Aug 11 11:37 user.rules
donnie@ubuntu-ufw:/etc/ufw$
在列表的底部,你会看到user6.rules
和user.rules
文件。这两个文件你都不能手动编辑。您可以在完成编辑后保存文件,但是当您使用sudo ufw reload
加载新的更改时,您会看到您的编辑已被删除。让我们看看user.rules
文件,看看我们能在那里看到什么。
在文件的顶部,您将看到 iptables 过滤器表的定义,以及相关链的列表:
*filter
:ufw-user-input - [0:0]
:ufw-user-output - [0:0]
:ufw-user-forward - [0:0]
. . .
. . .
接下来,在### RULES ###
部分,我们有了用ufw
命令创建的规则列表。以下是我们打开域名系统端口的规则:
### tuple ### allow any 53 0.0.0.0/0 any 0.0.0.0/0 in
-A ufw-user-input -p tcp --dport 53 -j ACCEPT
-A ufw-user-input -p udp --dport 53 -j ACCEPT
如你所见,ufw 的核心其实只是 iptables。
在### RULES ###
部分下面,我们可以看到防火墙阻止的任何数据包的日志记录规则:
### LOGGING ###
-A ufw-after-logging-input -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-A ufw-after-logging-forward -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-I ufw-logging-deny -m conntrack --ctstate INVALID -j RETURN -m limit --limit 3/min --limit-burst 10
-A ufw-logging-deny -j LOG --log-prefix "[UFW BLOCK] " -m limit --limit 3/min --limit-burst 10
-A ufw-logging-allow -j LOG --log-prefix "[UFW ALLOW] " -m limit --limit 3/min --limit-burst 10
### END LOGGING ###
这些信息被发送到/var/log/kern.log
文件。为了在大量数据包被阻止时不会淹没日志记录系统,我们每分钟只向日志文件发送三条消息,突发速率为每分钟 10 条消息。这些规则中的大多数都会在日志消息中插入一个[UFW BLOCK]
标签,这使得我们很容易找到它们。最后一个规则创建带有[UFW ALLOW]
标签的消息,奇怪的是,INVALID
规则没有插入任何类型的标签。
最后,我们有速率限制规则,每分钟每个用户只允许三个连接:
### RATE LIMITING ###
-A ufw-user-limit -m limit --limit 3/minute -j LOG --log-prefix "[UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT
-A ufw-user-limit-accept -j ACCEPT
### END RATE LIMITING ###
任何超过该限制的数据包都将被记录在带有[UFW LIMIT BLOCK]
标签的/var/log/kern.log
文件中。
/etc/ufw user6.rules
文件看起来几乎一样,只是它是针对 IPv6 规则的。任何时候使用ufw
命令创建或删除规则,它都会修改user.rules
文件和user6.rules
文件。
为了将在规则之前运行的规则存储在user.rules
和user6.rules
文件中,我们有before.rules
文件和before6.rules
文件。为了在user.rules
和user6.rules
文件中存储在规则之后运行的规则,我们有after.rules
文件和after6.rules
文件,你猜对了。如果需要添加无法通过ufw
命令添加的自定义规则,只需手动编辑其中一对文件即可。(我们一会儿就会谈到这一点。)
如果你看一下before
和after
文件,你会发现哪里已经为我们处理了这么多。这就是我们用 iptables/ip6tables 手工做的所有事情。
然而,你可能知道,所有这些美好的事物都有一个小小的警告。您可以使用 ufw 实用程序执行简单的任务,但是任何更复杂的任务都需要您手工编辑文件。(这就是我说 ufw 几乎没有大惊小怪,没有混乱的意思。)例如,在before
文件中,您会看到已经实现了阻止无效数据包的规则之一。以下是before.rules
文件的代码片段,您可以在文件顶部找到:
# drop INVALID packets (logs these in loglevel medium and higher)
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
这两个规则中的第二个实际上丢弃了无效数据包,第一个规则记录它们。但是正如我们已经在iptables概述部分看到的,这个特殊的DROP
规则不会阻止所有的无效数据包。而且,出于性能原因,我们更希望将此规则放在 mangle 表中,而不是现在的 filter 表中。为了解决这个问题,我们将编辑两个before
文件。在您最喜欢的文本编辑器中打开/etc/ufw/before.rules
文件,并在文件的最底部查找以下一对行:
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT
就在COMMIT
行下面,添加以下代码片段来创建损坏表规则:
# Mangle table added by Donnie
*mangle
:PREROUTING ACCEPT [0:0]
-A PREROUTING -m conntrack --ctstate INVALID -j DROP
-A PREROUTING -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j DROP
COMMIT
现在,我们将对/etc/ufw/before6.rules
文件重复这个过程。然后,我们将使用以下命令重新加载规则:
sudo ufw reload
通过使用iptables -L
和ip6tables -L
命令,您将看到新的规则出现在 mangle 表中,就在我们希望它们出现的地方。
您需要在您的 Ubuntu 虚拟机的干净快照上完成本实验。让我们开始吧:
- 关闭你的 Ubuntu 虚拟机,恢复快照,去掉你刚才做的所有 iptables 的东西。(或者,如果您愿意,可以从一个新的虚拟机开始。)
- 重新启动虚拟机后,验证 iptables 规则现在是否已消失:
sudo iptables -L
- 查看
ufw
的状态。打开端口22/TCP
,然后启用ufw
。然后,查看结果:
sudo ufw status
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status
sudo iptables -L
sudo ip6tables -L
- 这次,为 TCP 和 UDP 都打开端口
53
:
sudo ufw allow 53
sudo iptables -L
sudo ip6tables -L
sudo ufw status
cd
进入/etc/ufw
目录。熟悉那里文件的内容。- 在你喜欢的文本编辑器中打开
/etc/ufw/before.rules
文件。在文件底部的COMMIT
行下方,添加以下代码片段:
# Mangle table added by Donnie
*mangle
:PREROUTING ACCEPT [0:0]
-A PREROUTING -m conntrack --ctstate INVALID -j DROP
-A PREROUTING -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate
NEW -j DROP
COMMIT
- 对
/etc/ufw/before6.rules
文件重复步骤 6 。 - 使用以下命令重新加载防火墙:
sudo ufw reload
- 使用以下命令遵守规则:
sudo iptables -L
sudo iptables -t mangle -L
sudo ip6tables -L
sudo ip6tables -t mangle -L
- 快速查看
ufw
状态:
sudo ufw status
实验到此结束,祝贺你!
尽管 ufw 很酷,但它仍然使用老式的 iptables 技术作为核心引擎。有没有更现代的东西我们可以代替使用?没错,我们将在下一章讨论这个问题。
在本章中,我们看了 netfilter 防火墙的四个不同前端中的两个。首先,我们看了我们信任的老朋友,iptables。我们看到,尽管它已经存在了很长时间,并且仍然有效,但它确实有一些缺点。然后,我们看到了 Ubuntu 的简单防火墙如何极大地简化了基于 iptables 的防火墙的设置。
在分配给本章的篇幅中,我只介绍了设置基本主机保护所需的要点。然而,这应该足以让你开始。
在下一章中,我们将看看 nftables 和 firewalld,这两个最新的 netfilter 接口。到时候见。
- 以下哪个陈述是正确的? A. iptables 是最容易使用的防火墙系统。 B .使用 iptables,您创建的任何规则都适用于 IPv4 和 IPv6。 C .使用 iptables,您必须独立于 IPv4 规则创建 IPv6 规则。 D .使用 ufw,您必须单独创建 IPv6 规则和 IPv4 规则。
- Linux 防火墙的官方名称是什么? a . iptables b . ufw c . nftables d .网络过滤器
- 有了 ufw,你需要做的一切都可以通过 ufw 实用程序来完成。 A .真 B .假
- 您会使用哪个 iptables 命令来查看特定规则丢弃了多少数据包?
- 您会使用以下哪个 ufw 命令来打开默认的安全外壳端口?
a .
sudo ufw allow 22
T5】b .sudo ufw permit 22
T6】c .sudo ufw allow 22/tcp
T7】d .sudo ufw permit 22/tcp
- 在 iptables 中,以下哪个目标会导致数据包被阻止而不向源发送回通知?
a .
STOP
T5】b .DROP
T6】c .REJECT
T7】d .BLOCK
- 以下六个选项中的哪一个是 iptables 中的表格? A .网络过滤器 B .过滤器 C .撕裂 D .安全 E. ip6table F. NAT
- 25 iptables netfilter 防火墙示例:https://www.cyberciti.biz/tips/linux-iptables-examples.html
- Linux IPv6 操作指南:http://tldp.org/HOWTO/html_single/Linux+IPv6-HOWTO/
- 在防火墙中过滤 ICMPv6 消息的建议:https://www.ietf.org/rfc/rfc4890.txt
- ufw 限速:https://45squared.com/rate-limiting-with-ufw/
- UFW 社区帮助维基:https://help.ubuntu.com/community/UFW
- 如何在 Ubuntu 18.04 上设置带有 UFW 的 Linux 防火墙:https://linuxize . com/post/如何设置带有 ubuntu-18-04 上的 ufw 的防火墙/*