原文:Pro linux system administration
协议:CC BY-NC-SA 4.0
七、网络和防火墙
到目前为止,我们已经向您展示了 Linux 的一些基本特性,但是最重要的特性之一是联网。通过网络,您的主机可以与其他主机通信,您的应用程序可以与您的用户和世界通信。在这一章中,我们将描述如何设置你的主机的网络,然后如何使用防火墙保护网络免受攻击者的攻击。
Note
防火墙是一系列控制通过网络访问主机的规则。
我们将教您如何配置您的网卡或接口,以及如何为它们分配 IP(互联网协议)地址。您将学习如何连接到其他网络,以及如何排除连接故障。
我们还将看到一个名为 Netfilter 的软件应用程序,它是所有 Linux 发行版通用的防火墙。您将学习如何管理防火墙以及如何编写防火墙规则。为此,我们将向您介绍 Netfilter 的管理界面iptables
。我们还将向您展示如何使用 iptables 工具,如 Firewalld 和 ufw。最后,我们还将向您展示如何使用 TCP Wrappers 来保护在您的主机上运行的守护进程,然后使用 Linux 建立到 ISP (Internet 服务提供商)的 PPPOE(以太网点对点协议)连接。
在本章中,我们将使用网络术语。我们不指望你是一个网络专家,但我们已经假定你有一些基本的知识。如果您觉得自己了解的还不够,我们建议您查看以下网站和教程:
www.tutorialspoint.com/ipv4/
www.tutorialspoint.com/ipv6/
http://ipv6.com/articles/general/ipv6-the-next-generation-internet.htm
http://en.wikipedia.org/wiki/TCP/IP
Note
iptables
用于保护您的网络服务。在第九章中,你会学到更多关于如何在你的主机上运行 DNS(域名系统)和 DHCP(动态主机配置协议)等网络服务的知识。
网络和网络简介
网络由硬件和软件组成。它们的复杂程度取决于它们的大小和所需的互联程度。在小企业中,你可能会有一个简单的网络。您可能有一个 web 服务器和邮件服务器,也可能有一个文件/打印服务器(有时所有这些服务器实际上是一台主机)。毫无疑问,您将连接到互联网,并且您可能希望与您组织中的其他人共享该连接。
你的业务性质和你所做的工作将在很大程度上决定你如何选择建立你的网络。如今,许多企业充分利用 SaaS(软件即服务)提供商为他们提供某些业务功能,如电子邮件、文件存储和访问。这些企业可能有简单的网络要求。或者,刚起步的企业通常只有一台主服务器,几乎可以完成企业所需的所有功能。它可以是集 DHCP、DNS、文件、邮件和 web 服务器于一体的服务器。熟悉微软产品的人会认为这与 Windows Small Business Server 类似。但随着业务的增长,它可能会开始将这些组合功能转移到自己的主机上。很少有大型企业会将整个公司的 IT(信息技术)基础架构托付给一台承担如此多角色的主机。应该尽可能避免这种单点故障,但是小型企业很少有机会为其希望提供的每项服务配备一台主机。
Caution
如果您的业务确实存在单点故障,如一台主机上的许多服务,备份和恢复就变得至关重要。丢失数据对您的企业来说可能是一场灾难,因此您应该始终拥有备份以及恢复主机和数据的能力。有关如何为您的组织实施备份和恢复策略的详细信息,请参见第十三章。
然后是你可能需要的硬件的互连部分。如果您要将办公室中的用户连接到单个网络,您将需要电缆、配线架交换机,并且最有可能需要一个可以创建无线网络的无线接入点。
Caution
无线网络是扩展网络的一种有用而廉价的方式。它们不需要昂贵的布线和交换机,而且您的员工在办公室可以更加灵活。然而,它们也带来了一些挑战。众所周知,如果安全措施不当,无线网络会允许攻击者连接并嗅探您的网络,并且它们的性能不如有线网络(使用物理电缆的网络)。例如,通过有线连接传输大量数据仍然比通过无线连接快得多。如果您正在考虑为您的企业提供无线网络,我们建议您阅读位于 http://en.wikipedia.org/wiki/Wireless_security
、 https://www.fcc.gov/consumers/guides/protecting-your-wireless-network
和 https://www.communications.gov.au/what-we-do/internet/stay-smart-online/computers/secure-your-internet-connection
的信息。
我们将从解释如何在单台主机上配置网络开始,并向您介绍配置更广泛的网络所需的工具和命令。
为了向您展示如何配置网络,我们将使用我们创建的示例网络。你可以在图 7-1 中看到这个示例网络。
图 7-1。
Our example network
这是我们完整的网络图。到本章结束时,这个图表将不会像现在看起来那样令人生畏。我们将带您了解它的组件是什么,以及它们是如何配置的。我们还将解释所有这些 IP 地址的用途,以及我们如何能够阻止并从一个网络移动到另一个网络。
在本章中,我们将向您展示如何配置示例网络的元素。我们将配置一个名为gateway.example.com
的防火墙/路由器主机。它有多个 IP 地址,每个网络都有一个 IP 地址,充当路由器:我们内部网络上的 192.168.0.254,我们无线网络上的 192.168.1.254,以及外部 IP 地址 10.0.2.155。
我们还将配置一个名为headoffice.example.com
的主服务器。它在我们的内部网络上的 IP 地址将是 192.168.0.1。它将通过gateway.example.com
主机路由到其他网络,如我们的无线网络、分支机构和互联网。
如您所见,我们将网络划分为不同的网段,并选择了不同的网络地址来显示这一点。如前所述,我们的无线网络的网络地址为 192.168.1.0/24,由 IP 地址为 192.168.1.250 的无线接入点提供支持。
Note
有几种方法可以将 IP 地址分配给电脑。您可以手动配置它,允许它请求一个地址池中的随机 IP,并允许它请求一个它保证得到的分配的 IP 地址。对于像网络网关这样的重要 IP 地址,您应该总是手动配置它,或者确保它们总是接收一个已知的保证地址。当我们在第十章中讨论 DHCP 时,会详细讨论最后一个选项。
我们每个分公司都有一个独立的网络地址,其范围从 192.168.10.0/24 到 192.168.30.0/24。这为我们在每个分支办公室提供了 254 个可能的节点(或设备),如果需要,还可以扩展它们。
IP Addressing and Subnetting
在前面的例子中,我们看了像192.168.10.0/24
这样的 IPv4 网络。但是/24
是什么意思呢?
由于 IPv4 的地址空间有限,所以有必要保留 IP 地址,这就是将地址空间划分成更小的块或子网的想法的由来。IPv4 地址由 32 个二进制位组成。这些位被分成 4 个八位字节(1 个八位字节等于 8 位)。地址255.255.255.255
将被表示为11111111.11111111.11111111.11111111
–0.0.0.0
是00000000.00000000.00000000.00000000
。每个二进制八位数中的每个位置代表一个值,前导位置是 128,然后是 64,然后是 32,然后是 16,然后是 8,然后是 4,然后是 2,尾随位置是 1。如果你把所有这些值加在一起,它们等于 255。
网络地址由网络 ID 和主机组成。在192.168.10.0/24
的情况下,地址的前 24 位是网络 ID。它以二进制格式表示如下:
11000000.10101000.00001010
128+64.128+32+8.8+2
这样,最后一个二进制八位数可能有 254 个地址(不能使用 0 和 255,一个是全零地址(或基本网络地址),另一个是全 1 地址(或广播地址)——这些地址有特殊含义并被保留)。
因此,192.168.10.129/24
的 IPv4 地址将表示如下:
11000000.10101000.00001010.10000001
128+64.128+32+8.8+2.128+1
IPv6 的情况略有不同,但基本原理是相同的。你看到的每个地址字符实际上是 4 位。意味着这个本地链接地址fe80::a00:27ff:fea4:da6b/64
中的第一个字符(f
)实际上是二进制的1111
。每组四个字符代表 16 位(4x4 位),总共 80 位。完整的 IPv6 地址是 128 位。ISP 通常会根据您的要求提供/48 地址空间。这样就剩下 128 位,其中 48 位是可用地址空间,即 80 位。考虑到整个 IPv4 地址空间是 32 位,这是一个相当大的工作量。
这里还需要记住的是,每个 IPv6 都是全球可路由的,这与我们在 IPv4 示例中使用的私有地址空间不同,我们必须使用源网络地址转换(SNAT)将来自私有地址空间的连接路由到全球可路由的公共地址空间。在 IPv6 世界中,完整的 IPv6 地址由本地链接地址和网络地址组成,并且永远是唯一的。
作为一名使用 IPv6 的网络管理员,您将使用相同的二进制计算来确定您的 IPv6 子网划分,但是您可能的地址空间现在非常大!
我们还有一个本地有线网络,网络地址为 192.168.0.0/24。IP 地址为 192.168.0.1 的主服务器headoffice.example.com
将能够通过我们建立的从该主机到远程分支机构的 VPN 网络与分支机构通信(我们将在第十五章中解释 VPN)。
我们本地有线网络中的台式机被分配了一个地址池,可在 192 . 168 . 0 . 101–192 . 168 . 0 . 200 范围内使用。这允许 100 个节点,并且可以根据需要进行扩展。
实际上,对于这种规模的网络,我们可能会有更多的服务器,并且可能会通过将服务器放在分支办公室来分散服务器。然而,出于本章的目的,我们将专注于图 7-2 所示的场景,在该场景中,您可以看到我们已经将网络分解为一个更小的模块。
图 7-2。
The local wired network
在这里,我们可以集中精力为我们的办公室、gateway.example.com
和headoffice.example.com
构建主服务器。
我们将向您展示如何在gateway.example.com
主机上设置 PPPoE 连接,作为我们的 ISP 和互联网的防火墙/路由器主机。
Note
PPPoE 是一种用于从 ADSL 调制解调器连接到互联网的方法。
我们的主机headoffice.example.com
,将为公众提供邮件、网络和 DNS 服务(我们将在第十章、 11 章和 12 章中向您展示)。
我们将使用我们的gateway.example.com
防火墙主机接受来自互联网的流量,并通过我们的内部网络将其路由到我们的主主机。总部主机还将为我们的本地网络提供 DNS、DHCP、NTP(网络时间协议)、SMTP(简单邮件传输协议)、IMAP(互联网消息访问协议)、HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)服务。我们还将向您展示如何在我们的网络中将流量从一台主机路由到另一台主机。让我们从设置我们的界面开始。
界面入门
我们将向您介绍的第一个网络要素是接口,即网络接口。主机上的一个或多个网卡都将是一个网络接口。当我们在第二章中向您展示如何安装一个发行版并配置一个网络时,我们正在配置一个接口。
Tip
接口通常处于两种主要状态—开启和关闭。开启的接口处于活动状态,可用于接收网络流量。关闭的接口不会连接到网络。
您可以配置哪些类型的接口?现代计算机主机现在可以很容易地拥有一个以上的网卡(或网络接口),有时有数百个 IP 地址。一个接口可以有多个别名,或者您可以将两个或多个接口绑定或组合在一起,以显示为一个接口。
Linux 使您能够在一个接口上拥有多个 IP 地址。接口对所有 IP 地址使用相同的 Mac 地址。绑定或成组接口由两个或多个网络接口组成,显示为单个接口。这可用于为接口提供更高的容错能力或增加带宽。绑定接口也可以有许多 IP 地址。我们将在“CentOS 的网络配置文件”和“Ubuntu 的网络配置文件”部分对此进行进一步的阐述。
您的每个网络接口可能至少分配有一个 IP 地址。我们将从演示一个名为 ip 的简单工具开始介绍接口,该工具来自 iproute (CentOS)或 iproute2 (Ubuntu)包,可用于查看和更改接口的状态和配置。最简单形式的ip
工具可以像微软 Windows 上的ipconfig
命令一样使用。
命令是一个非常强大的工具,可以用来配置你所有的网络。ip
命令适用于不同的网络“对象”每个ip
对象处理你网络的一个特定部分。如果您键入ip help
,您将得到您可以管理的不同组件的列表。
在图 7-3 中,我们可以看到ip help
命令的输出,您可以看到我们可以使用它来配置我们网络堆栈的许多部分。ip
命令的基本语法如下:
图 7-3。
ip help command
ip [ OPTIONS ] OBJECT { COMMAND | help }
您将处理最常见的对象是link
、address
和route
。表 7-1 描述了该命令的这些和其余对象。
表 7-1。
Describing the Full List of Objects in the ip Command
| 目标 | 描述 | | --- | --- | | `link` | 该网络设备 | | `address` | 接口的地址(IPv4 或 IPv6) | | `addrlabel` | 允许您将标签应用于地址 | | `l2tp` | 基于 IP 的隧道以太网 | | `maddress` | 多播地址 | | `monitor` | Netlink 消息监控 | | `mroute` | 多播路由缓存条目 | | `mrule` | 管理多播路由策略中的规则 | | `neighbor` | ARP 或 NDISC 缓存条目 | | `netns` | 管理网络命名空间 | | `ntable` | 管理邻居缓存的操作 | | `route` | 路由表条目 | | `rule` | 路由策略数据库中的规则 | | `tcp_metrics` | 管理 tcp 指标 | | `tunnel` | IP 隧道 | | `tuntap` | 管理调谐器/TAP 设备 | | `xfrm` | 管理 IPSec 策略 |这些对象都有手册页来进一步描述它们的用途。例如,关于 ip 地址命令的更多信息可以通过输入$ man ip-address
找到。通过查看$ man ip
页面的 SEE ALSO 部分,您可以看到所有相应的手册页。
我们现在将向您展示如何使用ip
命令来发现有关您的网络接口的更多信息。要显示主机上所有接口的 IP 地址信息,我们使用以下命令:
$ ip address show
运行带有address show
选项的ip
命令会显示主机上的所有接口及其当前状态和配置。我们也可以使用简称ip addr show.
前面将列出所有主机接口及其地址。为了便于浏览特定接口的配置,您还可以显示单个接口,如下所示:
$ ip addr show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:a4:da:6b brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global enp0s3
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fea4:da6b/64 scope link
valid_lft forever preferred_lft forever
Listing 7-1.Status Output of ip addr show on an Active
Interface
第一行显示接口的状态。2:
只是一个订购号。enp0s3
是接口的设备名称。在< >之间是接口标志。BROADCAST
表示我们可以向链路上的所有其他主机发送流量,MULTICAST
表示我们可以发送和接收多播数据包,UP
表示设备正在运行。LOWER UP
表示电缆或底层链路已打开。
同样,我们还有其他一些信息。界面的状态当前为UP
。这意味着接口处于活动状态,如果配置正确,可能会接收流量。MTU
或最大传输单位,是网络上数据包的最大字节数;1500 是常见的默认值。qdisc pfifo_fast 是排队规程,它是数据如何被发送到网络的;这是先进先出,也是默认的。您还可以将接口组合在一起并对其执行操作;这说明我们的在默认组。最后,qlen 是以太网缓冲区传输队列长度,它可以被称为网卡的速度,在本例中为 1,000 mbits。
输出还显示了三条重要信息,即该主机的 ipv4 地址、ipv6 地址和 MAC(媒体访问控制)地址。它有一个分配给它的 IP 地址,inet 192.168.0.1
,我们很快会解释。下一行是 IPv6 地址,这里是inet6 fe80::a00:27ff:fea4:da6b/64
,这是从 MAC 地址派生的链路本地 IPv6 地址。每个以太网网卡都有一个唯一的硬件标识符,用于识别它并与其他以太网设备通信。这个 MAC 地址可以在输出的第一行看到(在这个例子中是link/ether 08:00:27:a4:da:6b
)。
Note
见 https://wiki.ubuntu.com/IPv6
or
www.internetsociety.org/deploy360/ipv6/basics/
for more information on IPv6
。
IPv6 地址可用于通过无状态地址自动配置(SLAAC)与其他主机通信。SLAAC 经常被 PDA 和移动电话等设备使用,它需要一个不太复杂的基础设施来与本地网络上的其他设备进行通信。这是因为每个 SLAAC IPv6 地址都是全球可路由的,并与网络地址结合在一起形成一个全球唯一的地址。
Note
有关无状态自动配置和 IPv6 的更多信息,请参见 http://www.ipv6.com/articles/general/Stateless-Auto-
Configuration.htm
。
在下一个示例中,我们将查看刚刚连接到主机的网络设备。此当前没有关联的 IP 地址:
$ ip addr show
3: enp0s8: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 08:00:27:13:3c:00 brd ff:ff:ff:ff:ff:ff
将其与我们之前的输出进行比较,您可以立即注意到状态为DOWN
,并且我们只能看到一个已经分配给网络设备enp0s8
的 MAC 地址。现在让我们看看当我们打开设备或链接时会发生什么。我们通过使用下面的ip link
子命令和ip addr show enp0s8
来完成:
$ sudo ip link set dev enp0s8 up
...
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:13:3c:00 brd ff:ff:ff:ff:ff:ff
inet6 fe80::a00:27ff:fe13:3c00/64 scope link
valid_lft forever preferred_lft forever
设备enp0s8
现在是UP
,并且已经分配了一个qdisc (pfifo_fast).
。有趣的是,我们还有一个 IPv6 生成的 IP 地址,该地址基于分配的 MAC 地址。
要关闭接口,您可以使用以下命令:
$ sudo ip link set dev enp0s8 down
您可以通过发出仅提供链接状态的以下命令来验证您所拥有的内容:
$ sudo ip link show enp0s8
3: enp0s8: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/ether 08:00:27:13:3c:00 brd ff:ff:ff:ff:ff:ff
现在,让我们为网络设备添加一个 IPv4 地址。我们已经检查了我们的网络,IP 地址 192.168.10.1 是可用的。让我们将它添加到设备 enp0s8 中。
$ sudo ip addr add 192.168.10.1/24 dev enp0s8
查看$ sudo ip addr show enp0s8
的结果,我们看到我们在输出中添加了以下行:
inet 192.168.10.1/24 scope global enp0s8
这是我们所期望的,但是状态仍然是 down,所以我们现在发出以下命令:
$ sudo ip link set dev enp0s8 up
再次查看ip addr show enp0s8
的输出,它现在将处于 UP 状态,并准备在 at 接口上发送和接收流量。它现在看起来应该类似于清单 7-1 。
我们还可以删除一个接口。当我们“关闭”一个链接时,我们不会删除 IP 地址。为此,我们将发出以下命令:
$ sudo ip addr del 192.168.10.1/24 dev enp0s8
如果您现在显示接口,则链路仍在运行,IPv4 地址已消失。您应该注意到,只要链路正常,IPv6 地址就可用。要禁用 IPv6 接口,您需要断开链接。
Note
使用 ip 命令对接口所做的更改不会在重新启动后持续存在;当您重新启动时,您将丢失所有更改。我们将很快解释如何将您的更改永久应用到您的主机。
管理界面
正如我们已经说过的,使用ip
命令有利于动态添加和管理接口,但是我们也需要能够永久地配置接口。在 Linux 上有几种方法可以做到这一点。您可以选择使用图形用户界面(GUI)或直接从命令行运行。如果您愿意,也可以直接写入网络文件。
CentOS 和 Ubuntu 可以不同地管理网络。CentOS 现在使用 NetworkManager 来管理其网络。Ubuntu 可以使用 NetworkManager,但默认情况下不会安装。NetworkManager 是一个管理网络连接和服务的守护进程。它作为 Unity 桌面的一部分安装在 Ubuntu 上,你也可以单独安装。NetworkManager 将与旧的样式(LSB)文件集成,通过 LSB 网络服务管理网络接口。
NetworkManager 通过 Dnsmasq 程序(本地 DNS 服务器)集成和配置域名系统(DNS)解析,并处理 VPN 和无线连接的配置和设置。
我们在第六章中讨论了 systemd 和多用户目标,这就是网络管理器。NetworkManager 具有插件,使其能够管理您的网络配置文件。它们是ifcfg-rh
和ifupdown
,分别处理 Red Hat 风格和 Debian 风格的脚本。您可以通过设置网络连接配置文件中的NM_CONTROLLED=’no’
(稍后解释),在 Red Hat 风格的主机中禁用通过 NetworkManager 对接口的管理。在 Debian 风格的主机中,NetworkManager 被禁用来管理/etc/network/interfaces
中列出的接口,除非您在/etc/NetworkManager/NetworkManager.conf
中明确地将以下内容更改为:
[ifupdown]
managed=true
有些人选择不运行 NetworkManager,因为他们觉得它太麻烦,他们更喜欢自己管理网络。NetworkManager 旨在使网络“正常工作”,您的里程数可能会有所不同,但自从它问世以来,已经做了大量的工作,它肯定比它问世时好得多。
NetworkManager 还提供了一些 CLI(命令行界面)程序来帮助管理您的配置。
- nmcli 控制和报告网络管理器的状态
- 用于管理网络管理器的基于文本的用户界面
在本章的后面,我们将向您展示更多关于nmcli
和nmtui
的内容。有关网络管理器的更多信息,您可以查看以下内容:
https://help.ubuntu.com/community/NetworkManager
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/sec-Introduction_to_NetworkManager.html
通过图形用户界面管理网络
如果您使用桌面来管理您的服务器,您可以使用 GUI 来管理您的网络配置。使用 CentOS,我们可以通过应用程序➤系统工具➤设置来访问网络设置。
在图 7-4 中,我们可以看到我们系统上配置的网络。在左侧面板中,您可以选择连接到系统的设备,这里我们的网络接口称为“有线”右下角的齿轮齿允许您访问配置。您可以使用开关按钮打开或关闭界面。如果您希望添加另一种类型的接口,如成组或绑定或 VPN 接口,您应该选择左侧面板底部的+。
图 7-4。
CentOS network settings
如果我们要添加一个新接口,并在那里进行配置,我们将看到接口按其设备名称列在左侧面板中,如enp0s8
。如果您选择配置其中一个接口,您可以看到选项与我们在安装服务器时看到的类似。
我们以前见过这种情况;在图 7-5 中,我们添加了192.168.10.1
地址。同样,我们可以选择手动配置接口,或者通过下拉选项允许通过 DHCP 进行配置。
图 7-5。
Adding an IP address in CentOS network settings
如果你运行 Ubuntu 桌面来管理你的服务器,我们可以做同样的事情。在图 7-6 中,我们使用 Unity Desktop 的搜索工具来查找网络设置。
图 7-6。
Network settings in Ubuntu
在图 7-6 中选择网络时,我们会看到一个与 CentOS 相似的用户界面来配置我们的网络。在图 7-7 中,我们可以看到您将与图 7-5 中相同的信息插入该界面。
图 7-7。
Configuring a network interface in Ubuntu
在图 7-7 中,我们再次可以选择使用 DHCP 或手动配置接口。使用用户界面配置网络接口在重新启动后仍然有效。
现在让我们看看用网络配置文件和脚本来保存网络配置的另一种方法。
使用 nmtui 配置接口
NetworkManager 附带的基于 curses 的配置工具设计用于任何类型的终端。您可以通过此终端用户界面(tui)创建和管理接口以及设置主机名。
在本练习中,我们将运行 nmtui 程序来配置我们新连接的enp0s8
以太网设备。我们可以使用 dmesg 找到新接口的设备名称。
$ sudo dmesg |grep enp
[ 6.903532] IPv6: ADDRCONF(NETDEV_UP): enp0s8: link is not ready
我们将很快使用这些信息。要启动它,您需要发出$ sudo nmtui
。
图 7-8。
Edit a connection
在这里,我们选择编辑连接。
在图 7-9 中,我们添加选择添加来添加我们的新接口。
图 7-10。
Type of interface, Ethernet
图 7-9。
Add a connection
在这里,我们选择希望添加的接口类型。有几个选项可供选择,包括用于连接到您的 ISP 的 DSL、Wi-Fi 以及其他选项,如 VLAN 和团队界面。我们将选择以太网。
图 7-11。
Add in our interface
我们提供了一个配置文件名;该名称可以是您希望的任何名称,但是将其命名为有意义的名称通常会很有帮助,因为您可以在使用姊妹命令nmcli
时使用该配置文件名。在我们的例子中,我们只是将其命名为与我们添加到设备部分的设备名称相同。
我们可以设置一个 IP 地址,或者允许我们的接口从 DHCP 服务器接收一个 IP 地址,这就是我们决定要做的。但是,添加 IP 地址就像我们之前做的一样简单。我们可以向下箭头到并退出。
Consistent Device Naming
enp0s3 或者 enp0s8 这个名字是怎么回事?以前,当系统启动时,它们的网络设备会被驱动程序探测到,并被命名为 eth0。如果有多个网络设备,eth0 可能在一次引导时是 eth0,而在下一次引导时是 eth1。这导致了明显问题。我们需要可预测的网络接口。幸运的是,systemd/udev 已经找到了解决方案。
设备现在可以从 biosdevname udev helper 实用程序中获得它们的名称。这些名字意味着一些东西。
- em[1,2,3…]–嵌入式网络接口
- P1 P1–PCI 卡(p p
- P2P 1 _ 1–虚拟接口(p p _
不同的硬件供应商默认启用此功能,有些则没有。您可以在 boot 命令行上将它设置为 enabled,biosdevname=0(或 1 表示禁用)。
如果 biosdevname 不可用,Systemd 提供了一个后备方案。这就是我们的设备名 enp0s8 的由来。systemd 中可能出现的其他命名模式有:
- eno1–车载设备
- en S1–PCI 插槽索引号
- enp0s 8–连接器的物理位置
- enx7f 291992–组合 MAC 地址
- eth 0–经典
要更仔细地阅读 systemd,请看一下 www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
.
使用 nmcli 配置接口
还有另一种方法可以配置我们的接口。它包含名为 nmcli 的实用程序。这是一个非常强大的工具,可以处理和配置 NetworkManager 配置。
有了这个工具,我们可以创建、显示、编辑和调出界面。让我们先花点时间来探索一下这个实用程序。
我们以前谈到过网络管理器配置文件。这些是接口的名称。要使用 nmcli 显示当前连接信息,我们将发出以下命令:
$ sudo nmcli connection show
NAME UUID TYPE DEVICE
enp0s3 da717740-45eb-4c45-b324-7d78006bb657 802-3-ethernet enp0s3
nmcli 有几个快捷方式,如“c”表示连接,“d”表示设备。要管理实际设备(连接、断开、删除),可以使用 device 子命令。
$ sudo nmcli d status
DEVICE TYPE STATE CONNECTION
enp0s3 ethernet connected enp0s3
lo loopback unmanaged --
nmcli 命令采用以下格式:
$ nmcli <OPTIONS> <OBJECT> <COMMAND|HELP>
因此,如果您需要帮助来记住如何在连接对象上使用 add 命令,您可以键入
$ nmcli connection add help
Usage: nmcli connection add { ARGUMENTS | help }
....
我们接下来要做的是为我们的 CentOS 主机添加一个团队界面。组接口是由两个或多个链接组成的聚合接口。它可以提供比单个接口更大的吞吐量或链路冗余。它可以支持主动/被动、LACP(链路聚合控制协议)和 VLANs(虚拟局域网)等协议。
一个团队有两个主要部分,一个团队守护进程和运行程序。teamd 守护进程管理网络接口和内核之间的 API(应用程序编程接口)。runners 是模块的另一种说法,它提供实现特定功能的代码,如主动/被动和 VLANs。
我们将添加两个设备来创建一个带有主动/被动跑步者的团队界面。它们是 enp0s8 和 enp0s9。
$ sudo nmcli device status
DEVICE TYPE STATE CONNECTION
enp0s8 ethernet disconnected --
enp0s9 ethernet disconnected --
首先,我们用清单 7-2 中的命令添加组接口(team0)。
sudo nmcli c add type team con-name team0 ifname team0 config
'{"device": "team0", "runner": {"name":"activebackup"}}' ip4 192.168.10.10 gw4 192.168.10.254
Listing 7-2.Adding team0 Interface
在清单 7-2 中,我们使用nmcli
命令添加了一个组接口,并为其分配了 IP 地址192.168.10.10
和网关地址192.168.10.254
。我们通过添加(add
)连接(c
)类型的团队来做到这一点。我们已经给这个接口命名为 team0 ( ifname
)和一个配置文件名 team0 ( con-name
)。
对于一个团队接口,我们需要提供一个 JSON 配置来描述我们希望使用的 runner。这既可以在 JSON 文件中,也可以在命令行中,就像我们上面提到的那样。您可以在man 5 teamd.conf
中使用更多的设置示例。在清单 7-2 中,我们已经提供了所需的最低要求,即设备和流道。
这将创建一个名为/etc/sysconfig/network-scripts/ifcfg-team0
的文件,我们可以看到它包含以下详细信息:
DEVICE=team0
TEAM_CONFIG="{\"device\": \"team0\", \"runner\": {\"name\":\"activebackup\"}}"
DEVICETYPE=Team
BOOTPROTO=none
IPADDR=192.168.10.10
PREFIX=32
GATEWAY=192.168.10.254
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
NAME=team0
UUID=2cef1621-4e56-4cb8-84f7-2d613fbc168f
ONBOOT=yes
我们将很快解释这些配置文件,你可以看到我们的组配置和 IP 地址的设置。我们已经创建了“主”接口,现在我们必须向它添加“从”接口。
我们使用以下命令来实现这一点:
sudo nmcli c add type team-slave con-name team0-port1 ifname enp0s8 master team0
Connection 'team0-port1' (4e2f4307-e026-4b1a-b19e-da8f1ad64d7a) successfully added.
sudo nmcli c add type team-slave con-name team0-port2 ifname enp0s9 master team0
Connection 'team0-port2' (ca1206ce-c0d3-45a5-b793-f10b8c680414) successfully added.
我们再次添加了一种连接名称为 team-port{1,2}的组从类型,并将它们连接到主组 0 的接口 enp0s{8,9}。让我们来看看它创建的一个文件。
/etc/sysconfig/network-scripts/ifcfg-team0-port1
NAME=team0-port1
UUID=4e2f4307-e026-4b1a-b19e-da8f1ad64d7a
DEVICE=enp0s8
ONBOOT=yes
TEAM_MASTER=team0
DEVICETYPE=TeamPort
现在让我们看看它们是否出现在我们的连接列表中。
sudo nmcli c show
NAME UUID TYPE DEVICE
team0-port1 4e2f4307-e026-4b1a-b19e-da8f1ad64d7a 802-3-ethernet enp0s8
team0 2cef1621-4e56-4cb8-84f7-2d613fbc168f team team0
team0-port2 ca1206ce-c0d3-45a5-b793-f10b8c680414 802-3-ethernet enp0s9
设备列表现在如下所示:
$ sudo nmcli d status
[sudo] password for jsmith:
DEVICE TYPE STATE CONNECTION
enp0s8 ethernet connected team0-port1
enp0s9 ethernet connected team0-port2
team0 team connected team0
lo loopback unmanaged --
我们将快速查看是否能从接口获得 ping 响应。
ping 192.168.10.10
PING 192.168.10.10 (192.168.10.10) 56(84) bytes of data.
64 bytes from 192.168.10.10: icmp_seq=1 ttl=64 time=0.047 ms
所以现在我们有了一个团队界面。你也可以用团队工具来管理团队界面,比如teamctl
和teamnl
。让我们继续查看配置文件的更多信息。
使用网络脚本配置网络
CentOS 和 Ubuntu 都将其网络配置文件存储在/etc
目录中。CentOS 将其文件存储在/etc/sysconfig/network-scripts
下的网络相关目录集合中,Ubuntu 将其文件存储在/etc/networks
目录下。
CentOS 的网络配置文件
如前所述,CentOS 使用 NetworkManager 来管理插入或连接的网络接口。与网络相关的 CentOS 文件可以在/etc/sysconfig
目录下找到。找到这些信息的主要地方有
/etc/sysconfig/network
文件/etc/sysconfig/network-scripts
目录
/etc/sysconfig/network
文件包含全局设置,可以包含像HOSTNAME
和默认GATEWAY
这样的东西。/etc/sysconfig/network-scripts
目录包含所有网络接口的启动和关闭脚本。这些文件是/etc/sysconfig/
网络脚本目录中文件的一般副本,由系统配置网络工具为您创建。
查看一下/etc/sysconfig/network-scripts
目录的内容,您会看到清单 7-3 中所示的文件。
sudo ls /etc/sysconfig/network-scripts/
ifcfg-enp0s3 ifdown-ipv6 ifdown-ppp ifdown-tunnel
ifup-ipv6 ifup-routes ifup-wireless network-functions-ipv6
ifcfg-lo ifdown-eth ifdown-routes ifup ifup-eth ifup-post
init.ipv6-global ifdown ifdown-post ifup-aliases
ifup-ppp ifup-tunnel network-functions
Listing 7-3.Files Found in /etc/sysconfig/network-scripts
在清单 7-3 中,您可以看到一个精简的脚本列表,这些脚本用于配置您的接口并使它们启动或关闭。存在各种文件。
像ifcfg-enp0s3
这样的文件是以太网接口的配置文件或连接配置文件。命名约定为if<action>-device
的文件,例如ifdown-ppp
,是用于控制状态的脚本(即,使界面打开或关闭)。
我们之前讨论过网络管理器。如果配置了 NetworkManager,它将读取和写入这些文件。与ifcfg-enp0s3
一样,配置描述文件由网络管理器读入,并将设备名称传递给ifup
脚本。如果设备已经连接并由网络管理器管理,ifup
将使用nmcli
来管理接口。如果我们有NM_CONTROLLED=”no”
,那么ifup
将使用ip
命令来管理界面。在此之前,它会检查该设备是否已经由网络管理器管理,如果是,它不会尝试管理该设备。要启动enp0s3
设备,您需要发出以下命令:
ifup enp0s3
像network-functions
这样的文件是包含函数和变量的脚本。其他脚本可以从network-functions
获取(或包含)函数和变量,并在它们的脚本中使用它们。
我们来看看 enp0s3 的配置文件,名字叫ifcfg-enp0s3
。您可以在清单 7-4 中看到这个文件的内容。
sudo less /etc/sysconfig/network-scripts/ifcfg-enp0s3
TYPE="Ethernet"
DEVICE="enp0s3"
NAME="enp0s3"
UUID="fa56e72e-ea22-43ca-9a90-e19d64c0c431"
ONBOOT="yes"
BOOTPROTO="dhcp"
DEFROUTE="yes"
PEERDNS="yes"
PEERROUTES="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_PEERDNS="yes"
IPV6_PEERROUTES="yes"
IPV6_FAILURE_FATAL="no"
Listing 7-4.The ifcfg-enp0s3 File
在清单 7-4 中,你可以看到许多选项=参数形式的配置选项。要配置 CentOS 界面,我们需要设置选项,如我们正在管理的设备的名称:DEVICE=”enp0s3”
。我们对名称使用相同的值。
引导协议BOOTPROTO=”dhcp”
被设置为从 DHCP 获取其地址。设备的 UUID(通用唯一标识符)是“fa 56 e 72 e-ea22-43ca-9a 90-e 19d 64 c 0 c 431”,这是分配给此设备的唯一标识符,由网络管理器用来映射设备。您可以通过指定ONBOOT=”yes”
来声明接口是否会在启动时初始化。接口的类型由TYPE=”Ethernet”
声明。如果您不想用 IPv6 地址初始化我们的接口,您可以将 IPV6INIT 设置为“no”;这里是默认的IPV6INIT=”yes”
。当PEERDNS=”yes”
被声明时,意味着/etc/resolv.conf
文件带有 DHCP 服务器提供的名称服务器。如果我们将它设置为 no,那么当这个接口进入 up 状态时,/etc/resolv.conf
将保持不变。我们将在第十章详细解释这是如何工作的。
表 7-2 列出了您可以在 CentOS 界面文件中使用的选项。
表 7-2。
Some of the Common Network Configuration File Options, CentOS
| [计]选项 | 描述 | | --- | --- | | `DEVICE` | 您正在创建的设备的名称。这将出现在接口列表中。 | | `BOOTPROTO` | 设备启动时使用的协议。这里的选择有`static`、`dhcp`和`none`。 | | `ONBOOT` | 主机启动时设备是否启动。 | | `NETWORK` | 这个设备的网络地址。 | | `NETMASK` | 该设备的网络掩码。 | | `IPADDR` | 这个设备的 IP 地址。 | | `IPV4_FAILURE_` `FATAL` | 如果设置为是,如果我们没有从 DHCP 获得 IP 地址,`ifup-eth`脚本将立即结束 | | `MASTER` | 该设备所属的设备是`SLAVE`。 | | `SLAVE` | 设备是否由`MASTER`指令中指定的主机控制。 | | `NM_CONTROLLED` | 如果设置为否,网络管理器将忽略该设备。CentOS 上的默认值是 yes。 | | `DNS{1,2}` | DNS 主机的 IP 地址(多个地址用逗号分隔)。如果`PEERDNS`设置为是,这将被添加到`/etc/resolv.conf`中。 | | `PEERDNS` | 确定是否将 DNS 中指定的`DNS`主机添加到`/etc/resolv.conf`的设置。如果设置为`yes`,它们被添加。如果`no`,则不添加。 | | `VLAN` | 将此设备设置为 VLAN 接口(“是”、“否”) | | `IPV6INIT` | 启用或禁用此设备的 IPv6 配置。 |表 7-2 中的选项只是可以在您的网络连接配置文件中设置的一部分;要获得选项的完整列表,您可以阅读/usr/share/doc/initscripts-<version>/sysconfig.txt
,其中<version>
是 initscripts 包的版本号。
创建结合界面
我们现在将带您了解如何通过在连接配置文件中设置一些选项来手动配置绑定的以太网设备。绑定的以太网设备也可以称为中继设备。绑定允许您使用两个或更多以太网端口作为一个接口,为您提供扩展的带宽和一些冗余。这样,对于一个虚拟接口,您可以将 1 GiB 链路转换为 2 GiB 链路。
那么我们该如何完成这一壮举呢?我们的主机上连接了两个器件:enp0s8 和 enp0s9。我们将这两个器件绑定在一起,使它们显示为一个接口,即 bond0。首先,我们必须将每个器件配置为从机,在清单 7-5 中,您可以看到我们是如何配置 enp0s8 的。enp0s9 器件将是该器件的镜像。
less /etc/sysconfig/network-scripts/ifcfg-enp0s8
DEVICE="enp0s8"
NAME="bond0-slave"
TYPE="Ethernet"
ONBOOT="yes"
BOOTPROTO="none"
SLAVE="yes"
MASTER="bond0"
Listing 7-5.The enp0s8 Slave Device Configuration
这是一个非常简单的配置。我们已经指定了我们希望控制的设备 enp0s8,以及当我们通过指定ONBOOT=”yes”
启动主机时是否希望它初始化。该绑定设备的 IP 地址将自身连接到 bond0 设备,而不是 enp0s8 或 enp0s9。因此,我们在这里不指定引导协议,而是使用选项BOOTPROTO=”none”
。当我们打开绑定接口时,NAME=”bond0-slave”
将变得清晰,但是它提供了一个易于阅读的名称,NetworkManager 将显示这个名称(记住,除非我们明确地拥有NM_CONTROLLED=”no”
,否则 NetworkManager 将管理我们的连接)。
接下来是将该设备添加到绑定配置的两个选项。第一个是SLAVE=”yes”
,声明该设备是从设备。接下来,我们通过指定MASTER=”bond0”
来声明它属于哪个主机。我们所指的bond0
是我们即将创造的同名设备。
如我们所说,接口 enp0s9(在/etc/sysconfig/network-scripts/ifcfg-enp0s9
文件中配置)将镜像复制并粘贴来自 enp0s8 的细节。然后我们需要把DEVICE=enp0s8
改成DEVICE=enp0s9
。其余的可以保持不变。
接下来,我们将创建焊接 0 器件文件。在 CentOS 上,配置细节将保存在一个名为/etc/sysconfig/network-scripts/ifcfg-bond0
的文件中。在清单 7-6 中,你可以看到我们需要什么来创建一个绑定接口。
[jsmith@au-mel-centos-1∼]$ vi /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE="bond0"
NAME="bond0"
TYPE="bond"
BONDING_MASTER="yes"
BONDING_OPTS="mode=1 delayup=0 delaydown=0 miimon=100"
BOOTPROTO="none"
ONBOOT="yes"
NETWORK="192.168.0.0"
NETMASK="255.255.255.0"
IPADDR="192.168.0.1"
Listing 7-6.Configuration for a Bonded Interface
如您所见,它非常类似于标准的以太网设备文件。您需要指定设备名称,在我们的示例中为 bond0,并为其提供适当的网络信息,如 IP 地址、网络和网络掩码信息。同样,我们希望这个设备在启动时被初始化。
清单 7-6 中列出了一些特定于绑定的选项,比如 BONDING_MASTER 和 BONDING_OPTS。BONDING_MASTER 相当简单,仅仅意味着这是一个绑定主接口。BONDING_OPTS 允许您为您的接口设置每个接口的绑定选项。让我们看看我们在上面设置了什么。
模式 1 将接口绑定类型设置为主动备份,如果您愿意,可以使用“mode=active-backup”
代替“mode=1”
。对于主动备份,当主动接口出现故障时,另一个接口会接管。这主要是为了网卡冗余,而不是吞吐量。miimon 是检查接口是否处于活动状态的频率(毫秒)。在高可用性配置中,当 miimon 发现一个接口关闭时,它将激活其余的接口。delayup
和delaydown
是以毫秒为单位给出时间周期的设置,在这个时间周期内,我们应该等待对从状态的变化做出反应。我们已经将这些设置为零,随着时间的推移,我们会根据需要进行调整。
根据您的网络以及在给定网络设备的情况下可以实现的绑定类型,您可以在此处添加其他选项,以便为绑定的设备提供容错、冗余和循环功能。有关更多信息,您可以查看 iputils 包提供的文档,该包管理 CentOS 主机上的绑定,特别是/usr/share/doc/iputils-<version>/README.bonding
。
当您的接口出现时,您的脚本(NetworkManager 或 ifup-eth 脚本)会将绑定模块插入内核。绑定模块允许内核知道如何处理绑定接口,它也可以被称为内核的驱动程序。管理绑定接口的低级工具,如 iputils 包中的ifenslave
,需要在绑定接口之前加载绑定模块。如果您想检查您的绑定模块是否已经加载到内核中,您可以发出以下命令,如果是,您将会看到如下内容:
lsmod |grep bonding
bonding 136705 0
如果不是,也不用担心。我们将在调出界面后再次检查。如果您愿意,您可以使用modprobe
命令插入焊接模块。
sudo /usr/sbin/modprobe bonding
Tip
modprobe
命令是将模块(而不是 insmod 命令)插入内核的更聪明的方法,因为它处理依赖关系。
我们现在将调出 bond0 器件或主接口。遵循接口的启动顺序很重要;例如,当您首先启动主接口时,您的从接口不会自动启动,但是当您启动从接口时,您的主接口会自动启动。我们正在设置一个静态 IP 地址,即使从接口没有启动,我们的主接口也会启动 IP 连接并响应“ping”。在 DHCP 中,主设备在从设备启动之前不会获得 IP。另外,请记住,NetworkManager 将管理这些接口,因此我们将开始使用一些nmcli
命令来显示我们的连接,但是您也可以使用我们前面看到的ip
命令。
当我们修改界面脚本时,比如ifcfg-enp0s8
,我们需要告诉网络管理器重新读取它。我们可以指定要重读的接口文件,但在这种情况下,我们将通过发出
sudo nmcli connection reload
Tip
这可以缩短为nmcli c r
,因为许多命令可以只取子命令的第一个字母。
现在让我们检查一下接口的当前状态。我们发布了以下内容:
sudo nmcli device status
DEVICE TYPE STATE CONNECTION
enp0s8 ethernet disconnected --
enp0s9 ethernet disconnected --
这表明我们的设备当前处于断开状态。我们现在将通过启动从属接口来启动主(bond0)接口。我们也可以通过nmcli
命令来完成,如下所示:
sudo nmcli device connect enp0s8
Device 'enp0s8' successfully activated with '00cb8299-feb9-55b6-a378-3fdc720e0bc6'.
sudo nmcli device status
DEVICE TYPE STATE CONNECTION
bond0 bond connected bond0
enp0s3 ethernet connected enp0s3
enp0s8 ethernet connected bond0-slave
enp0s9 ethernet disconnected --
lo loopback unmanaged --
sudo nmcli device connect enp0s9
sudo nmcli device status
DEVICE TYPE STATE CONNECTION
bond0 bond connected bond0
enp0s3 ethernet connected enp0s3
enp0s8 ethernet connected bond0-slave
enp0s9 ethernet connected bond0-slave
lo loopback unmanaged --
我们的第一个命令是连接我们的enp0s8
设备。当连接可以建立时,我们的bond0
设备也可以,但是我们的enp0s9
设备仍然是断开的。然后我们拿出了我们的enp0s9
设备。
很快,我们可以通过再次发出以下命令来验证我们的绑定驱动程序已经加载到内核中:
lsmod |grep bonding
bonding 136705 0
如果我们想关闭 bond 接口,我们可以发出以下命令:
sudo nmcli connection down bond0
Connection 'bond0' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)
sudo nmcli device status
DEVICE TYPE STATE CONNECTION
enp0s3 ethernet connected enp0s3
enp0s8 ethernet disconnected --
enp0s9 ethernet disconnected --
您可以看到,关闭 bond0 接口也断开了两个从机的连接。
我们还可以通过发出/sbin/ip addr show
命令来查看您新绑定的器件,这将产生以下输出:
3: enp0s8: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP>
mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
link/ether 08:00:27:71:c3:d8 brd ff:ff:ff:ff:ff:ff
4: enp0s9: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP>
mtu 1500 qdisc pfifo_fast master bond0 state UP qlen 1000
link/ether 08:00:27:71:c3:d8 brd ff:ff:ff:ff:ff:ff
8: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP>
mtu 1500 qdisc noqueue state UP
link/ether 08:00:27:71:c3:d8 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/24 brd 192.168.0.255 scope global bond0
valid_lft forever preferred_lft forever
inet6 fe80::a00:27ff:fe71:c3d8/64 scope link
valid_lft forever preferred_lft forever
如果看 enp0s8 和 enp0s9 的接口描述,可以看到它们都被设置为SLAVE
,可以看到 bond0 被设置为MASTER
。两个从站都没有相关联的 IP 地址。bond0 接口具有与之关联的 IP 地址。
向接口添加多个 IP 地址
我们可以向一个接口添加多个地址。它们不必在同一个网络中,可以用于在您的主机上路由来自不同网络的流量。为此,我们可以编辑我们的网络配置文件。让我们再次看看我们的 CentOS 主机及其 enp0s3 配置文件。
我们可以使用nmcli
命令来做到这一点。为此,我们必须修改现有的接口。首先,我们看到以下可用接口:
sudo nmcli c s
enp0s3 da717740-45eb-4c45-b324-7d78006bb657 802-3-ethernet enp0s3
记下设备 uuid(da 717740-45e b-4c 45-b324-7d 78006 bb 657),我们可以使用它来引用我们的接口。我们将使用连接对象来修改我们的接口并添加多个 IP 地址,如下所示:
sudo nmcli con mod da717740-45eb-4c45-b324-7d78006bb657 ipv4.addresses '192.168.14.10/24, 172.10.2.1/16, 10.2.2.2/8'
如果我们现在查看/etc/sysconfig/network-script/ifcfg-enp0s3
文件,我们可以看到我们添加了 IP 地址。
TYPE=Ethernet
BOOTPROTO=dhcp
DEFROUTE=yes
<snip>
NAME=enp0s3
UUID=da717740-45eb-4c45-b324-7d78006bb657
DEVICE=enp0s3
ONBOOT=yes
<snip>
IPV6_PEERROUTES=yes
IPADDR=192.168.14.10
PREFIX=24
IPADDR1=172.10.2.1
PREFIX1=16
IPADDR2=10.2.2.2
PREFIX2=8
在这里,您可以看到我们添加了两个 IPv4 地址:IPADDR、IPADDR1 和 IPADDR2。我们可以使用前缀、前缀 1 和前缀 2 来提供网络掩码。
刷新接口以显示新地址。我们也使用 nmcli 这样做。
sudo nmcli con up enp0s3
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/2685)
我们现在可以看到如下新地址:
ip addr show enp0s3 |grep inet
inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
inet 192.168.14.10/24 brd 192.168.14.255 scope global enp0s3
inet 172.10.2.1/16 brd 172.10.255.255 scope global enp0s3
inet 10.2.2.2/8 brd 10.255.255.255 scope global enp0s3
inet6 fe80::a00:27ff:feb2:9245/64 scope link
添加别名的另一种方法是在主机启动时使用脚本来分配 IP 地址。我们可以将类似这样的内容添加到我们的rc.local
文件中:
/etc/rc.d/rc.local
/sbin/ip addr add 192.168.0.24/24 brd 192.168.0.255 dev enp0s3
/sbin/ip addr add 192.168.0.25/24 brd 192.168.0.255 dev enp0s3
/sbin/ip addr add 192.168.0.26/24 brd 192.168.0.255 dev enp0s3
在上文中,当我们的主机重新启动时,我们将 IPv4 地址192.168.0.24-26
添加到我们的enp0s3
地址中。/etc/rc.d/rc.local
文件需要设置执行位(chmod +x rc.local
),因为我们运行的是 systemd 而不是 SysVInit,所以我们需要确保在重启系统时 systemd 会执行它。如果你还记得第六章的话,我们通过执行下面的代码来实现:
sudo systemctl enable rc-local.service
这就是我们如何在 CentOS 下管理不同类型的接口。现在让我们看看在 Ubuntu 下我们是如何做到这一点的。
Ubuntu 的网络配置文件
Ubuntu 在/etc/network
中有一个类似的网络文件目录。它包含 Ubuntu 用来设置网络的网络文件和脚本。如前所述,Ubuntu 将接口信息存储在文件/ etc/network/interfaces
中。它包含任何已配置接口的所有接口信息。
使用 DHCP 的接口可能很简单,如下所示:
# The primary network interface
auto enp0s3
iface enp0s3 inet dhcp
首先我们声明 enp0s3 是用auto enp0s3
自动启动的。接下来,我们声明 enp0s3 接口将使用 IPv4 地址,该地址将从 DHCP 服务器iface enp0s3 inet dhcp
获得。如果您要配置其它以太网卡,enp0s8 或 enp0s9,您也可以使用/etc/network/interfaces
文件。您可以将配置文件放在/etc/network/interfaces.d
目录中,然后使用以下命令从/etc/network/interface
文件中“获取”它:
source-directory interfaces.d
这将自动引入interfaces.d
目录中的任何配置文件。您可以在界面文件中使用的其他参数见表 7-3 。
表 7-3。
Ubuntu Parameters in /etc/network/interfaces
在表 7-3 中,你可以看到在 Ubuntu 上设置网络接口时可用的大多数参数。我们将使用其中一些在/etc/network/interfaces
文件中为 enp0s3 设置一个静态网络接口,如下所示:
auto enp0s3
iface enp0s3 inet static
address 192.168.0.10
netmask 255.255.255.0
gateway 192.168.0.254
dns-nameservers 192.168.0.1
这里我们已经设置了 enp0s3 接口。我们已经将它设置为在我们的主机启动时自动启动,auto enp0s3
,并告诉我们的操作系统将为它分配一个静态 IP 地址,iface enp0s3 inet static
。我们为 enp0s3 接口分配了地址 192.168.0.10 和默认网关(默认路由)192.168.0.254。我们还将 DNS 服务器指定为 192.168.0.1,这是我们内部网络的主要名称服务器。
我们现在将向您展示如何在下面的示例中使用它们。使用接口文件,我们将在 Ubuntu 主机上创建一个绑定的以太网设备。
我们需要做的第一件事是安装一个额外的软件包,如果它还没有安装的话。
sudo aptitude install ifenslave
在这种情况下,我们将启用模式“1”绑定,我们已经知道,这也可以称为主动备份。这可以在从属接口之间实现一些简单的循环负载平衡,并支持从属设备的连接和分离。
在 Ubuntu 中,和在 CentOS 中一样,处理接口的脚本也可以在/etc/network
目录中找到,比如 if-up.d,处理将绑定模块插入内核。如果你使用的是旧版本的 Ubuntu,你可以在/etc/modules
文件中添加“bonding ”,它会在启动时加载上面列出的模块。
我们为 Ubuntu 主机添加了两个新的网卡,它们显示为设备 enp0s3 和 enp0s8。我们需要配置这些设备进行绑定。为此,我们编辑 Ubuntu /etc/network/interfaces
文件,并添加从接口以及主接口 bond0 的配置。让我们从展示一个从机的配置开始。
# slave interface
auto enp0s8
iface enp0s8 inet manual
bond-master bond0
这里,我们将第一个从机接口设置为 enp0s8。iface enp0s8 inet manual
表示我们不想给这个接口分配 IP 地址。显然,我们将 bond-master 设置为主接口的名称 bond0。enp0s9 接口再次反映了 enp0s8 的配置。
转到焊接设备,我们可以按如下方式进行设置:
# The primary network interface
auto bond0
iface bond0 inet static
address 192.168.0.10
netmask 255.255.255.0
bond-mode active-backup
bond-miimon 100
bond_downdelay 25
bond_updelay 25
bond-primary enp0s8
bond-slaves enp0s8 enp0s9
在第一行“自动焊接 0”中,我们已经声明焊接 0 器件应该在引导时自动加载。接下来,在iface bond0 inet static
中,我们已经声明接口 bond0 是一个 IPv4 静态分配的接口,这意味着我们不会使用 DHCP 或其他协议为其分配地址。然后,我们分别使用关键字address, netmask, gateway
和dns nameservers
分配 IP 地址、网络掩码、网关和 DNS 服务器。然后,我们将bond-mode
设置为active-backup
(模式 1),将bond-miimon
设置为100
,并指定该接口的从机。我们还配置了一个 25 毫秒的等待时间,然后对我们的从机的状态进行处理。这些都有相同的含义,因为他们在 CentOS 债券。
现在你可以选择两种方法来启动这个界面。首先是使用systemctl
命令重启 networking.service,如下所示:
sudo systemctl restart networking.service
另一种是使用ifup
命令。不过,这应该按照特定的顺序来完成。从接口将自动启动主接口,但主接口不会启动从接口。
sudo ifup enp0s8 && sudo ifup enp0s9
这里我们说的是调出 enp0s8 接口,如果退出代码为 0 (’ &&
'),则调出 enp0s9 接口。我们也可以重启我们的主机。我们现在可以通过查看特殊的/proc/net/bonding/bond0
文件来验证我们的绑定接口是否正常工作。
sudo cat /proc/net/bonding/bond0
Bonding Mode: fault-tolerance (active-backup)
Primary Slave: None
Currently Active Slave: enp0s8
MII Status: up
MII Polling Interval (ms): 100
这是针对该文件的 cat 命令输出的一部分。我们可以看到绑定模式设置为“容错(主动备份)”,主动从机为 enp0s8,MII 状态为“启动”;这告诉我们债券运作正常。在完整的输出中,您也可以看到列出的从机。
您也可以通过如下的ip
命令进行检查:
sudo ip link show enp0s8
3: enp0s8: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP>
mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:5c:94:ef brd ff:ff:ff:ff:ff:ff
sudo ip addr show bond0
9: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP>
mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:5c:94:ef brd ff:ff:ff:ff:ff:ff
inet 192.168.0.10/24 brd 192.168.0.255 scope global bond0
valid_lft forever preferred_lft forever
现在可以看到 IP 地址 192.168.0.10 被附加到 bond0,enp0s8 和 enp0s9 都是 bond0 的从机:<BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0
。您还会注意到,所有三台设备都有相同的 MAC 地址08:00:27:5c:94:ef
,这意味着它们都可以响应地址解析协议(ARP)对该 MAC 地址的请求。我们将在“TCP/IP 101”一节中进一步解释 ARP
Ethtool
ethtool
命令用于进一步研究和操作您的界面。例如,根据您的驱动程序,您可以更改接口的链接速度或双工设置。
您可以通过发出以下命令来查看您的设备正在使用的设置:
sudo ethtool enp0s8
Settings for enp0s8:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: Yes
Speed: 1000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
MDI-X: off (auto)
Cannot get wake-on-lan settings: Operation not permitted
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
这显示了 enp0s8 设备的当前设置。如果要更改双工模式和速度,可以发出如下命令:
sudo ethtool -s enp0s8 speed 1000 duplex half
这里我们将以太网卡的speed
更改为1000Mb/s
,将duplex
设置为half
双工。您也可以使用其他设置。为了更好地了解可用设置,请阅读ethtool
的man
页面。
TCP/IP 101
是时候稍微深入研究一下 TCP/IP(传输控制协议/互联网协议)了。您可能对 IP 地址很熟悉,但是它与 TCP/IP 的其他部分有什么关系呢?IP 地址用于查找网络上的其他主机,并供其他主机查找您。但是它是怎么做到的呢?
让我们看看这个简化的例子,当你用你的网络浏览器查找一个页面时。你在地址栏输入地址,然后按回车键。浏览器应用程序获取这些数据,并确定它需要通过打开会话向 web 服务器发送页面请求。为此,它将需要发送的信息分成离散的数据包。然后,它将 web 服务器的地址附加到数据包上,并开始试图确定将数据包发送到哪里。当它获得此信息时,它将启动与 web 服务器的连接,然后在物理线路上传输数据包中的数据,该信息将找到到达 web 服务器的路径。
您可能有兴趣知道,当您启动 TCP/IP 连接(也称为套接字)时,一个三阶段的过程会使该连接进入“已建立”状态,这意味着两台主机都知道彼此的套接字,同意如何发送数据,并准备好发送该数据。第一阶段是主机通过向它想要开始通信的主机发送一个称为 SYN 包的包来启动套接字。该主机用另一个数据包(称为 SYN ACK 数据包)作出响应,表示它已准备好开始通信。然后,发起主机发送一个数据包,另一个 SYN,ACK 数据包,确认该数据包并告诉远程主机它将开始发送数据。当它们完成通信后,连接被 FIN 数据包关闭。这是 TCP/IP 通信过程的基本概述。
Note
要更深入地了解实际数据包的外观,请阅读 http://www.tcpipguide.com/free/t_TCPMessageSegmentFormat-
3.htm
中关于 TCP 数据段的讨论。你也可以去下面找一个方便的袖珍指南: http://www.sans.org/resources/tcpip.pdf?ref=3871
, and of course
: https://en.wikipedia.org/wiki/Transmission_Control_Protocol
。
TCP/IP 协议可以在所谓的 OSI 模型下描述,即使它最初是在一个不同的模型下构思的,称为 DoD 模型(国防部)。OSI 模型由七层组成。在主机之间通过网络进行数据通信的过程中,每一层都有特殊的职责。在诊断网络时,您通常会对第 1 层、第 2 层和第 3 层感兴趣。你可以在图 7-12 中看到这些层的描述。
图 7-12。
The OSI layer model Note
我们将描述前三层;有关 OSI 模型和层的更多信息,请参见: http://www.webopedia.com/quick_ref/OSI_Layers.asp
.
第 1 层涉及数据如何通过物理线路传输,这由图 7-12 底部出现的物理层表示。诊断网络问题时,晃动连接电脑和网络其他部分的电缆不会有什么坏处。此外,当所有其他方法都失败时,您可以尝试更换电缆。如果电缆有故障,您可能看不到主机连接的交换机/集线器和网卡上的任何指示灯。没有这些灯,您的主机将无法与其他主机通信,因此首先尝试更换电缆,然后更换交换机上它所连接的端口,最后更换网卡。
第 2 层,即数据链路层,通过线路提供实际的通信协议。在这一层遇到的问题很少。正是在这里,IP 地址通过使用 ARP(地址解析协议)与 MAC 地址相匹配。当网络上的两台主机具有相同的 IP 地址和不同的 MAC 地址时,您的主机可能会开始尝试向错误的主机发送数据。在这种情况下,可能需要刷新 ARP 表,并且 IP 地址不正确的主机需要脱机。
第 3 层是网络层。它能够发现到您的目的地的路线,并发送您的数据,同时检查错误。这是 IP 层,因此它也可以负责 IPsec 隧道。也是这一层负责响应您的 pings 和其他路由请求。
层 4 到 7 被描述为宿主层。TCP 运行在第 4-5 层,即网络层和会话层。网络层关注寻址和链路可靠性,如错误控制和流量控制。会话层控制计算机之间连接的建立和关闭。第 6 层到第 7 层负责连接用户,这是 HTTP 和浏览器将您连接到 web 服务器的地方。
常规网络故障排除
你的网络可能会出错。有时您无法连接到服务,或者网络的某些部分配置不正确。要识别和解决这些问题,您需要一套工具。我们将研究各种工具:
ping
:在主机之间发送数据包以确认连通性的命令tcpdump
:显示和捕获网络流量的命令mtr
:网络诊断工具- 另一个网络诊断和测试工具 netcat
平!
人们用来检查网络的最常用工具可能是一个名为ping
的命令。您可以 ping 主机或接口,看看它是否有响应。在发出ping
命令的输出响应中,显示了该响应返回所用的时间。你可以 ping 地球的另一端,并在几毫秒内收到响应。那很好。如果您得到的响应时间是几秒钟或一条“主机不可达”消息,那就糟了。当然,如果你 ping 的主机在另一个大陆或者通过卫星链接连接,ping 次数会比你桌子底下的主机多。
我们刚刚使用了ping
命令来测试我们的路由,如下所示:
$ ping 192.168.0.50
PING 192.168.0.50 (192.168.0.50) 56(84) bytes of data.
64 bytes from 192.168.0.50: icmp_seq=1 ttl=64 time=1.24 ms
ping
命令可以接受以下参数。关于其他参数,请参考man
页。
ping –c <count> –i <interval> –I <interface address> –s <packet size> destination
ping
命令将无限期地向主机发送 ping 命令,除非您通常使用 Ctrl+C 停止它,或者使用–c
number
选项给它提供 ping 命令的次数。
您也可以将 pings 的间隔表示为–i
number
(以秒为单位),并选择您希望使用的接口作为源地址,通过-I
IP address
或接口名称指定,如:-I enp0s8
。如果您有多个接口,并且希望测试其中一个,这将非常方便。如果没有定义地址,它通常会使用主机上的主接口 ping,通常是 eth0。您还可以使用-s
number of bytes
指定数据包大小,这对于测试带宽问题或 MTU 设置问题非常有用。
Note
正如本章前面提到的,MTU 是最大传输单位。它用于将数据包的大小限制在该网络上的网络设备能够处理的范围内。通常它被设置为 1,500 字节,但是对于巨型帧,它可以高达 9,000 字节。拥有更大的数据包意味着您可以更高效地发送更多数据,因为通过网络传输的数据包更少。
要测试您的网络,您可以做的第一件事就是使用ping
ping 您已经配置的接口。如果它们响应来自您自己主机的 pings,则它们已启动,您的接口正在响应 TCP 流量。您可以这样做:
ping 192.168.0.253
PING 192.168.0.253 (192.168.0.253) 56(84) bytes of data.
64 bytes from 192.168.0.253: icmp_seq=2 ttl=128 time=1.68 ms
在这里,我们向主机的本地 IP 地址发送了一个 ping 命令,我们可以看到一系列的响应,表明已经建立了一个连接以及连接所用的时间。如果我们没有收到响应,我们就会知道我们的接口或网络有问题。
下一步是 ping 网络上的另一台主机,比如您的默认网关或 DNS 服务器(这两台主机对您的互联网通信至关重要)。
ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=128 time=2.97 ms
如果您可以到达那里,您就知道您的主机可以到达其他主机。然后,您可以 ping 您网络外的一台主机,比如说 www.ibm.com
或 www.google.com
,并测试它的响应:
ping www.google.com
PING www.l.google.com (150.101.98.222) 56(84) bytes of data.
64 bytes from g222.internode.on.net (150.101.98.222): icmp_seq=1 ttl=59 time=20.0 ms
当您在连接到互联网上的主机时遇到问题,可能有多种原因。在某些情况下,部分互联网会因为核心路由器损坏而中断。在这种情况下,您的所有专用网络 ping 都将返回,但对互联网上主机的某些 ping 可能不会返回。如果您没有从互联网上的一台主机得到响应,请尝试另一台主机,看看问题是在本地还是在其他地方。一些远程网络会主动阻止 ICMP(互联网控制消息协议)流量。这些主机不会响应 pings,因此您应该在惊慌之前检查其他主机的响应。在这些情况下,将您的调查与其他工具结合起来也很方便,其中之一就是mtr
。
平均拆卸时间(Mean Time of Remove)
如果您可以 ping 通网络内部的主机,但无法 ping 通网络外部的主机,您可以使用 traceroute 或 mtr 等工具进行故障排除。两者都提供类似的服务:它们跟踪到达目的主机的路由。两者都使用“TTL 在传输中过期”消息来记录沿途的主机。这些消息是什么意思?嗯,正如我们已经解释过的,TTL 是用来杀死 TCP/IP 包的,这样它们就不会像大型强子对撞机中丢失的粒子一样在互联网上不停地闪烁。这些命令利用礼貌的路由器,当它们杀死你的包时,发送回“TTL 在传输中过期”的消息。
让我们看一个例子。如果我们对 www.ibm.com
执行 ping 操作,并将 TTL 设置为1
,它将到达路径上的第一个路由器,无论 www.ibm.com
解析为什么。第一个路由器查看 TTL,发现它是1
。它现在会丢弃数据包并发送传输中过期的消息。
ping -t 1 -c 1 www.ibm.com
PING www.ibm.com.cs186.net (129.42.60.216) 56(84) bytes of data.
From 192.168.0.254 (192.168.0.254) icmp_seq=1 Time to live exceeded
--- www.ibm.com.cs186.net ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
mtr
和traceroute
应用程序使用发回的数据包来发现路由器的 IP 地址(因为包含回复的 TCP/IP 数据包将保存此信息)。然后显示该信息并发送下一个 ping,这次 TTL 设置为2
。一旦 ping 到达我们的目的地,我们应该会收到标准的回应。一些路由器被配置为不发送这些 ICMP 消息,并在跟踪输出中显示为空白。
看看 mtr 的输出。这里,我们使用 mtr 跟踪主机au-mel-centos-1
和 www.ibm.com
之间的路由,命令如下:
sudo /usr/sbin/mtr www.ibm.com --report
Start: Tue May 17 18:04:01 2016
HOST: au-mel-centos-1 Loss% Snt Last Avg Best Wrst StDev
1.|-- 192.168.0.254 0.0% 10 2.7 2.4 1.8 3.2 0.0
2.|-- lnx20.mel4.something.net 0.0% 10 444.7 339.7 231.5 514.1 101.8
3.|-- xe-0-3-2.cr1.mel4.z.net 0.0% 10 456.4 332.2 211.5 475.6 103.0
4.|-- ae0.cr1.mel8.boo.net 0.0% 10 463.3 338.3 240.2 463.3 91.1
5.|-- ??? 100% 10 0.0 0.0 0.0 0.0 0.0
6.|-- a104-97-227-232.deploy.st 0.0% 10 476.3 341.9 229.3 476.3 97.0
因为我们使用了--report
开关,所以直到至少发送了十个包,才会显示输出。该命令的输出显示,我们的第一跳(我们经过的每个主机/路由器称为一跳)是我们的防火墙路由器。接下来是我们 ISP 的互联网连接的默认网关。当我们经过沿途的每一跳时,我们记录下关于我们路线的信息。在倒数第二跳,我们到达了 IBM gateway。如果看到一个???
,那就说明路由器已经被设置为拒绝返回 ICMP 数据包,mtr 因为没有收到“TTL 在传输中过期”的消息,所以打印了???
。一些网络管理员这样做是因为他们认为 ICMP 是一个安全漏洞。
更多关于 ICMP 的一些安全漏洞,请阅读: http://resources.infosecinstitute.com/icmp-attacks/
。
tcpdump 命令
您无法轻易查看第 1 层的通信,但您可以使用数据包嗅探软件查看第 2 层和第 3 层的通信。查看这些细节的一个应用程序是tcpdump
命令行工具。tcpdump
命令以及类似的命令可以在网络上查看数据包级别的流量。您可以看到进出主机的数据包。tcpdump
命令在没有任何表达式的情况下运行时,将打印通过接口的每个数据包。您可以使用表达式来缩小它将显示的数据包类型的范围。更多信息见man tcpdump
页。
Note
你可以尝试的另一个程序叫做 Wireshark。它有一个非常好的图形用户界面,可以让您轻松地过滤流量。它还有一个名为tshark
的命令行实用程序,其操作方式与tcpdump
类似。WireShark 的一个优点是,您可以从tcpdump
(通过指定–w 选项)获取输出,并在 WireShark 中读取它,这使得查看信息变得更加容易。这里可以看到更多关于 Wireshark 的内容: http://www.wireshark.org/
.
为了向您展示如何建立网络连接,我们将建立一个从防火墙到邮件服务器的连接。为了说明会发生什么,我们将使用tcpdump
命令,输出如下所示:
sudo /usr/sbin/tcpdump -i enp0s3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 96 bytes
19:26:35.250934 ARP, Request who-has 192.168.0.1 tell 192.168.0.254, length 46
19:26:35.475678 ARP, Reply 192.168.0.1 is-at 00:50:56:a9:54:44 (oui Unknown), length 28
19:31:17.336554 IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [S],
seq 3194824921, win 29200, options [mss 1460,sackOK,TS val 47080429
ecr 0,nop,wscale 7], length 0
19:31:17.619210 IP 192.168.0.1.smtp > 192.168.0.254.33348: Flags [S.],
seq 2011016705, ack 3194824922, win 65535, options [mss 1460], length 0
19:31:17.619249 IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [.],
ack 1, win 29200, length 0
19:31:17.900048 IP 192.168.0.1.smtp > 192.168.0.254.33348: Flags [P.],
seq 1:42, ack 1, win 65535, length 41
19:31:17.900081 IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [.],
ack 42, win 29200, length 0
我们已经发出命令,告诉它转储通过 enp0s3 接口的所有流量。我们使用-i 选项来指定要检查哪个接口。在输出中,我们可以将这些行分解如下:
timestamp source.port > destination.port : flags
在前面的输出中,前两行包含告诉您命令正在做什么的信息,在本例中是listening on enp0s3
。其余的都是真正的数据包。每行的第一个数字,例如19:26:35.250934
,是时间戳。
ARP, Request who-has 192.168.0.1 tell 192.168.0.254
第一个字段(去掉时间戳)是 TCP/IP 模型中的协议。这是一个 ARP 请求,ARP 运行在 TCP/IP 协议栈的第 2 层(或数据链路层)。ARP 用于匹配 MAC 地址和 IP 地址。可以看到 192.168.0.254 想知道谁有 192.168.0.1。有一个 ARP 回复说 192.168.0.1 在 MAC 地址00:50:56:a9:54:44
。
ARP, Reply 192.168.0.1 is-at 00:50:56:a9:54:44
既然 192.168.0.254 知道了要将它的数据包发送到哪里,它就试图通过发送一个 SYN 数据包来建立一个套接字,Flags [S]
。SYN 数据包携带 SYN 位组,初始序列号为seq 3194824921
。
IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [S], seq 3194824921,
win 29200, options [mss 1460,sackOK,TS val 47080429 ecr 0,nop,
wscale 7], length 0
来源和目的地由192.168.0.254 > 192.168.0.1.smtp
描述,其中。smtp
是我们正在连接的端口。该端口映射到端口 25。这是正在建立的与 SMTP 邮件服务器的连接。
再来看下一部分:Flags [S]
。源和目的地后面的[S]表示这是一个 SYN 请求,我们正在建立连接。接下来是数据包的初始序列号3194824921
。序列号是随机生成的,用于对数据包进行排序和匹配。该数据包的长度为0
,这意味着它是一个零字节数据包(即,它不包含任何有效载荷)。
其他标志win 29200, options [mss 1460,sackOK,TS val 47080429 ecr 0,nop,wscale 7]
提供通信中的其他信息,如滑动窗口大小、最大分段大小等等。
Note
更多信息,请参见 http://www.tcpipguide.com/free/
t_TCPMaximumSegmentSizeMSSandRelationshiptoIPDatagra.htm.
下一个包是192.168.0.1
的回复。
IP 192.168.0.1.smtp > 192.168.0.254.33348: Flags [S.], seq 2011016705,
ack 3194824922, win 65535, options [mss 1460], length 0
该数据包具有Flag [S.]
集合和序列号2011016705
。[S.]是一个 SYN ACK(准确地说是无标志),这是对 SYN 数据包的响应。序列号是另一个随机生成的数字,数据有效载荷也是零,(length 0)
。附加到该序列的是 ACK 响应ack 3194824922
。这是增加了 1 的原始初始序列号,表示它正在确认我们的第一个序列。
下一个数据包是由始发主机发送的另一个确认数据包:
IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [.],
ack 1, win 29200, length 0
在这个输出中,点(.)
表示没有设置标志。ack 1
表示这是一个确认包,从现在开始,tcpdump
将显示当前序列和初始序列之间的差异。这是在两台主机之间建立连接所需的最后一次通信,称为三次握手。
最后两个包是数据的交换。
IP 192.168.0.1.smtp > 192.168.0.254.33348: Flags [P.],
seq 1:42, ack 1, win 65535, length 41
邮件服务器正在向 192.168.0.254 上的客户端发送消息,如[P.] seq 1:42, ack 1
所示。这是将[P.], 41
字节的数据推入有效载荷,并确认之前的通信(ack 1
)。
IP 192.168.0.254.33348 > 192.168.0.1.smtp: Flags [.],
ack 42, win 29200, length 0
最后一次通信是 192.168.0.254 确认该数据包,ack 42
。
现在,您已经知道了如何使用数据包嗅探程序(如tcpdump
)在最基本的层面上查看两台主机之间的通信,让我们来看看另一个有用的工具netcat
。
Note
如果你有兴趣深入探讨tcpdump
和连接建立,可以试试下面这篇文章: http://www.linuxjournal.com/article/6447
。
Netcat 工具
可以用来诊断网络问题的另一个非常有用的工具是nc
或ncat
命令。您可以使用这个工具来测试您的能力,不仅可以到达其他主机,还可以到达它们可以监听的端口。
当您想测试通过防火墙到端口的连接时,这个工具特别方便。让我们测试一下我们的防火墙是否允许我们从主机 192.168.0.254 连接到主机 192.168.0.1 上的端口 80。
首先,在主机 192.168.0.1 上,我们将确保我们已经停止了 web 服务器。例如,我们发出以下命令:
sudo systemctl stop httpd
然后,我们将在 IP 地址为 192.168.0.1 的主机上使用-l
或 listen 选项启动nc
命令。
sudo nc -l 80
这将我们的nc
命令绑定到端口上的所有接口。我们可以通过运行另一个名为 netstat 的命令进行测试:
sudo netstat –lpt
tcp 0 0 *:http *:* LISTEN 18618/nc .
我们启动了带有三个选项的netstat
命令。–l
选项告诉netstat
命令列出监听套接字。–p
选项告诉netstat
显示哪些应用程序正在使用每个连接,最后一个选项–t
告诉netstat
只寻找 TCP 连接。
netstat
命令显示监听主机上某些端口的程序。我们可以在前面的输出中看到,18618
的 PID 程序nc
正在监听端口 80 上的 TCP 连接。*:http
表示它正在监听端口 80 上所有可用的地址(网络接口 IP 地址)(http
端口映射到端口 80)。好了,我们知道我们的nc
命令正在监听并等待连接。接下来,我们测试从 IP 地址为 192.168.0.254 的主机进行连接的能力。
我们将使用nc
命令连接到主机 192.168.0.1 上的端口 80,如下例所示:
nc 192.168.0.1 80
hello host
nc
程序允许我们测试两台主机之间的连接,并向远程主机发送文本。当我们在连接窗口中键入文本并按 Enter 键时,我们将看到我们键入的内容在au-mel-centos-1
主机上得到回应。
sudo nc -l 80
hello host
我们现在知道我们的主机可以连接到端口 80 上的au-mel-centos-1
主机,确认我们的防火墙规则正在工作(或者如果我们试图阻塞端口 80,这种情况可能过于宽松)。
你喜欢吗?
dig
是解决 DNS 问题的另一个便捷工具。如果你将这个工具与其他工具如ping
和nc
结合使用,你将能够解决许多问题。dig
命令是域名信息搜索工具(domain information groper)的缩写,用于查询 DNS 服务器。简单地说,该命令将通过查询在/etc/resolv.conf
文件中找到的nameserver
来解析一个完全合格的域名。
/etc/resolv.conf
文件用于存储nameserver
信息,以便您的主机知道查询哪个 DNS 服务器进行域名解析。一个/etc/resolv.conf
文件看起来如下:
sudo cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search example.com
nameserver 192.168.0.1
nameserver 192.168.0.254
首先,您可以看到resolv.conf
文件是由 DHCP 客户端生成的。一般来说,这个文件应该不需要编辑;通常它会被网络管理器覆盖。默认的search
域是example.com
,任何主机名搜索都会将该域附加到查询的末尾。接下来,我们有我们希望查询域名解析的nameserver(s)
。这些应该是 IP 地址格式。如果第一个nameserver
不可用,将使用第二个。
除非另有指示,否则dig
命令将查询这些nameservers
。让我们看看这个查询。
dig www.google.com
; <<>> DiG 9.10.3-P4-Ubuntu <<>> www.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16714
;; flags: qr rd ra; QUERY: 1, ANSWER: 12, AUTHORITY: 4, ADDITIONAL: 5
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.google.com. IN A
;; ANSWER SECTION:
www.google.com. 233 IN A 150.101.161.181
www.google.com. 233 IN A 150.101.161.187
www.google.com. 233 IN A 150.101.161.146
www.google.com. 233 IN A 150.101.161.152
www.google.com. 233 IN A 150.101.161.153
www.google.com. 233 IN A 150.101.161.159
www.google.com. 233 IN A 150.101.161.160
www.google.com. 233 IN A 150.101.161.166
www.google.com. 233 IN A 150.101.161.167
www.google.com. 233 IN A 150.101.161.173
www.google.com. 233 IN A 150.101.161.174
www.google.com. 233 IN A 150.101.161.180
;; AUTHORITY SECTION:
google.com. 10960 IN NS ns4.google.com.
google.com. 10960 IN NS ns2.google.com.
google.com. 10960 IN NS ns1.google.com.
google.com. 10960 IN NS ns3.google.com.
;; ADDITIONAL SECTION:
ns1.google.com. 9192 IN A 216.239.32.10
ns2.google.com. 13861 IN A 216.239.34.10
ns3.google.com. 9192 IN A 216.239.36.10
ns4.google.com. 2915 IN A 216.239.38.10
;; Query time: 28 msec
;; SERVER: 192.168.0.254#53(192.168.0.254)
;; WHEN: Sun Jul 17 15:43:41 AEST 2016
;; MSG SIZE rcvd: 371
在ANSWER SECTION
中,你可以看到 www。谷歌。主机名将解析为 12 个可能的 IP 地址。AUTHORITY SECTION
告诉我们哪个nameservers
负责为 www 提供 DNS 信息。谷歌。com 。ADDITIONAL SECTION
告诉我们AUTHORITY SECTION
中的域名服务器将解析到什么 IP 地址。
IN A
表示互联网地址(或相对记录)。IN NS
表示一个nameserver
记录。在前面代码的三个部分中显示的数字,如 233、10960 和 9192,表示记录被缓存的时间(以秒为单位)。当它们达到零时,nameserver
将查询权威 DNS 服务器以查看它是否已经改变。
在dig
输出的底部,您可以看到提供响应的SERVER
、192.168.0.254
,以及查询花费的时间28 msec
。
你可以通过使用@
符号使用dig
来查询特定的nameserver
,这里我们使用的是谷歌公共 DNS 服务器之一。您还可以使用–t
type
选项查询某些记录类型。例如,如果我们想测试我们的 DNS 服务器是否正常工作,我们可以使用dig
来查找 Google 邮件服务器的 IP 地址。
dig @8.8.8.8 –t MX google.com
<snip>
;; QUESTION SECTION:
;google.com. IN MX
;; ANSWER SECTION:
google.com. 392 IN MX 20 alt1.aspmx.l.google.com.
<snip>
google.com. 392 IN MX 10 aspmx.l.google.com.
;; AUTHORITY SECTION:
google.com. 10736 IN NS ns4.google.com.
google.com. 10736 IN NS ns3.google.com.
google.com. 10736 IN NS ns1.google.com.
google.com. 10736 IN NS ns2.google.com.
;; ADDITIONAL SECTION:
aspmx.l.google.com. 55 IN A 64.233.189.27
aspmx.l.google.com. 112 IN AAAA 2404:6800:4008:c03::1b
<snip>
ns3.google.com. 8968 IN A 216.239.36.10
ns4.google.com. 2691 IN A 216.239.38.10
<snip>
我们可以使用这些信息并比较其他nameservers
的反应。如果我们的nameserver
提供了相同的信息,我们的 DNS 服务器工作正常。如果有差异或者我们没有返回结果,我们将不得不进一步调查我们的 DNS 设置。在第九章中,我们将更详细地讨论 DNS 和dig
命令。
其他故障排除工具
我们刚刚讨论的程序涵盖了基本的网络故障排除。还有许多其他网络工具可以进一步帮助诊断问题。我们简要介绍了 netstat 命令,但是还有许多其他命令。表 7-4 列出了一些最常见的故障排除命令及其描述。
表 7-4。
Other Handy Network Diagnostic Tools
| 工具 | 描述 | | --- | --- | | `netstat` | 这个工具给出了你的主机上正在监听的内容的状态以及更多信息,包括路由和统计数据。 | | `host` | 另一个诊断 DNS 服务器的工具。我们将在第九章的中告诉你如何使用`host`。 | | `openssl s_client` | 这对于测试 SSL 连接非常有用,因为它可以尝试建立到远程主机端口的 SSL 连接。 | | `arp` | 这个程序查询和管理 ARP 缓存表,并允许您删除 ARP 条目。 |表 7-4 中的有用工具列表绝非详尽无遗。然而,只需使用其中的一些工具,您就可以诊断许多常见问题。
添加路由和转发数据包
您将使用ip
命令做的另一件常见事情是向您的主机添加路由。路由是主机访问其它网络或其它主机时应该遵循的路径。
IP Forwarding
默认情况下,Linux 主机通常关闭 IP 转发。IP 转发允许您的主机充当路由器,将网络中主机发送给它的数据包定向到目的主机。如果您的主机打开了 IP 转发,您的主机将能够将数据包从一个接口转发到另一个接口或从一个网络转发到另一个网络。这是一个内核级函数,可以通过编辑/etc/sysctl.conf
文件来打开或关闭。这个文件允许您在运行时配置内核参数。您可以在sysctl.conf
文件中设置许多其他参数,包括内存、交换和其他与网络相关的内核参数,这些参数可以在运行时进行调整。
内核将这类信息存储在/proc
目录中。例如,IP 转发设置位于/proc/sys/net/ipv4/ip_forward
文件中。这个文件系统是由内核在启动时创建的,直接对其进行的更改不会在重新启动后保持不变。如果将其设置为0
,IP 转发将被禁用,您的主机将不会传递任何目的地不是它的数据包。如果设置为 1,IP 转发会将那些不是发往它的数据包重定向到它们的目的主机。
要使设置在重启后保持不变,您需要取消对/etc/sysctl.conf
中下面一行的注释,保存文件,然后发出sysctl –p
命令将更改加载到内核中:
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
您还可以通过将数字 1 回显到文件/proc/sys/ net/ipv4/ip_forward
中来立即打开数据包转发,如下所示:
echo 1 > /proc/sys/net/ipv4/ip_forward
此更改不会在重启后持续,但编辑/etc/sysctl
会使其永久化。
您也可以为 IPv6 接口配置 IP 转发。类似地,我们需要将net.ipv6.conf.all.forwarding=1
添加到sysctl.conf
文件中,或者再次将 1 回显到/proc/sys/net/ipv6/conf/all/forwarding
中。
有关sysctl.conf
和sysctl
使用的更多信息,请阅读手册页。
我们想向您展示一个如何使用 ip 命令添加路由的示例。首先,我们将解释我们想要实现的目标。我们将通过防火墙将流量从一个网络路由到另一个网络。我们位于主服务器主机上,其 IP 地址为 192.168.0.1,即图 7-13 中的主机 A。我们的防火墙/路由器位于网络中,接口 enp0s8(主机 b)的 IP 地址为 192.168.0.254。我们在防火墙主机上配置了接口 enp0s9,地址为 192.168.1.254/24。网络 192.168.1.0/24 将成为我们的无线网络,我们将把它划分到自己的子网中。在 IP 地址为 192.168.1.220 的网络中,有一台我们希望与之通信的主机,即主机 c。图 7-13 提供了我们的网络图。
图 7-13。
Adding a route
主机 A 和主机 C 已正确配置为在网络间路由。在路由表中,它们通过默认网关发送所有发往其它网络的请求。在这种情况下,它们的默认网关是防火墙/路由器,默认网关的地址分别是 192.168.0.254 和 192.168.1.254。主机 A 不知道主机 B 的 enp0s9 接口连接了 192.168.1.0/24 网络,主机 C 也不知道主机 B 的 enp0s8 接口连接了 192.168.0.0/24 网络。
Note
我们将使用 ip 命令来浏览路由表。但是首先你需要知道有不同的路由表。默认情况下,有一个主要的,本地和默认。也可以添加自己的。您可以通过发出ip route show table local|main|default|number.
来查看不同的表。当我们发出ip route show
命令时,我们看到的是主表,相当于ip route show table main
。
让我们查看主机 A 的路由表。通过发出以下命令,我们可以列出主机 A 的路由表:
sudo /sbin/ip route show
192.168.0.0/24 dev enp0s8 proto kernel scope link src 192.168.0.1
default via 192.168.0.254 dev enp0s8 scope link
路由表显示了该主机知道的网络。它知道自己的网络,如192.168.0.0/24 dev enp0s8 proto kernel scope link src 192.168.0.1
所示。
可以看到默认路线,default via 192.168.0.254 dev enp0s8 scope link
。默认路由指向网络中的主机,该主机可以处理其网络中主机的路由请求。这些设备通常连接有多个接口或 IP 地址网络,因此可以将路由请求沿路由路径传递到主机,进而到达最终目的地。
让我们将路由表与主机 B 路由表进行比较。主机 B 是我们的网络路由器,因此它应该有多个网络连接到其接口。
sudo /sbin/ip route show
192.168.0.0/24 dev enp0s8 proto kernel scope link src 192.168.0.254
192.168.1.0/24 dev enp0s9 proto kernel scope link src 192.168.1.254
10.204.2.10 dev dsl-provider proto kernel scope link src 10.0.2.155
default dev dsl-provider scope link
首先让我们来看看主机 b 上的default
路由。它表示它不知道的任何东西都将从dev dsl-provider
发出。设备dsl-provider
是我们到 ISP 的 PPP 链接。第一行与该路线相关。它显示网络 10.204.2.10 是通过设备dsl-provider
和 10.0.2.155 的link src
地址到达的。10.204.2.10 主机位于我们的 ISP 中,在我们建立 PPP 连接时由 ISP 分配给我们。
在主机 C 上,我们有这样的路由配置:
sudo /sbin/ip route show
192.168.1.0/24 dev enp0s8 proto kernel scope link src 192.168.0.220
default via 192.168.1.254 dev enp0s8 scope link
我们知道,主机 A 和主机 C 位于不同的网络中,它们本身无法相互联系。对于我们来说,要建立一个简单的连接,比如从主机 A 到主机 C 的ping
连接,TCP/IP 数据包必须通过主机 b。ping
命令向命令行中指定的主机发送 ICMP 回应请求。回应请求是一种定义好的协议,它向发出请求的主机传达计算机语言“我在这里”
Note
互联网控制消息协议(ICMP)是一种 TCP/IP 协议,用于在主机之间发送消息,通常是错误消息;但是在ping
的情况下,它也可以发送信息性的 echo 回复。
因此,让我们看看是否可以通过在主机 A 上发出ping
命令从主机 A 到达主机 C。
ping –c 4 192.168.1.220
PING 192.168.1.220 (192.168.1.220) 56(84) bytes of data.
64 bytes from 192.168.1.220: icmp_seq=1 ttl=64 time=1.79 ms
我们使用了ping
命令,这是一种发送网络回应的方式,带有–c 4
选项来限制回复给4
的回应数量。这足以确认我们可以从我们的主机 a 到达我们的主机 C。这是相对容易的。让我们看一个稍微不同的场景,其中我们必须添加自己的路由。你可以在图 7-14 中看到它的示意图。
图 7-14。
Adding another route
在这种情况下,我们假设主机 D 试图通过主机 E 到达主机 F。主机 E 有两个以太网设备 enp0s8 和 enp0s9。设备 enp0s8 连接到 IP 地址为 192.168.0.2 的 192.168.0.0/24 网络,enp0s9 连接到 IP 地址为 192.168.10.0/24 的 192.168.10.2 网络。主机 D 位于 192.168.0.0/24 网络中,IP 地址为 192.168.0.50。主机 D 的默认路由是 192.168.0.254。主机 F 位于 192.168.10.0/24 网络中,IP 地址为 192.168.10.100。主机 F 的默认路由是 192.168.10.254。
让我们看看它们的路由表:
Host D
192.168.0.0/24 dev enp0s8 proto kernel scope link src 192.168.0.50
default via 192.168.0.254 dev enp0s8 scope link
Host E
192.168.0.0/24 dev enp0s8 proto kernel scope link src 192.168.0.2
192.168.10.0/24 dev enp0s9 proto kernel scope link src 192.168.10.2
default via 192.168.0.254 dev enp0s8 scope link
Host F
192.168.10.0/24 dev enp0s8 proto kernel scope link src 192.168.10.100
default via 192.168.10.254 dev enp0s8 scope link
您可以看到,主机 E 包含连接了两个不同网络的两个接口。要让主机 D 看到主机 F,我们需要告诉主机 D 通过主机 e 到达主机 F。我们通过添加如下路由来实现:
sudo /sbin/ip route add 192.168.10.0/24 via 192.168.0.2 dev enp0s8
这里,我们必须使用 ip 命令和 route 对象来添加从主机 d 到 192.168.10.0/24 网络的路由。我们为该命令提供主机的 IP 地址 192.168.0.2,它是我们网络中通往目的网络的路由器。
既然主机 D 有到达 192.168.10.0/24 网络的路径,我们应该能够 ping 通主机 F,对吗?
ping 192.168.10.100
PING 192.168.10.100 (192.168.10.100) 56(84) bytes of data.
似乎没有返回数据包,我们没有看到该命令的输出。如果我们通过尝试从主机 f ping 主机 D 来测试这一点会怎么样呢?我们使用–c 4
选项将发送到目的主机的 ping 次数限制为四次。
ping –c 4 192.168.0.50
PING 192.168.0.50 (192.168.0.50) 56(84) bytes of data.
--- 192.168.0.50 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 2999ms
当我们从主机 F ping 主机 d 时,我们的主机看不到彼此。这是为什么?这是因为主机 F 对 192.168.0.0/24 网络一无所知。该主机会向其默认网关发送它不知道的任何信息。因为主机 F 的默认网关没有配置为知道将数据包发送到 192.168.0.50 的位置,所以它会将数据包发送到默认网关。最终这些数据包会死亡。
Note
TCP/IP 协议的一部分是 TTL(生存时间),在一段时间后,数据包会被上游路由器忽略和丢弃。TTL 由一个数字表示,现在通常是 64,但也可以是 32 或 128。当数据包通过每个路由器(或跳)时,它们会将 TTL 值减 1。如果 TTL 在到达路由器时为 1,并且该路由器不是最终目的地,则路由器将丢弃该数据包,并使用 ICMP 协议发送“TTL 在传输中过期”消息。您将很快在“MTR”部分看到这是多么有用。
那么我们如何解决这个问题呢?我们给主机 F 添加了一条路由,告诉它如何通过主机 e 向主机 D 发送数据包。
sudo /sbin/ip route add 192.168.0.0/24 via 192.168.10.2 dev enp0s8
现在,当主机 F 尝试 ping 主机 D 时,我们会得到以下结果:
ping 192.168.0.50
PING 192.168.0.50 (192.168.0.50) 56(84) bytes of data.
64 bytes from 192.168.0.50: icmp_seq=1 ttl=64 time=1.24 ms
添加到主机 F 的路由后,我们现在可以到达主机 d。结合所有这些信息,我们可以在脚本中使用这些命令来打开接口、添加 IP 地址和添加路由。
#!/bin/bash
# bring up the interface
ip link set enp0s8 up
# add an address
ip addr add 192.168.10.1/24 dev enp0s8
# add a route
ip route add 192.168.100.1 via 192.168.10.254 dev enp0s8
# ping the host
ping 192.168.100.1 –c 4
# bring down the route, remove the address and bring down the interface.
ip route del 192.168.100.1 via 192.168.10.254 dev enp0s8
ip addr del 192.168.10.1/24 dev enp0s8
ip link set enp0s8 down
exit 0
我们使用了相同的命令来控制我们的界面,打开界面,添加地址,然后添加路由。我又以同样的命令把它降下来。这种脚本可以用来将文件从一台主机复制到另一台主机,或者建立任何类型的连接。
现在让我们继续深入探讨如何使用一些简单的实用程序来测试连接和排除网络故障。
Netfilter 和 iptables
许多人现在明白了什么是防火墙,因为它们已经开始成为最简单的主机上的强制性要求。您可能已经熟悉了运行在您桌面上的防火墙。这些简单的防火墙可以用来阻止不需要的流量进出单个主机,但这是它们唯一能做的。
Netfilter 是一个复杂的防火墙应用程序,可以位于网络的外围或单台主机上。它不仅可以阻止不需要的流量并在网络中路由数据包,还可以控制流量。“塑造流量?”你可能想知道,“那是什么?”
数据包整形是改变进出网络的数据包的能力。您可以使用它来增加或减少某些连接的带宽,优化其他数据包的发送,或保证特定类型数据包的性能。这对于那些希望确保 VoIP 通话不会被下载 GoT 的人打断的公司来说是有益的。
Netfilter /iptables 如何工作
iptables
命令是 Netfilter 的用户空间管理工具。Netfilter 是由 Paul“Rusty”Russell 开创的,从 2.4 版本开始就存在于 Linux 内核中。它允许操作系统在内核级执行包过滤和整形,这使得它比用户空间程序受到的限制更少。这对于专用防火墙和路由器主机尤其有用,因为它可以显著提高性能。
Note
术语用户空间程序指的是最终用户用来配置操作系统的某个部分的工具。在这种情况下,内部操作系统组件称为 Netfilter,用户空间组件,即用于配置 Netfilter 的命令,称为iptables
。
包过滤和整形是根据一组标准或规则,在数据包进入或离开主机时更改或丢弃数据包的能力。Netfilter 通过在数据包进入、通过和/或离开主机时重写数据包报头来实现这一点。
Netfilter 是一种状态包过滤防火墙。存在两种类型的包过滤防火墙:有状态和无状态。无状态包过滤防火墙只检查数据包的报头来过滤信息。它孤立地看待每个数据包,因此无法确定数据包是现有连接的一部分还是孤立的恶意数据包。状态防火墙维护通过它的连接的状态信息。这允许防火墙根据连接状态过滤数据包,从而对您的流量进行更精细的控制。
Netfilter 是 Linux 内核的一部分,可以通过iptables
命令在用户空间进行控制和配置…在本章中,我们将经常使用iptables
来指代一般的防火墙技术。大多数基于 Linux 的发行版都有一个iptables
包,但是它们也有自己的工具来配置防火墙规则——cmd 和 ufw。
Netfilter 通过引用一组表来工作。这些表包含链,链又包含单独的规则。链条拥有一组有序且相似的规则;例如,控制传入流量的一组规则可以保存在一个链中。规则是基本的 Netfilter 配置项目,包含匹配特定流量并对匹配的流量执行操作的标准。
将主机当前正在处理的流量与这些规则进行比较,如果当前正在处理的数据包满足规则的选择标准,则执行该规则指定的操作(称为目标)。这些操作包括忽略数据包、接受数据包、拒绝数据包或将数据包传递给其他规则进行更精细的处理。我们来看一个例子;假设您的 web 服务器上的以太网接口刚刚收到来自 Internet 的数据包。根据您的规则检查该数据包,并将其与选择标准进行比较。选择标准可以包括诸如目的地 IP 地址和目的地端口之类的项目。在本例中,假设您希望允许网络接口上的传入 web 流量访问侦听 web 服务的 HTTP 端口 80。如果传入流量符合这些标准,您可以指定一个操作让它通过。
每个iptables
规则依赖于指定一组网络参数作为选择标准来为每个规则选择数据包和流量。您可以使用许多网络参数来构建每个iptables
规则。例如,两台主机之间的网络连接称为套接字。这是源 IP 地址、源端口、目的 IP 地址和目的端口的组合。要建立连接,这四个参数都必须存在,iptables
可以使用这些值来过滤进出主机的流量。此外,如果您观察基于 TCP/IP 的网络上的通信是如何执行的,您会发现三种协议是最常用的:Internet 控制消息协议(ICMP)、传输控制协议(TCP)和用户数据报协议(UDP)。iptables
防火墙可以轻松区分这些不同类型的协议和其他协议。
有了这五个参数(源和目的 IP 地址、源和目的端口以及协议类型),您现在就可以开始构建一些有用的过滤规则了。但是在你开始构建这些规则之前,你需要理解iptables
规则是如何构建和交互的。为了获得这种理解,您需要进一步理解一些初始的iptables
概念,例如表、链和策略,我们将在接下来讨论这些概念,并略微涉及网络地址转换(NAT)。
桌子
我们讨论过 Netfilter 拥有规则表,可以与流量进行比较,可能会导致采取一些行动。Netfilter 有四个内置表,可以保存处理流量的规则。第一个是filter
表,这是用于所有与流量过滤相关的规则的默认表。第二个是nat
,处理 NAT 规则。接下来是mangle
表,它涵盖了各种数据包变更功能。有一个raw
表,用于使数据包免于连接跟踪,它在任何其他 Netfilter 表之前被调用。最后是security
表,用于强制访问控制(MAC)网络规则,在过滤表之后处理。这是 SELinux 之类的模块使用的。
链
每个 Netfilter 表filter, nat, mangle
、raw and security
都包含一组预定义的钩子,Netfilter 将按顺序处理这些钩子。这些挂钩包含称为链的有序规则分组。每个表都包含表中内置的默认链。表 7-5 中描述了内置链条。
表 7-5。
Built-in Chains
| 链子 | 描述 | | --- | --- | | `INPUT` | 用于对到达主机接口的数据包进行规则排序。仅在`filter`、`mangle and security`表格中找到。 | | `FORWARD` | 用于对发往另一台主机的数据包进行规则排序。仅在`filter`、`mangle and security`表中找到。 | | `OUTPUT` | 用于对来自主机接口的传出数据包的规则进行排序。在`filter`、`nat`、`mangle`、`raw and security`表中找到。 | | `PREROUTING` | 用于在数据包被路由到其他链之前改变数据包。在`nat`、`mangle`和`raw`表中找到。 | | `POSTROUTING` | 用于在数据包离开其他链并即将离开接口后更改数据包。仅在`nat`和 mangle 表中找到。 |每个链都与数据包通过主机的基本路径相关联。当 Netfilter 逻辑遇到一个数据包时,它首先评估该数据包的目的地是哪个链。并非所有表格都包含表 7-5 中列出的所有内置链。
让我们以filter
表为例。它仅包含INPUT, OUTPUT,
和FORWARD
链,并且是您最常配置的链。如果一个数据包通过网络接口进入主机,它需要通过INPUT
链中的规则进行评估。如果数据包由此主机生成,并通过网络接口发送到网络上,则需要通过OUTPUT
链中的规则对其进行评估。FORWARD
链用于已经到达本地网络接口但目的地是其他主机(例如,充当路由器的主机)的数据包。您可以在每个表中创建自己的链来保存额外的规则。您还可以将数据包流从内置链定向到您创建的链,但这只能在同一个表空间内进行。
现在让我们来探索一下数据包进入您的系统时的生命周期。我们将只关注filter
表,因为这是您最常处理的表。记住表格filter
包含三个内置链:INPUT, FORWARD,
和OUTPUT
。这些都有默认的ACCEPT
政策(我们很快就会谈到政策)。请看图 7-15 ,图中显示了一个普通的网络数据包如何流经filter
表。
图 7-15。
Traffic flow through the filter
table
在图 7-15 中,你可以看到数据包流经filter
表的方式。Netfilter 防火墙程序会根据 IP 数据包的目的地址将它们路由到INPUT
或FORWARD
链。它在 Netfilter 路由块中做出此决定,数据包在到达过滤器之前由 raw、mange 和 nat 表检查。
如果传入数据包的目的地是另一台主机,并且在防火墙主机上启用了 IP 转发,那么它们将被传送到FORWARD
链。一旦被该链中的任何规则集处理,如果允许,数据包将离开主机,否则将被丢弃(DROP
)。就像在OUTPUT
链中一样,这些数据包在离开网络之前,由 Netfilter 程序路由并传递到其他表(mangle,nat)。
如果数据包的目的地是防火墙主机本身,它们将被传递到INPUT
链,如果它们被该链中的任何规则集接受,它们将被传递到应用程序(通过安全表)。然后,应用程序可能希望发回一个响应。如果是的话,这个流量由OUTPUT
链管理。
OUPUT
链用于从实际的防火墙主机发送到别处的另一台主机的数据包。这些可以是从防火墙到远程套接字发起的新连接,也可以是已建立的数据包流的一部分。
Tip
把前面解释的鱼钩想象成一套鱼钩,用不同类型的鱼饵钓不同类型的鱼。当一种特定的鱼游过时,它会被某种诱饵所吸引。一旦它被钩住,我们就根据线末端的东西来决定它的命运。iptables 就像捞取网络数据包一样!
政策
过滤器表中定义的每个内置链也可以有一个策略。策略是链对数据包采取的默认操作,以确定数据包是否完全通过链中的规则,而不匹配任何规则。您可以对数据包使用的策略有DROP
、REJECT
和ACCEPT
。默认情况下,Ubuntu 和 CentOS 都将ACCEPT
作为所有表中所有链的默认策略。
DROP
策略在不通知发送者的情况下丢弃数据包,通常被描述为“丢弃到地板上”。REJECT
策略也会丢弃数据包,但是它会向发送方发送一个 ICMP 数据包,告诉发送方已经发生了拒绝。REJECT
策略意味着设备将知道其数据包没有到达目的地,并将快速报告错误,而不是像DROP
策略那样等待超时。DROP
政策与 TCP RFCs(请求评论)相反,对网络设备可能有点苛刻;具体来说,它们可以长时间等待来自它们丢弃的分组的响应。但是出于安全考虑,通常认为使用DROP
策略比REJECT
策略更好,因为它向外界提供的网络信息更少。
ACCEPT
策略接受流量,如果它没有被链中的规则捕获,就允许它通过防火墙。自然,从安全角度来看,如果将防火墙用作默认策略,它会使防火墙失效。如前所述,默认情况下,iptables
使用ACCEPT
策略配置所有链,建议对所有链将其设置为DROP
策略,这是最佳实践,但必须经过仔细考虑,因为如果操作不当,这可能会停止所有网络流量。
Caution
在远程主机上,很容易将主机与您用来配置它的网络隔离开来。在将策略更改为DROP.
之前,确保您已经配置了允许您连接的ACCEPT
规则
DROP
的默认策略符合防火墙“默认拒绝立场”的基本原则。默认情况下,您应该拒绝所有流量,只向您明确授予访问权限的流量开放主机。这种拒绝可能会有问题,因为为INPUT
和OUTPUT
链设置默认策略DROP
意味着不允许传入和传出流量,除非您明确添加允许流量进出防火墙主机的规则。同样,在这样做的时候需要一些小心和考虑,因为如果没有明确允许它们进入或离开,这将导致所有通过防火墙从您的主机或您的内部网络连接的服务和工具失败。
网络地址转换
网络地址转换允许您的专用网络 IP 地址空间看起来来自一个公共 IP 地址。它是在 IP 伪装的帮助下做到这一点的,IP 伪装会重写 IP 数据包报头。NAT 在转换表中保存有关穿越防火墙/路由器的连接的信息。一般来说,当数据包从私有地址空间穿越防火墙/路由器到达公有地址空间时,转换表中会写入一个条目。当匹配的数据包返回时,路由器使用转换表将返回的数据包与始发源 IP 进行匹配。
许多年前,互联网上的每台主机都被分配了一个公共 IP 地址,以便成为互联网的一部分并与其他主机通信。人们很快意识到,如果每台想上网的主机都有自己的公有 IP 地址,那么可用的地址就会用完。发明 NAT 是为了能够让私有地址空间看起来像来自单个 IP 地址。
The End of Nat
IPv6 当然将我们从 IPcalypse 中拯救了出来,并且不再需要 NAT 网络地址了。然而,虽然 NAT 是一种路由服务(相对于防火墙服务),但它确实为它隐藏的地址空间提供了一些安全性。NATs 隐藏我们“私有”网络地址空间的能力意味着许多主机和设备不必担心网络攻击(嗯,他们应该担心,但他们不担心)。
当我们考虑到每一个 IPv6 设备都可以从互联网到达,并且我们考虑到我们刚刚展示的防火墙链的默认规则时,我们的系统可能会在没有 NAT’ing 的安全遮羞布的情况下处于混乱状态。我们仍将有能力在 IPv6 中执行防火墙和路由操作,以保护我们的设备安全,但我们将不能只是“隐藏”我们的网络。
所以纳特死了。但是你仍然会看到它的存在——很多——直到 IPv6 更加普及。
使用防火墙-cmd 命令
对于 CentOS,正如我们提到的,Firewalld 是默认安装的。Firewalld 附带了两个配置工具,一个是 GUI firewall-config,另一个是 firewall-cmd 命令行工具。我们将向您展示如何使用此命令来管理您的主机。
首先是一些关于防火墙的背景。防火墙拥有大家熟悉的区域概念。区域是网络中不同信任级别的名称。从低信任度下降区域开始,逐步提升到公共、外部、隔离区、工作、家庭、内部和受信任区域的更高信任度。这个想法是,根据您的安全需求,将您的接口添加到其中一个区域。默认情况下,接口会添加到公共区域。
它还具有定义服务的能力。可以用简单的语法在 xml 格式的文件中定义服务。取/usr/lib/firewalld/services
目录下的https.xml
区域文件:
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>Secure WWW (HTTPS)</short>
<description>HTTPS is a modified ..<snip>.. be useful.</description>
<port protocol="tcp" port="443"/>
</service>
您可以在/etc/firewalld/services
目录中创建自己的服务文件。这些允许您在防火墙配置中将它们作为服务对象引用。
防火墙的配置选项可以在/etc/firewalld/firewalld.conf
和/etc/sysconfig/firewalld
中找到。在/etc/firewalld/firewalld.conf
中你可以设置默认区域和其他选项。在/etc/sysconfig/firewalld
中,您可以向 firewalld 守护进程添加任何参数。
默认情况下,防火墙不会在您的系统上运行。您需要启用它来使用它。您可以使用以下命令在防火墙服务上运行 stop | start | disable | enable | status:
sudo systemctl stop|start|disable|enable|status firewalld
您可以使用以下命令检查其运行状态:
sudo firewall-cmd –state
not running
要启动 firewalld,并确保它在重新启动主机时再次启动,您需要使用 systemctl 来启用并启动 firewalld 服务。启动后,我们可以查看哪些区域处于活动状态:
sudo firewall-cmd --get-active-zones
public
interfaces: enp0s8 enp0s9
要获取有关区域的信息,可以执行以下命令:
sudo firewall-cmd --zone=public --list–all
public (default, active)
interfaces: enp0s8 enp0s9
sources:
services: dhcpv6-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
在这里,我们可以看到公共区域是默认的,并且处于活动状态。我们还可以看到附加到它的接口。服务描述了允许访问的服务,DHCP 客户端和 SSH。DHCP 允许我们自动获取接口的 IP 地址。这些是在服务 xml 文件中定义的,如果需要,我们也可以使用端口。
如果要永久更改接口的区域,可以使用 nmcli 修改网络接口:
sudo nmcli c modify enp0s9 connection.zone dmz
这将把“ZONE=dmz”添加到接口配置文件/etc/sys config/network-scripts/if CFG-enp0s 9 中。在我们再次打开该界面之前,这不会起任何作用。
我们可以向标记为 dmz 的区域添加 http 服务。我们通过以下方式做到这一点:
sudo firewall-cmd --zone=dmz --add-service=https --permanent
如果我们要使一个改变成为永久性的,我们需要记住添加- permanent 选项。您可以在不丢失状态信息(不中断连接)的情况下重新加载配置,并且可以使用完整重新加载重新加载丢失状态(用户丢失连接)的配置:
sudo firewall-cmd reload
sudo firewall-cmd --complete-reload
在这里,您可以看到我们的隔离区现在连接了 https 和 ssh 服务:
sudo firewall-cmd --zone=dmz --list-all
dmz
interfaces:
sources:
services: https ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
但是你可以看到它没有接口。我们将向该接口添加 enp0s9,正如我们所说,该接口需要再次“升级”。
sudo nmcli c up enp0s9
现在,您应该能够访问运行在 enp0s9 接口上的 HTTPS web 服务了。
使用 ufw 命令
Ubuntu 还有一个从命令行操作防火墙规则的工具。它叫做ufw
,可以从ufw
包中获得。
Tip
我们将在第八章中讨论更多关于安装包的内容。
ufw 和 Firewalld 完全不同。在幕后,它使用直接的 iptables 指令来创建防火墙规则。如果我们查看/etc/ufw/目录中的规则文件,我们可以看到 ufw 用来创建 Netfilter 规则集的指令。
现在让我们展示一些基本命令。
您可以像这样启用或禁用 ufw:
sudo ufw enable|disable
要获得当前防火墙状态的输出:
sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] 22/tcp ALLOW IN Anywhere
[ 2] 22/tcp (v6) ALLOW IN Anywhere (v6)
也就是说,我们将允许来自任何网络(Anywhere
)的流量进入(ALLOW IN
),并且流量的目的地是端口 TCP 22(在 IPv4 和 IPv6 接口上)。
您可以添加另一个规则,如下所示,以允许 http 流量到达任何本地接口:
sudo ufw allow 80/tcp
Rule added
Rule added (v6)
sudo ufw status numbered
...
[ 3] 80 ALLOW IN Anywhere
[ 4] 80 (v6) ALLOW IN Anywhere (v6)
...
在上图中,您可以看到我们已经在所有 IPv4 和 IPv6 接口上添加了从任意位置访问端口 80 的功能。对于公共服务(即/etc/services 文件中列出的服务),也可以这样表达。
sudo ufw allow http
要删除规则,您可以使用删除命令:
sudo ufw delete 3
Deleting:
allow 80
Proceed with operation (y|n)? y
Rule deleted
我们需要在提示符下回答一个y
或n
来确认我们是否希望删除该规则。您也可以指定要删除的规则:
sudo ufw delete allow http
您还可以使用简化的语法来描述应用程序可能需要的规则。您可以看到 ufw 允许 TCP 端口 22 访问系统的方式(记住 TCP 端口 22 用于 OpenSSH)。缺省情况下,/ etc/ufw/applications . d/OpenSSH-server 文件用于配置端口 22 访问。
[OpenSSH]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=22/tcp
这里我们有名称空间[OpenSSH],后面是标题和描述。然后描述我们需要的端口,用“|”分隔多个端口和协议。例如,假设我们有一个 web 应用程序需要打开以下 TCP 端口,80、443 和 8080。我们可以通过添加文件/etc/ufw/applications . d/we B- server 来创建一个 ufw 应用程序,如下所示:
[WebServer]
title=Application Web Server
description=Application X web services
ports=80/tcp|443/tcp|8080/tcp
要查看我们的新配置,我们可以使用以下命令:
sudo ufw app info WebServer
sudo: unable to resolve host ubuntu-xenial
Profile: WebServer
Title: Application Web Server
Description: Application X web services
Ports:
80/tcp
443/tcp
8080/tcp
创建应用程序配置后,我们需要发出如下更新子命令:
sudo ufw app update WebServer
然后,要应用新的规则集,您可以发出类似这样的命令,只允许 192.168.0.0/24 地址范围内的主机。
sudo ufw allow from 192.168.0.0/24 to any app WebServer
Rule added
让我们稍微分解一下。我们说,我们希望从192.168.0.0/24
网络到本地主机上的any
地址的任何连接能够allow
到app WebServer
中列出的任何端口。现在列出我们已经完成的工作,我们将看到以下内容:
sudo ufw allow from 192.168.0.0/24 to any app WebServer
sudo ufw status numbered
Status: active
To Action From
-- ------ ----
[ 1] WebServer ALLOW IN 192.168.0.0/24
需要使用 ufw route 命令路由通过该主机的流量。例如,我们有 SSH 流量在 enp0s8 上进入,在 enp0s9 上离开,我们将这样编写 ufw 路由规则:
sudo ufw route allow in on enp0s8 out on enp0s9 to any port 22 proto tcp
这里我们说的是允许 SSH 流量(22)在 enp0s8 上进入,在 enp0s9 上离开,到达任何目的地 IP 地址。这将在 iptables 中创建一个规则,当使用 iptables -L 命令查看时,该规则如下所示:
Chain ufw-user-forward (1 references)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
让我们继续探索关于 iptables 的更多信息以及这意味着什么。
使用 iptables 命令
之前,我们已经描述了 Netfilter 中数据包流的概念,并介绍了可以用来管理它们的两个主要命令,firewall-cmd 和 ufw。重要的是,我们现在了解它们是如何工作和做什么的。我们现在将向您展示如何使用iptables
命令来管理 Netfilter。iptables
命令允许您执行以下操作:
- 列出数据包筛选器规则集的内容。
- 添加/删除/修改数据包筛选器规则集中的规则。
- 列出/清零数据包筛选器规则集的每规则计数器。
对于 IPv6,您使用 ip6tables 命令,但是从语法上来说,它是相同的命令,但是指示 Netfilter 如何对 IPv6 数据包进行操作。在本节中,我们将主要讨论 IPv4 命令,但 IPv6 的命令用法没有什么不同。为了有效地使用iptables
命令,您必须拥有 root 权限。基本的iptables
命令结构和参数如下:
iptables –t table-name command chain rulenumber paramaters –j target
表 7-6 给出了命令的概要,如前面的语法command
所示,我们将演示它们的描述。
表 7-6。
Command Options Available to the iptables
Command
Caution
当您使用防火墙规则时,如果您犯了一个错误并阻止了所有网络流量,那么访问系统控制台总是一个好主意。如果您犯了一个错误(每个人至少都会犯一个错误),那么更改网络上的防火墙规则,尤其是在远程系统上,会让您陷入尴尬的境地。
iptables –t table-name command chain rulenumber paramaters –j target
大量的参数,如上面的parameters
中的iptables
命令语法所示,可以用来操纵通过防火墙的数据包。当我们解释链条时,我们说它们就像钩子。这些参数是放在鱼钩上的不同类型的鱼饵。每个参数将根据包中的信息吸引包。它可以是数据包或协议的源地址和目的地址。此外,分组可以与源或目的地端口或者分组所处的状态相匹配。这些参数还可以用于匹配数据包、捕获数据包、标记数据包和释放数据包。
iptables –t table-name command chain rulenumber paramaters –j target
在iptables
命令语法中由–j
target
描述的目标参数是如果信息包被钩住时要对其执行的动作。常见的目标有ACCEPT, DROP, LOG
、MASQUERADE
和CONNMARK
。目标也可以是另一个用户定义的链。
我们现在想通过一些例子向你展示如何使用iptables
命令。
iptables
命令是 Ubuntu 和 CentOS 通用的,操作方式相同。让我们来看看列出我们当前运行的iptables
规则集的内容。我们通过发出以下命令来实现这一点:
sudo /sbin/iptables -t filter -L --line-numbers
这里我们正在查看filter
表。–L
选项列出了所有链及其相关的规则,每条链都有由--line-numbers
指定的行号。行号很重要,因为正如已经提到的,iptables 从第一个到最后一个按顺序贯穿每个规则。当您想要添加一个新规则或删除一个旧规则时,您可以使用这些数字来确定您想要的目标规则。清单 7-7 中列出了该命令的输出。
sudo /sbin/iptables -t filter -L --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
Listing 7-7.
iptables
filter table
这有点反高潮。默认情况下,我们在过滤表的任何链中都没有规则。这当然意味着在我们的主机上启动的任何服务都可以立即在我们的网络上开始通信。我们应该解决这个问题。
由你来设定最低的规则要求,我们会在进行过程中提供帮助。我们可以选择创建自己的链,这样我们就可以对防火墙规则进行分组。您不必创建新的链,但是如果您希望将所有规则与默认链分开,您可以创建新的链,我们可以将它们与逻辑业务组相关联。我们也可以通过逻辑网络组来定义这个链,我们将保持它的简单性,称它为IPV4-INCOMING
。
sudo /sbin/iptables –t filter –N IPV4-INCOMING
该命令使用filter
表中的–N IPV4-INCOMING
创建一个新的链,如–t filter
所示。它还没有任何关联的规则,但是在本节结束时,您将能够添加和删除规则。
Note
您不必使用前面的命名标准来命名链。但是,使用对您的配置有意义的东西会让您受益。否则,您的iptables
规则的输出可能看起来非常混乱,难以诊断错误。如果你不想的话,你也不需要创建你自己的用户定义的链,但是如果你这样做的话,会使阅读你的规则更简单。
通过列出我们的 iptables,您将看到我们创建的新链:
Chain IPV4-INCOMING (0 references)
num target prot opt source destination
它还没有规则,所以我们要创建一些。让我们从一个简单的规则开始…
sudo iptables -t filter -A IPV4-INCOMING -d 0.0.0.0/0 -s 0.0.0.0/0 -j ACCEPT
Chain IPV4-INCOMING (0 references)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere
该规则允许来自任何地方、任何端口的所有连接,相当于接受策略。我们将集中精力解释我们发出的命令,而不是它的优点。分解一下,我们再次在filter
桌上工作。接下来,我们向IPV4-INCOMING
链添加(-A
)一个规则。我们对- destination ( -d
)使用了简化的语法,并使用了0.0.0.0/0
的 anywhere IP 表示法来表明这个规则应该匹配我们本地主机上的所有 IPv4 地址。同样,对于- source ( -s
),我们接受该规则的所有源地址(0.0.0.0/0
)。最后,我们提供这个规则的目标(-j
),它将跳转到ACCEPT
目标。接受目标允许套接字建立连接。
好吧,这是一个错误,让我们取消这条规则。从上面的 iptables 列表中,我们可以看到我们想要删除的规则位于位置 1。我们将在删除该规则时使用它。
sudo /sbin/iptables –t filter –D IPV4-INCOMING 1
如果您再次列出这些表,我们会发现没有关联的规则。我们现在可以删除该链,因为它是空的。为此,我们发出以下命令:
sudo /sbin/iptables -t filter -X IPV4-INCOMING
整个链条都被拆了。您不能删除默认的输入、输出正向链。
我们将重新创建链,并添加一些规则,以便显示下一部分。这是我们的名单。
1 ACCEPT all -- anywhere anywhere ctstate INVALID
2 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
3 DROP all -- anywhere anywhere
4 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
如果这个规则集在输入链中,将会导致问题。让我们使用 iptables 命令来修复它。首先,我们需要将规则 4 移到规则 1 之上。为此,我们发布了以下内容:
iptables –t filter –I IPV4-INCOMING 1 –p tcp –-dport 22 –j ACCEPT
当您现在查看IPV4-INCOMING
链中的第三行时,您可以看到我们的规则已经被插入,并且具有目标ACCEPT
。
num target prot opt source destination
1 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
2 ACCEPT all -- anywhere anywhere ctstate INVALID
3 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
4 DROP all -- anywhere anywhere
5 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
我们将删除第 5 条规则,就像用–D IPV4-INCOMING 5
开关删除之前的规则一样。但是我们的规则看起来还是不对。规则 2 不应该接受连接,而应该丢弃它们。让我们用正确的规则替换那个规则(不要担心,我们很快会解释conntrack
是做什么的)。
sudo iptables -R IPV4-INCOMING 2 -m conntrack --ctstate INVALID -j DROP
1 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
2 DROP all -- anywhere anywhere ctstate INVALID
3 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
4 DROP all -- anywhere anywhere
看起来好多了。因此,像 Netfilter 防火墙一样从上到下阅读规则,我们允许 SSH 流量,丢弃无效流量,允许任何当前和已建立的流量,然后丢弃所有其他流量。
您还可以flush
您的链,这意味着从所有链中移除所有规则或者从指定链中移除所有规则。这可用于在添加新规则集之前清除任何现有规则。
Note
我们将很快向您展示如何保存您的 iptables,如果您不想丢失当前的设置,您可能需要在下一步之前做这件事。(提示:iptables-save > iptables.backup
)
您可以通过发出类似下面的命令来实现这一点:
sudo /sbin/iptables –t filter –F IPV4-INCOMING
这里我们已经清空了filter
表中IPV4-INCOMING
链的所有规则,如-F
所示。如果您现在查看filter
表中的INPUT
链,您将会看到不再有任何与它相关联的规则。
sudo /sbin/iptables -L IPV4-INCOMING --line-numbers
Chain IPV4-INCOMING (policy ACCEPT)
num target prot opt source destination
在这种情况下,由于我们有一个默认策略ACCEPT
,清除这个链并不影响我们主机的操作方式。如果我们将策略更改为DROP
并刷新链,所有入站连接都将被切断,使我们的主机无法用于网络相关的任务和服务。这是因为该策略决定了与任何规则都不匹配的数据包会发生什么情况。如果您的链中没有规则,那么iptables
将使用默认策略相应地处理数据包。
目前,我们已经能够随意更改我们的链,因为 Netfilter 没有配置为使用它。为了解析我们的IPV4-INCOMING
链中的规则,我们需要在INPUT
链中添加一个规则,将所有传入主机的数据包定向到IPV4-INCOMING
链。
sudo /sbin/iptables –t filter –A INPUT –j IPV4-INCOMING
num target prot opt source destination
1 IPV4-INCOMING all -- anywhere anywhere
我们已经在上面包含了 list ( –L
)命令的输出。这里,我们发出了将规则附加到输入链的命令。它是接收以我们的主机为最终目的地的防火墙入站数据包的第一个链。就像我们的其他规则一样,我们给它添加了-t filter –A INPUT
。具有任何协议的任何分组现在将被发送到链IPV4-INCOMING
,如- j IPV4-INCOMING
所示,用于进一步处理。
我们可能不希望所有的数据包都进入 IPV4 传入链。也许我们只想让 tcp 数据包进入该链,我们将在不同的链中处理 udp 数据包。您可以通过添加其他参数来细化您想要在规则中捕获的内容。在下面的例子中,我们可以只匹配 TCP 流量,并通过替换(-R
)我们的第一个输入规则将它发送到某个目标。
sudo /sbin/iptables –t filter –R INPUT 1 –p tcp –j IPV4-INCOMING
我们可以进一步完善我们的“诱饵”来吸引不同类型的鱼。。。呃。。。小包。也许我们只想要目的地址在 192.168.10.0/24 网络中的 tcp 数据包?看起来会像这样:
sudo /sbin/iptables –t filter –R INPUT 1 –s 0.0.0.0/0 –d 192.168.10.0/24 –p tcp –j IPV4-INCOMING
num target prot opt source destination
1 IPV4-INCOMING tcp -- anywhere 192.168.10.0/24
我们现在已经替换了一个规则,通过指定- R
到INPUT
链,该链仅定向具有tcp
协议的包,并且仅当它们的目的地地址在192.168.10.0/24
网络中。像这样的数据包被发送到IPV4-INCOMING
链。
最后,我们现在将在我们的INPUT
链上设置一个默认策略。我们将把它设置为DROP
,这样任何与我们的规则集不匹配的东西都将被自动“扔到地板上”我们通过指定表名(由–t filter
指定)、链(由INPUT
表示)和目标(??)来实现这一点。
Caution
这是一个有潜在危险的命令,可能会断开所有的网络连接。在运行这个命令之前,确保您可以访问物理控制台,以防万一。
sudo /sbin/iptables –t filter –P INPUT DROP
当我们现在在filter
表中列出INPUT
链时,默认策略显示为DROP.
sudo iptables -L INPUT
sudo /sbin/iptables -t filter -L --line-numbers
Chain INPUT (policy DROP)
num target prot opt source destination
1 IPV4-INCOMING all -- anywhere anywhere
记住将DROP
政策应用到你所有的连锁店是一个好的实践和好的习惯。为了使防火墙最安全,默认的拒绝策略应该在您的所有链中强制执行。
有了这些基本命令,您将能够在您的链和规则集上执行大多数功能。您可以将更多功能添加到您的规则中,使您的防火墙执行非常复杂和有趣的路由。请参阅iptables man
页,了解您可以执行的任务的完整列表。
您可以非常简单地保存和恢复 iptables 配置。Ubuntu 和 CentOS 都有相同的命令来完成这个任务。首先,让我们保存 iptables 规则:
sudo iptables-save > /path/to/your/iptables.bak
这里,我们发出了 iptables 命令,并将输出(>
)定向到文件系统中的一个文件。如果不将输出重定向到文件,它将打印到屏幕上。恢复这些文件也很简单。首先,我们可以使用以下命令对文件的语法进行测试:
sudo iptables-restore –t -v < /path/to/your/iptables.bak
Flushing chain `INPUT'
Flushing chain `FORWARD'
Flushing chain `OUTPUT'
# Completed on Fri May 20 21:49:49 2016
这显示了该命令的详细输出(-v ),并且如果您的配置文件中有错误(如iptables-restore: line 4 failed
),将会给出一个错误。要恢复 iptables 文件,您需要移除测试开关(-t
)。
在 Ubuntu 和 CentOS 上启动和停止 iptables 是不同的。在 Ubuntu 上,你可以做以下事情来添加和删除你的防火墙规则。你可以对你的规则做任何修改和补充。然后,您可以在您的/etc/network/interfaces
文件中使用以下内容来激活您的规则并再次保存它们。
auto enp0s3
iface enp0s3 inet dhcp
pre-up iptables-restore < /etc/network/firewall
post-down iptables-save -c > /etc/network/firewall
这里是 enp0s3 的标准接口配置。在调出界面之前,我们使用pre-up
命令激活防火墙规则。一旦我们的接口关闭,我们就使用post-down
命令保存我们的规则。
如果你在 Ubuntu 主机上使用ufw
,你可以使用systemctl
命令来停止和启动ufw
:
sudo systemctl start|stop|restart ufw
这里的systemctl
用于管理ufw
服务。
在 CentOS 机器上,因为它紧跟 Red Hat,所以需要安装管理 iptables 的常用工具(如果您还没有安装的话)。您需要下载并安装 iptables-services 包(yum install –y iptables-services
)来访问以下命令。
要启动和停止iptables
,您可以使用systemctl
命令:
sudo systemctl start|stop|restart iptables
这些操作现在应该不言自明了。你也可以使用status
到你期望的当前状态。当您执行stop
时,您当前的防火墙规则将被保存。
进一步阅读
Netfilter 和iptables
是复杂的主题,我们建议您进一步阅读它们。有关 Netfilter 和iptables
命令的更多信息,请阅读其man
页面。还提供了一些在线教程:
https://help.ubuntu.com/community/IptablesHowTo
http://www.linuxtopia.org/Linux_Firewall_iptables/index.html
Ubuntu 还会在本地硬盘上安装一些 iptables 文档:
/usr/share/doc/iptables/html/packet-filtering-HOWTO.html
/usr/share/doc/iptables/html/NAT-HOWTO.html
对于更高级的主题,您可能会感兴趣:
- 使用 netfilter、iproute2、NAT 和 L7-filter 设计和实现具有 QoS 的 Linux 防火墙
- Linux 防火墙:用 iptables、psad 和 fwsnort 进行攻击检测和响应
- 《Linux 防火墙:使用 nftables 增强安全性》(第 4 版)作者:Steve Suehring(Pearson Education 2015 年)
解释防火墙规则
现在是更仔细地研究您可能在主机上看到的防火墙规则的好时机。根据您的安装方法,CentOS 和 Ubuntu 都可以预装防火墙配置。像ufw
和firewalld
这样的工具都是管理防火墙的用户工具,它们试图以一种合理的方式做到这一点,并为您隐藏规则的复杂性。
针对 firewalld 或 ufw 的过滤器表的默认规则集可以超过 100 行,清单 7-8 显示了安装了 firewalld 的 CentOS 主机上过滤器表的输入链的输出(iptables-save
)。在清单 7-8 中,我们减少了输出并增加了行号来帮助澄清我们对输出的解释。
1\. *filter
2\. :INPUT ACCEPT [0:0]
3\. :INPUT_ZONES – [0:0]
4\. :INPUT_ZONES_SOURCE - [0:0]
5\. :INPUT_direct - [0:0]
6\. -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
7\. -A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
8\. -A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT
9\. -A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT
10\. -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
11\. -A INPUT -i lo -j ACCEPT
12\. -A INPUT -j INPUT_direct
13\. –A INPUT –j INPUT_ZONES_SOURCE
14\. –A INPUT –j INPUT_ZONES
15\. –A INPUT –p icmp –j ACCEPT
16\. -A INPUT -j REJECT --reject-with icmp-host-prohibited
Listing 7-8.Firewalld INPUT chain
Netfilter 喜欢以下格式的 iptables 规则配置:
* <table name>
<CHAIN> <POLICY> [<byte:counter>]
-A <CHAIN> <rule set>
COMMIT
* filter
是过滤表节的开始,每一行将被读入,直到COMMIT
语句。然后列出链以及它们的默认策略(如果它们有一组的话)。字节和计数器标记[ 0:0
],可用于查看有多少流量通过该链,以及有多少数据包通过该链(如果您愿意,可以使用iptables –Z
chain
将这些计数器重置为零)。然后,我们列出该特定链的所有规则。最后,我们要求COMMIT
告诉 Netfilter 添加表节。
清单 7-8 中的第 2-5 行是过滤表中链的定义。我们只显示了与INPUT
相关的链,但是还有FORWARD
、OUTPUT
和其他用户定义的链在这里没有显示。第 2 行的INPUT ACCEPT
是默认的INPUT
链,该链的默认策略是ACCEPT
。第 3-5 行是 Firewalld 用来将规则分组为更多逻辑单元的链。它们没有附加策略(-
)。
在清单 7-8 中,第 6-9 行做了类似的事情。首先要注意的是,符合这些规则的数据包将跳转到ACCEPT
目标。第 6-7 行允许在 udp 和 tcp 协议上从任何源到virbr0
接口上的任何目的地进行 DNS 查询。virbr0
接口用于共享物理设备的虚拟接口。第 8-9 行类似,提供了对 bootps (DHCP)服务的访问。这些规则允许可能已经启动的虚拟主机(例如 KVM 或 Xen 虚拟主机)访问这些服务以获得 DNS 和 DHCP 服务。我们将在第二十章中更多地讨论 KVM 和 Xen。
为了理解第 10 行,我们需要记住我们谈到的 tcpdump 和 IP 协议用来与另一台主机建立连接(套接字)的三次握手。在第 10 行中,我们希望接受连接状态为RELATED
、ESTABLISHED
的所有连接。这意味着已经完成握手并且已经“建立”的任何连接或者与现有连接“相关”的任何连接都被允许。Netfilter 使用conntrack
模块来跟踪连接并了解它们的状态,正是这一点使得 Netfilter 成为有状态防火墙。
New, Established, Related, and Invalid States
NEW
连接状态表示新发起的连接,数据没有通过该连接来回传递。如果您想允许一个服务的新连接,您必须允许NEW
连接状态,无论是传入还是传出。例如,如果不指定邮件服务器上的传入 SMTP 流量接受NEW
连接状态,远程客户端将无法使用邮件服务器发送电子邮件。
ESTABLISHED
连接状态表示正在传输数据的现有连接。如果您希望服务能够保持与远程客户端或服务器的连接,您需要允许ESTABLISHED
连接。例如,如果您希望允许 SSH 连接到您的主机,您必须允许NEW
和ESTABLISHED
传入流量和已建立的传出流量,以确保连接是可能的。
RELATED
状态指的是用于促进另一个连接的连接。一个常见的例子是 FTP 会话,其中控制数据被传递到一个连接,而实际的文件数据流经另一个连接。
INVALID
状态标记在处理数据包时出现问题的连接上:它们可能超出了防火墙的处理能力,或者是与任何当前连接无关的数据包。
在清单 7-8 中,第 11 行的规则被设置为接受环回设备上的所有连接,也称为 lo 或 127.0.0.1。这对于进程间通信非常重要,因为许多进程经常使用回送来相互发送消息。重要的是允许它接受数据包,否则许多东西会停止工作。
清单 7-8 中的第 12-14 行用于将所有来自本地接口的数据包定向到防火墙链。它们的格式如下:
–A <CHAIN> -j <CHAIN TO JUMP TO>.
所以第 12 行说将所有包发送到由 Firewalld 管理的INPUT_direct
链。如果您查看 iptables-save 命令的完整输出,您可能看不到任何与此链相关联的规则。如果我们找不到任何规则,我们将转到输入链中的下一个规则。第 13 行也可能没有与该链相关联的任何规则。如果我们遵循第 14 行(–A INPUT –j INPUT_ZONES
)的规则,我们将跳转到INPUT_ZONES
链。那条链子看起来像这样:
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
Listing 7-9.Iptables Jump and Goto
在清单 7-9 中,我们有一个INPUT_ZONES
链,带有一个到IN_public
链的–g
开关。–g
表示转到用户链IN_public
并在那里继续处理,而不是返回INPUT_ZONES
。
一个数据包将进入IN_public
,然后跳转到IN_public_log
,返回IN_public
,跳转到IN_public_deny
,返回IN_public
,然后跳转到IN_public_allow
。在IN_public_allow
中,我们有允许 ssh 连接的规则。
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
为了解释这一行,让我们假设我们将启动一个到主机上本地 SSH 服务的传入连接。最初的传入数据包将包含 SYN 标志,以尝试启动套接字。上面一行告诉我们,我们匹配第一个 tcp ( -m tcp
)数据包,其目的端口为 22 ( --dport 22
)。如果我们以前没有见过这个连接,那么它与任何数据包都没有关系,它也是一个 SYN 数据包,所以我们还没有建立连接。--ctstate NEW
允许我们从远程主机启动套接字。一旦连接处于ESTABLISHED
状态,我们的防火墙就允许正在进行的通信。然后清单 7-8 中的第 10 行处理ESTABLISHED
和RELATED
连接。
The Different Protocols
Netfilter 或iptables
根据 TCP/IP 协议栈中的不同协议过滤流量。您可以过滤 TCP、UDP、AH、IPsec、PPPoE、STP 等协议。
您可以在/etc/protocols
中获得所有可能的协议及其协议编号的列表。在 iptables 中,您可以在声明规则时指定协议名称,如 udp,或协议编号,如 17(对于 UDP)。下面,我们将对 UDP 数据包进行过滤:
iptables –A INPUT –p 17 –m conntrack --ctstate NEW --dport 53 –j ACCEPT
如果不指定协议,默认为匹配所有协议。您也可以使用!
来排除协议,方法是指定您的规则,如下所示:
iptables –A INPUT –p ! udp –m conntrack --ctstate NEW –j ACCEPT
此规则接受所有协议的数据包,除了在新状态下使用 UDP 协议的数据包。下面是一个很好的关于网络协议的参考: http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
。
日志记录、速率限制和保护 Netfilter
保护和管理防火墙的一部分是监控日志记录、丢弃不需要的流量和限制可能的攻击媒介。使用 Netfilter,我们可以在日志中记录进入防火墙的连接尝试,然后接受或拒绝这些连接。这本身就是一个攻击媒介,因为攻击者可以用连接尝试来填充您的防火墙日志,并利用它来掩盖另一个攻击,或者使持续记录的不良连接淹没您的防火墙资源。因此,对任何防火墙日志进行速率限制或对连接尝试本身进行速率限制是一个好主意。
当数据包进入防火墙时,我们可以在协议、端口、源地址、目的地址等方面进行匹配。以 SSH 为例,我们可以匹配协议 TCP 和目的端口 22。当你建立一个服务器,它的 SSH 端口对外界开放时,你会看到很多僵尸程序试图使用暴力的用户名/密码组合来访问这个端口。通常我们会这样设置我们的 Netfilter(使用 iptables、firewall-cmd 或 ufw ):
-A INPUT_ZONES -g IN_public
-A IN_public -j IN_public_log
-A IN_public -j IN_public_deny
-A IN_public -j IN_public_allow
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
在 IN_public_log 链中,我们可以添加这样的规则:
-A IN_public_log ! --source 10.0.0.1/32 \
–p tcp –m tcp --dport 22 \
–m conntrack --ctstate NEW \
–m limit --limit 2/m --limit-burst 5 \
–j LOG --log-prefix “IN_LOG_SSH:”
在这里,我们添加了一条规则:
- 如果我们的源地址不是来自我们信任的 IP 地址
- 它是端口 22 上的 TCP 请求
- 并且它具有新的连接状态
- 在前 5 个匹配的数据包之后,应用每分钟 2 个连接的限制
- 记录这些连接尝试,并在日志中添加前缀“IN_LOG_SSH”。
这将记录 SSH 连接尝试地址,我们通常不希望连接来自(! --source 10.0.0.1/32
–感叹号,!,表示‘不从’)。我们还可以通过在 IN_public_allow 链中编写如下规则来进一步保护我们的 SSH 服务:
-A IN_public_allow -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set --name drop_ssh
-A IN_public_allow -p tcp --dport ssh -m conntrack --ctstate NEW \
-m recent --name drop_ssh --update --seconds 60 --hitcount 5 -j DROP
这里我们使用的是 Netfilter recent
模块。recent
模块允许我们创建一个动态的 IP 地址列表,我们可以在以后的匹配中应用这些动作。上面创建了与新 TCP SSH 连接相匹配的 IP 列表,这些 IP 与目标 TCP 端口 22 和新连接状态相匹配。该列表被命名为 drop_ssh。下一行表示,每次看到这种类型的连接时,我们都会更新上次看到的时间戳。如果我们在 60 秒的时间段内看到该规则的 5 次命中,则断开这些连接。
您还可以使用 firewall-cmd 来启用日志记录和速率限制。如果我们想将最新的模块应用到我们的 firewall-cmd 中,请从命令行发出类似这样的命令:
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter IN_public_allow 0 -p tcp --dport 22 \
-m state --state NEW -m recent --set –name ssh_drop
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter IN_public_allow 1 -p tcp --dport 22 \
-m state --state NEW -m recent –name ssh_drop --update --seconds 60 --hitcount 5 -j DROP
这使用了firewall-cmd
和--direct
配置选项,通过recent
模块添加我们的规则。直接论证是这样表述的:
--permanent --direct --add-rule { ipv4 | ipv6 | eb } <table> <chain> <priority> <args>
所以在第一个命令中,表是filter
,链是IN_public_allow
,优先级是0
,后面跟着参数。你可以在这里阅读更多关于--direct
论点的内容:
在该链接中,您还将发现如何使用丰富语言命令以及使用firewall-cmd
来应用限制和日志记录。
另外,每次您想用firewall-cmd
更改防火墙规则时,请记住发出以下命令:
sudo firewall-cmd --reload
Caution
如果有人假冒您的合法 IP 地址来触发丢弃规则,实际上拒绝您访问您的系统,这些规则有时会有问题。
除此之外,我们可以使用 Fail2ban 或 Sec 等工具来解析我们的 SSH 日志,然后“监禁”或“丢弃”与一组不成功的连接尝试标准相匹配的连接。你可以在这里阅读更多关于 Fail2ban 的信息:
http://www.fail2ban.org/wiki/index.php/Main_Page
https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-centos-7
现在分别看一下 IN_public_allow 和 IN_public_deny 链中的这些 to 规则:
-A IN_public_allow -p icmp -m icmp --icmp-type echo-request –m limit --limit 1/s -j ACCEPT
-A IN_public_deny -p icmp -m icmp --icmp-type any -j DROP
在IN_public_allow
链中,我们已经指定对于类型为echo-request
的 ICMP 数据包,我们将接受每秒 1 个数据包。ICMP 数据包可能是攻击的途径,因此一些管理员通常会默认阻止所有外部(有时是内部)ICMP 数据包。在这里,我们决定允许回应请求,或 ping,其他类型的 ICMP 将被丢弃。
Different Types of Attacks
人们可以使用不同类型的攻击来破坏您的网络。一些攻击你网络的外围,用虚假的连接把它捆绑起来,直到它崩溃并停止响应;这些被称为拒绝服务攻击(DoS),例如 SYN flood 攻击。其他人将使用您正在运行的服务(如邮件或 web 服务器)绕过您的外围安全并从您的网络内部发起攻击(例如,病毒攻击、特洛伊木马攻击、脚本注入攻击)。
分布式拒绝服务攻击(DDoS)也越来越普遍,并且很难防范。这就是攻击者使用僵尸网络(一组“拥有的”互联网计算机,可以通过发送数百万个虚假请求来攻击网络)用大量特制数据包淹没网络防火墙的地方。即使是拥有非常昂贵设备的大公司也可能受到这些攻击。
虽然保持网络安全是一个持续的过程,但您可以做一些事情来最大限度地降低风险:
- 跟踪主机的安全警报邮件列表。
- 让您的主机保持最新的安全补丁。
- 关闭不需要的端口和服务。
- 了解你的日志,学会发现任何看起来奇怪的事情。
- 至少每六个月检查一次您的安全性,以确保它仍然正常工作。
- 使用上游 DDoS 缓解服务来帮助保护您的网络。
连接到互联网的任何东西都不是 100%安全的,但是您可以采取措施来确保您的网络不存在众所周知的漏洞。脚本小子很快就会找到您的主机,并尝试常见的可预防的攻击。
还有一些其他规则可以帮助防止不同的网络攻击。一种常见的攻击称为 SYN flood,攻击者向受害者发送伪造的 SYN 数据包。SYN flood 使用 TCP 三次握手来耗尽防火墙上的资源。
Linux 内核(3.12 版)最近增加了一个模块,可以使用 SYNPROXY。此 Netfilter 模块旨在缓解 SYN 泛滥。您可以在此阅读有关 SYN floods、DDoS 缓解和 SYNPROXY 的更多信息:
http://rhelblog.redhat.com/2014/04/11/mitigate-tcp-syn-flood-attacks-with-red-hat-enterprise-linux-7-beta/
https://javapipe.com/iptables-ddos-protection
使用 ufw,我们只能应用简单的过滤和日志记录。如果我们想要限制我们的 SSH 连接,我们将发出以下命令:
sudo ufw limit ssh/tcp
目前仅支持 ipv4,如果在过去 30 秒内尝试超过 5 次,将会拒绝连接。如果我们想要记录我们的 SSH 连接,我们将发出以下命令:
sudo ufw allow log 22/tcp
这将记录 SSH 的连接。有关这些选项的更多信息,请参见 ufw 手册页。
进一步探索防火墙-cmd
如前所述,我们还可以在 CentOS 主机上使用 firewall-cmd 来管理 iptables。在 CentOS 主机上,我们可以通过 firewall-cmd 执行相同的 iptables 指令。在本例中,我们将把enp0s8
添加到外部区域,然后在该接口上配置 IP 伪装。然后,我们将端口 80“转发”到我们在192.168.0.1:80
上的内部主机。
首先,我们需要将我们的enp0s8
接口设置在外部区域中。有两种方法,一种是使用firewall-cmd
cli,另一种是在/etc/sysconfig/network-scripts/ifcfg-enp0s8
中直接编辑网络配置文件。如果接口由网络管理器管理,则直接编辑以下内容并将其添加到文件的底部:
ZONE=external
如果设备不受网络管理器管理,则可以发出以下命令:
sudo firewall-cmd --zone=external --add-interface=enp0s8
下一步是向外部区域添加伪装。首先,我们可以检查它是否已经有它,然后像这样添加它:
sudo firewall-cmd --zone=external --query-masquerade
no
sudo firewall-cmd --zone=external --add-masquerade --permanent
我们添加了--permanent
来使更改持久化。现在,为了添加我们的端口转发,或者我们之前所说的 DNATs,我们将发出以下命令:
sudo firewall-cmd --zone=external --add-forward-port=port=80:proto=tcp:toport=80:toaddr=192.168.0.1 --permanent
我们的区域现在应该是这样的:
sudo firewall-cmd --zone=external --list-all
external (active)
interfaces: enp0s8
sources:
services: ssh
ports:
masquerade: yes
forward-ports: port=80:proto=tcp:toport=80:toaddr=192.168.0.1
icmp-blocks:
rich rules:
我们现在将为我们的服务设置一个 DMZ 区域,这些服务位于我们的网络内部,但由外部客户端访问,例如托管在内部服务器上的公共网站。为此,我们将我们的enp0s9
接口添加到zone=dmz
中,就像我们为enp0s8
所做的那样。
一旦我们有了,我们的非军事区应该是这样的:
$msudo firewall-cmd --zone=dmz --list-all
dmz (active)
interfaces: enp0s9
sources:
services: ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:
现在,当我们试图从公共互联网访问我们的网站时,用类似 curl 的东西:
curl -I http://website.example.com
HTTP/1.1 200 OK
Date: Mon, 23 May 2016 12:40:16 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Tue, 10 May 2016 11:54:38 GMT
Firewalld 的最终指南可以在 Red Hat 文档网站上找到:
这里也有一些专门用于防火墙的发行版。在这里可以找到一个列表,有些是商业产品,有些是社区支持的。
https://en.wikipedia.org/wiki/List_of_router_and_firewall_distributions
http://www.techradar.com/au/news/software/applications/7-of-the-best-linux-firewalls-697177
对于防火墙来说,还有其他非 Linux 操作系统,比如 NetBSD https://www.netbsd.org/
。Linux 和 Unix 风格的操作系统也可以在商业设备中找到。
TCP 包装
最后,保护主机安全的另一种方法是使用 TCP 包装器。如果您的网络服务在编译时支持 TCP 包装,您可以使用 TCP 包装来进一步保护您的主机的服务。TCP Wrappers 通过/etc/hosts.allow
和/etc/hosts.deny
文件中的一系列定义来控制对主机上运行的守护进程的访问,而不是对端口的访问。
hosts.allow
中的规则优先于hosts.deny
中的规则。如果您打算使用 TCP Wrappers,在hosts.deny:
中设置以下内容是一个好主意
ALL: ALL
这将设置所有服务的默认拒绝操作,除非在/etc/hosts.allow
文件中指定。规则是按照从上到下的顺序读的。
然后,您可以添加网络服务。例如,对于我们的示例网络,我们将通过设置以下内容来允许网络服务:
ALL: localhost ACCEPT
sshd: .example.com EXCEPT .baddomain.com
这些设置将首先允许接受任何本地主机连接。许多服务需要连接到运行在 loopback (localhost)接口上的服务,这些需要被接受。接下来,我们允许example.com
网络上的主机连接到我们的 SSH 守护进程。这里我们也明确否认了baddomain.com
。有关配置 TCP Wrappers 的更多信息,请参见hosts_options
或hosts.allow
和hosts.
的man
页面。
设置 ppp 连接
在我们的 gateway.example.com 堡垒或网关主机(网络外围路由器/防火墙的别称)上,我们需要设置 PPP 服务。PPP 服务与您的 ISP 建立连接,提供一些身份验证细节,并接收 ISP 提供给您的 IP 地址。这个 IP 地址可以是静态地址,表示它不会改变,也可以是动态地址,表示它是从地址池中提供的,每隔几天就会定期改变。我们将建立一个 PPP xDSL 连接,这是连接到 ISP 的常用方式。
在没有网络管理器的情况下,在 Linux 上建立 xDSL 连接最常见的方法是使用咆哮企鹅 PPPoE 客户端。为此,首先您需要检查是否安装了此客户端。在 CentOS 上,我们将再次使用 nmcli 来创建连接。在 Ubuntu 上,你得安装pppoeconf
。
让我们简单看看如何使用 CentOS 和 Ubuntu 设置 PPP ADSL 连接。
有了 Ubuntu,你可以使用pppoeconf
命令或者在你的/etc/network/interfaces
文件中创建一个 PPP 连接。
使用 nmcli 设置 ADSL
我们将了解如何对 PPPOE 连接使用 nmcli 命令。如你所见,这相对容易。首先,你需要发现你的 Linux 服务器通过什么接口连接到你的调制解调器。在本练习中,我们将使用 enp0s8 作为界面。
sudo nmcli c add type adsl ifname enp0s8 protocol pppoa username ourname password psswd encapsulation llc
Connection 'adsl-enp0s8' (ae7bc50a-c4d5-448a-8331-4a6f41c156c5) successfully added.
根据您的 ISP 连接,这些可能会有所不同。您的 ISP 将提供关于您的封装协议的信息,在我们的例子中,它是 llc(逻辑链路控制)。nmcli 命令现在已经创建了一个名为/etc/network manager/system-connections/ADSL-enp0s 8 的文件。网络管理器现在控制这个连接。我们的adsl-enp0s8
文件看起来像清单 7-10 。
sudo cat /etc/NetworkManager/system-connections/adsl-enp0s8
[connection]
id=adsl-enp0s8
uuid=ae7bc50a-c4d5-448a-8331-4a6f41c156c5
type=adsl
interface-name=enp0s8
permissions=
secondaries=
[adsl]
encapsulation=llc
password=psswd
protocol=pppoa
username=ourname
[ipv4]
dns-search=
method=auto
[ipv6]
dns-search=
method=auto
Listing 7-10.adsl-enp0s3 File on CentOS
该文件分为几个部分,[连接]、[adsl]、[ipv4]和[ipv6]。连接部分描述了接口和类型。adsl 部分包含我们的连接所需的配置细节。ipv4 和 ipv6 是连接信息。如果您的 ISP 提供专用的 IP 地址,您可以修改我们的 nmcli 命令来适应。
在 Ubuntu 上,你需要运行 pppoeconf 命令。
图 7-16。
Checking for modem/concentrators
pppoeconf enp0s8
我们要做的第一件事是搜索设备上的信号,如 7-16 所示。接下来,系统会询问我们是否希望修改 pppoeconf 更改的配置文件。
如图 7-17 所示选择是。
图 7-17。
Okay to Modify?
采用图 7-18 中的默认值。
图 7-19。
ISP username
图 7-18。
Popular options
输入您用来连接到 ISP 的 ISP 用户名。
图 7-20。
ISP password
输入您的 ISP 密码。
图 7-21。
Say No ot USER PEER DNS
我们将对 DNS 设置说“不”,就像我们对 CentOS 配置所做的那样,因为我们将很快管理它们。在接下来的屏幕中,我们将选择默认值。
图 7-25。
Checking DSL connection
图 7-24。
Start the DSL connections now?
图 7-23。
Start the PPPOE connection at boot.
图 7-22。
Clamp MSS at 1452.
一旦你在 Ubuntu 上创建了 PPPoE 设备,你会看到ppp
部分已经被添加到了/etc/network/interfaces
文件中:
auto dsl-provider
iface dsl-provider inet ppp
pre-up /bin/ip link set enp0s8 up # line maintained by pppoeconf
provider dsl-provider
这里您可以看到,当网络启动时,将创建一个名为 dsl-provider 的接口,用auto dsl-provider
表示。接下来,注意设备信息将由provider dsl-provider
提供。提供商信息可以在/etc/ppp/peers
目录下找到。Ubuntu 在我们的/etc/ppp/peers/dsl-provider
文件末尾添加了以下信息:
# Minimalistic default options file for DSL/PPPoE connections
noipdefault
defaultroute
replacedefaultroute
hide-password
#lcp-echo-interval 30
#lcp-echo-failure 4
noauth
persist
#mtu 1492
#persist
#maxfail 0
#holdoff 20
plugin rp-pppoe.so
nic-enp0s8
user "username"
密码信息存储在这里,在/etc/ppp/chap-secrets
文件中,内容很像清单 7-10 。
如果不成功,可以通过 Ubuntu 上的plog
命令或 CentOS 上的/var/log/messages
查看连接日志。
您还应该检查以确保您的默认路由设置为 ISP 的第一跳,并且从正确的接口出去。
ip route show
default via 10.1.1.1 dev adsl-enp0s8
在上面的例子中,10.1.1.1
将是您的 ISP 的第一跳,如果流量的目的地是离开您的网络,它将从 adsl-enp0s8 接口出去。
有关在 Ubuntu 上建立连接的更多信息,请访问:
摘要
在本章中,我们将带您了解网络和 Linux Netfilter 防火墙。我们讨论了基本的网络,如何管理 Linux 网络接口以及如何解决网络问题。本章讲述了如何执行以下操作:
- 在主机上配置接口。
- 网络过滤器基础
- 防火墙和防火墙-cmd
- 管理 Ubuntu 防火墙的 ufw 工具
- 用于管理 Linux 防火墙的 iptables 工具
- 记录、限制和保护您的连接
- 使用 TCP 包装来保护您的守护进程。
- 配置 PPP 连接
在下一章,我们将看看如何管理主机上的软件包。在该章中,您将了解如何在您的主机上安装、删除和更新软件。