LPI Linux 认证/高级网络配置和故障排除
(LPIC-2 版本 4.5)
权重 4
描述: 候选人应该能够配置网络设备以实现各种网络身份验证方案。本目标包括配置多宿主网络设备并解决通信问题。
关键知识领域
- 用于操作路由表的实用程序
- 用于配置和操作以太网网络接口的实用程序
- 用于分析网络设备状态的实用程序
- 用于监控和分析 TCP/IP 流量的实用程序
术语和实用程序
ip
ifconfig
route
arp
ss
netstat
lsof
ping
,ping6
nc
tcpdump
nmap
描述: 候选人应该能够配置网络设备以实现各种网络身份验证方案。本目标包括配置多宿主网络设备,配置虚拟专用网络并解决网络和通信问题。
关键文件,术语,和实用程序包括
/sbin/route /sbin/ifconfig /bin/netstat /bin/ping /sbin/arp /usr/sbin/tcpdump /usr/sbin/lsof /usr/bin/nc
在 Linux 下,网络数据包过滤可以通过以下三种方式之一实现
- Ipfwadm : 内核 2.0.x 及更高版本 (RedHat 5.x)
- Ipchains : 内核 2.2.x 及更高版本 (RedHat 6.x, 7.0)
- Iptables : 内核 2.4.x 及更高版本 (RedHat 7.1 – 9.0)
它们的设计和功能大不相同 - 请注意,ipfwadm 被认为是过时的,iptables 是最先进的和当前的。在 iptables 中,数据包流图如下所示
Iptables 需要在你的内核中配置一些选项 (或作为模块)
- CONFIG_PACKET
- 此选项允许需要直接与各种网络设备交互的应用程序和实用程序。此类实用程序的示例包括 tcpdump 或 snort。
- CONFIG_NETFILTER
- 如果要使用你的计算机作为防火墙或网关连接到互联网,则需要此选项。
- CONFIG_IP_NF_CONNTRACK
- 此模块对于实现连接跟踪是必需的。连接跟踪由 NAT 和伪装等功能使用。如果需要在 LAN 上对机器进行防火墙,那么你绝对应该选中此选项。
- CONFIG_IP_NF_FTP
- 如果要对 FTP 连接进行连接跟踪,则需要此模块。由于 FTP 连接在正常情况下很难进行连接跟踪,因此 conntrack 需要一个所谓的辅助程序,此选项将编译该辅助程序。如果未添加此模块,将无法通过防火墙或网关正常使用 FTP。
- CONFIG_IP_NF_IPTABLES
- 如果要执行任何类型的过滤、伪装或 NAT,则需要此选项。它将整个 iptables 识别框架添加到内核。没有它,你将无法使用 iptables 执行任何操作。
- CONFIG_IP_NF_MATCH_LIMIT
- 此模块并非严格意义上的必需项。此选项提供 LIMIT 匹配,它增加了控制每分钟匹配数据包数量的可能性,受相应规则控制。例如,-m limit --limit 3/minute 将匹配每分钟最多 3 个数据包。此模块还可以用于避免某些拒绝服务攻击。
- CONFIG_IP_NF_MATCH_MAC
- 这使我们能够根据 MAC 地址匹配数据包。每个以太网适配器都有自己的 MAC 地址。例如,我们可以根据使用的 MAC 地址阻止数据包,并很好地阻止特定计算机,因为 MAC 地址很少更改。
- CONFIG_IP_NF_MATCH_MARK
- 这使我们能够使用 MARK 匹配。例如,如果使用 MARK 目标,我们可以标记数据包,然后根据此数据包是否在表中被进一步标记,我们就可以根据此标记进行匹配。此选项是实际的 MARK 匹配,稍后我们将介绍实际的 MARK 目标。
- CONFIG_IP_NF_MATCH_MULTIPORT
- 此模块使我们能够匹配具有整个目标端口或源端口范围的数据包。通常这不可能,但有了此匹配就成为可能。
- CONFIG_IP_NF_MATCH_TOS
- 有了此匹配,我们可以根据数据包的 TOS 字段匹配数据包。TOS 代表服务类型。TOS 也可以通过 mangle 表中的某些规则和通过 ip/tc 命令设置。
- CONFIG_IP_NF_MATCH_TCPMSS
- 此选项为我们增加了根据 TCP 数据包的 MSS 字段匹配 TCP 数据包的可能性。
- CONFIG_IP_NF_MATCH_STATE
- 这是与 ipchains 相比最大的改进之一。有了此模块,我们可以在数据包上进行有状态匹配。例如,如果我们已经看到 TCP 连接中双向的流量,则此数据包将被视为 ESTABLISHED。
- CONFIG_IP_NF_MATCH_UNCLEAN
- 此模块将增加我们匹配不符合类型或无效的 IP、TCP、UDP 和 ICMP 数据包的可能性。例如,我们可以丢弃这些数据包,但我们永远不知道它们是否合法。请注意,此匹配仍在试验中,可能无法在所有情况下都能完美运行。
- CONFIG_IP_NF_MATCH_OWNER
- 此选项将增加我们根据套接字所有者进行匹配的可能性。例如,我们可以只允许 root 用户访问互联网。此模块最初只是作为新 iptables 可以做什么的示例编写的。请注意,此匹配仍在试验中,可能无法适用于所有人。
- CONFIG_IP_NF_FILTER
- 此模块将添加基本的 filter 表,它将使你能够执行 IP 过滤。在 filter 表中,你会找到 INPUT、FORWARD 和 OUTPUT 链。如果你计划对收发的数据包进行任何类型的过滤,则需要此模块。
- CONFIG_IP_NF_TARGET_REJECT
- 此目标使我们能够指定应该发送 ICMP 错误消息来回复传入数据包,而不是简单地将它们丢弃。请记住,与 ICMP 和 UDP 不同,TCP 连接始终使用 TCP RST 数据包重置或拒绝。
- CONFIG_IP_NF_TARGET_MIRROR
- 这使数据包能够反弹回数据包的发送者。例如,如果我们在 INPUT 链上的目标端口 HTTP 上设置了 MIRROR 目标,并且有人试图访问此端口,我们将把他的数据包反弹回他,最终他可能会看到他自己的主页。
- CONFIG_IP_NF_NAT
- 此模块允许各种形式的网络地址转换 (NAT)。此选项使我们能够访问 iptables 中的 nat 表。如果要执行端口转发、伪装等操作,则需要此选项。请注意,此选项不是执行 LAN 防火墙和伪装所必需的,但除非你能够为所有主机提供唯一的 IP 地址,否则你应该拥有它。
- CONFIG_IP_NF_TARGET_MASQUERADE
- 此模块添加了 MASQUERADE 目标。例如,如果我们不知道我们的互联网 IP 地址,这将是获取 IP 地址的最佳方式,而不是使用 DNAT 或 SNAT。换句话说,如果我们使用 DHCP、PPP、SLIP 或其他分配 IP 地址的连接,我们需要使用此目标,而不是 SNAT。伪装比 NAT 给计算机带来稍微高的负载,但无需预先知道 IP 地址即可工作。
- CONFIG_IP_NF_TARGET_REDIRECT
- 此目标与应用程序代理一起使用非常有用,例如。我们不会让数据包直接通过,而是将其重新映射到我们的本地框。换句话说,我们可以通过这种方式创建透明代理。
- CONFIG_IP_NF_TARGET_LOG
- 这将 LOG 目标及其功能添加到 iptables。我们可以使用此模块将某些数据包记录到 syslogd,从而了解数据包的处理情况。这对于安全审计、取证或调试您编写的脚本非常宝贵。
- CONFIG_IP_NF_TARGET_TCPMSS
- 此选项可用于应对阻止 ICMP 分片需要的互联网服务提供商和服务器。这会导致网页无法通过,小邮件能够通过而大邮件无法通过,ssh 正常工作但 scp 在握手后挂起等等。然后我们可以使用 TCPMSS 目标通过将我们的 MSS(最大段大小)限制为 PMTU(路径最大传输单元)来克服此问题。这样,我们就能处理 Netfilter 作者在内核配置帮助中所说的“犯罪性质的脑残 ISP 或服务器”。
- CONFIG_IP_NF_COMPAT_IPCHAINS
- 添加了对过时的 ipchains 的兼容模式。不要将其视为解决从 Linux 2.2 内核迁移到 2.4 内核的任何真正的长期解决方案,因为它可能在 2.6 内核中消失。
- CONFIG_IP_NF_COMPAT_IPFWADM
- 与过时的 ipfwadm 的兼容模式。绝对不要将其视为真正的长期解决方案。
当数据包第一次进入防火墙时,它会撞击硬件,然后被传递到内核中的适当设备驱动程序。然后,数据包开始在内核中经历一系列步骤,然后要么被发送到正确的应用程序(本地),要么被转发到另一个主机 - 或者发生任何其他情况。
首先,让我们看一下一个目标是我们自己本地主机的包。在实际交付给接收它的应用程序之前,它将经过以下步骤
请注意,这次数据包通过 INPUT 链而不是 FORWARD 链传递。非常合乎逻辑。最有可能的是,从一开始,唯一真正合乎逻辑的是您眼中的表和链的遍历,但如果您继续思考,您会发现它随着时间的推移会变得更加清晰。现在我们看一下来自我们自己本地主机的传出数据包,以及它们经过的步骤。
在本例中,我们假设数据包的目标是另一个网络上的另一个主机。数据包以以下方式经过不同的步骤
如您所见,要经过很多步骤。数据包可以在任何 iptables 链中被阻止,或者在格式错误的任何其他地方被阻止;但是,我们主要对这批 iptables 方面感兴趣。请注意,没有针对不同接口或任何其他内容的特定链或表。所有通过此防火墙/路由器转发的数据包始终通过 FORWARD。
不要在前面的场景中使用 INPUT 链进行过滤!INPUT 专门用于到达我们本地主机的,不会路由到任何其他目标的数据包。
我们现在已经了解了三种不同场景中不同链的遍历方式。如果我们要找出所有这些内容的良好地图,它看起来会像这样
为了阐明此图像,请考虑以下内容。如果我们接收到一个在第一个路由决策中没有目标为本地机器本身的数据包,它将通过 FORWARD 链路由。另一方面,如果数据包的目标是本地机器正在监听的 IP 地址,我们将通过 INPUT 链将数据包发送到本地机器。
还值得注意的是,数据包可能是目标为本地机器,但目标地址可能在 PREROUTING 链中通过执行 NAT 被更改。由于这发生在第一个路由决策之前,因此数据包将在更改后进行查看。因此,路由可能会在路由决策完成之前更改。请注意,所有数据包都将经过此图像中的某条路径。如果您将数据包 DNAT 回到它来自的同一个网络,它仍然会经过其余的链,直到它回到网络上。
Mangle 表
[edit | edit source]如我们已经提到的,此表主要用于修改数据包。换句话说,您可以自由使用可以用来更改 TOS(服务类型)字段等的修改匹配项。
强烈建议您不要使用此表进行任何过滤;并且任何 DNAT、SNAT 或伪装都将无法在此表中工作。
仅在修改表中有效的目标
- TOS
- TTL
- MARK
TOS 目标用于设置和/或更改数据包中的服务类型字段。这可以用于建立有关数据包应如何路由等的网络策略。请注意,这尚未完善,并且在 Internet 上并未真正实现,大多数路由器并不关心此字段中的值,有时它们的行为会根据接收到的内容而出现故障。换句话说,除非您想使用 iproute2 对其进行路由决策,否则不要将此设置为发送到 Internet 的数据包。
TTL 目标用于更改数据包的 TTL(生存时间)字段。我们可以告诉数据包只具有特定的 TTL 等等。这样做的一个很好的理由可能是我们不想向爱窥探的互联网服务提供商泄露我们的行踪。一些互联网服务提供商不喜欢用户在一个单一连接上运行多台计算机,并且有一些互联网服务提供商已知会查找生成不同 TTL 值的单个主机,并将其视为连接到单个连接的多台计算机的许多迹象之一。
MARK 目标用于将特殊标记值设置为数据包。然后,iproute2 程序可以识别这些标记,根据数据包的标记或是否没有标记来执行不同的数据包路由。我们还可以根据这些标记执行带宽限制和基于类别的排队。
NAT 表
[edit | edit source]此表仅用于对不同数据包执行 NAT(网络地址转换)。换句话说,它应该仅用于转换数据包的源字段或目标字段。请注意,如前所述,只有流中的第一个数据包会命中此链。此后,其余数据包将自动执行与第一个数据包相同的操作。执行此类操作的实际目标是
- DNAT
- SNAT
- MASQUERADE
DNAT 目标主要用于您拥有公共 IP 并且想要将对防火墙的访问重定向到其他主机(例如 DMZ)的情况。换句话说,我们更改数据包的目标地址并将其重新路由到主机。
SNAT 主要用于更改数据包的源地址。在大多数情况下,您将隐藏您的本地网络或 DMZ 等等。一个很好的例子是防火墙,我们知道外部 IP 地址,但需要用防火墙的 IP 地址替换本地网络的 IP 地址。使用此目标,防火墙将自动对数据包进行 SNAT 和 De-SNAT,从而可以从 LAN 建立到 Internet 的连接。例如,如果您的网络使用 192.168.0.0/netmask,那么数据包将永远无法从 Internet 返回,因为 IANA 已将这些网络(以及其他网络)划分为私有网络,仅供隔离的 LAN 使用。
MASQUERADE 目标的使用方式与 SNAT 完全相同,但 MASQUERADE 目标需要更多的计算开销。原因是,每次 MASQUERADE 目标被数据包命中时,它会自动检查要使用的 IP 地址,而不是像 SNAT 目标那样 - 只使用配置的单个 IP 地址。MASQUERADE 目标使使用您的 ISP 可能会为您提供的 PPP、PPPoE 或 SLIP 连接到 Internet 的动态 DHCP IP 地址成为可能。
Filter 表
[edit | edit source]Filter 表主要用于过滤数据包。我们可以匹配数据包并以任何我们想要的方式过滤它们。这是我们实际上对数据包采取行动并查看它们包含的内容,并根据它们的内容将其丢弃或接受的地方。当然,我们也可以进行预过滤;但是,此特定表是为其设计过滤的地方。几乎所有目标都可以在此链中使用。我们将在此处对 Filter 表更加详细地说明;但是您现在知道,此表是进行主要过滤的正确地方。
状态机
[edit | edit source]状态机是 iptables 中的一个特殊部分,其实不应该被称为状态机,因为它实际上是一个连接跟踪机器。然而,大多数人还是习惯用第一个名字称呼它。在本章中,我将或多或少地使用这两个名称,就好像它们是同义词一样。这应该不会造成过多的混淆。连接跟踪的作用是让 Netfilter 框架了解特定连接的状态。实现这一点的防火墙通常被称为状态防火墙。状态防火墙通常比无状态防火墙安全得多,因为它允许我们编写更严格的规则集。
在 iptables 中,数据包可以与跟踪的连接关联起来,分为四种不同的状态。它们被称为 NEW、ESTABLISHED、RELATED 和 INVALID。我们将在稍后更深入地讨论每一种状态。使用 --state 匹配,我们可以轻松地控制谁或什么可以发起新的会话。
所有连接跟踪都是由内核中一个称为 conntrack 的特殊框架完成的。conntrack 可以作为模块加载,也可以作为内核本身的内部部分加载。大多数情况下,我们需要并希望比默认的 conntrack 引擎所能维护的更具体的连接跟踪。因此,conntrack 中还有更具体的模块来处理 TCP、UDP 或 ICMP 协议,以及其他协议。这些模块从数据包中获取特定、唯一的信息,以便它们可以跟踪每个数据流。conntrack 收集的信息随后用于告诉 conntrack 当前数据流处于哪个状态。例如,UDP 数据流通常由其目标 IP 地址、源 IP 地址、目标端口和源端口唯一标识。在以前的内核中,我们可以选择开启或关闭碎片重组。然而,自从引入了 iptables 和 Netfilter,特别是连接跟踪之后,这个选项就被取消了。原因是,连接跟踪无法在不进行数据包碎片重组的情况下正常工作,因此碎片重组已经被整合到 conntrack 中,并自动执行。它无法被关闭,除非关闭连接跟踪。如果开启连接跟踪,就会始终执行碎片重组。
所有连接跟踪都在 PREROUTING 链中处理,除了本地生成的包,它们在 OUTPUT 链中处理。这意味着 iptables 会在 PREROUTING 链中执行所有状态的重新计算等操作。如果我们发送数据流中的初始包,状态在 OUTPUT 链中被设置为 NEW,当我们收到返回包时,状态在 PREROUTING 链中被更改为 ESTABLISHED,依此类推。如果第一个包不是由我们自己发起的,那么 NEW 状态将在 PREROUTING 链中设置,当然。因此,所有状态更改和计算都在 nat 表的 PREROUTING 和 OUTPUT 链中完成。
conntrack 条目
[edit | edit source]让我们简要地看一下 conntrack 条目以及如何在 /proc/net/ip_conntrack 中读取它们。这列出了 conntrack 数据库中的所有当前条目。如果已加载 ip_conntrack 模块,则 /proc/net/ip_conntrack 的 cat 可能看起来像
tcp 6 117 SYN_SENT src=192.168.1.6 dst=192.168.1.9 sport=32775 \ dport=22 [UNREPLIED] src=192.168.1.9 dst=192.168.1.6 sport=22 \ dport=32775 use=2
此示例包含 conntrack 模块维护的所有信息,以了解特定连接处于哪个状态。首先,我们有一个协议,在本例中是 tcp。接下来,是相同的值,以正常的十进制编码表示。在此之后,我们看到这个 conntrack 条目还有多少时间存活。该值现在设置为 117 秒,并且会定期递减,直到我们看到更多流量。然后,该值将重置为与它在相关时间点所处状态相对应的默认值。接下来是该条目在当前时间点所处的实际状态。在上面提到的例子中,我们看到的是一个处于 SYN_SENT 状态的包。连接的内部值与在 iptables 中使用的外部值略有不同。SYN_SENT 值告诉我们,我们看到的是一个连接,它在一个方向上只看到了一个 TCP SYN 包。接下来,我们看到源 IP 地址、目标 IP 地址、源端口和目标端口。此时,我们看到一个特定的关键字,告诉我们我们没有看到该连接的任何返回流量。最后,我们看到我们对返回包的预期。该信息详细说明了源 IP 地址和目标 IP 地址(它们都被反转了,因为数据包要被定向回我们)。源端口和目标端口也是如此。这些是我们应该感兴趣的值。
连接跟踪条目可能采用一系列不同的值,所有这些值都指定在 conntrack 头文件中,这些头文件在 linux/include/netfilter-ipv4/ip_conntrack*.h 文件中可用。这些值取决于我们使用的 IP 子协议。TCP、UDP 或 ICMP 协议采用特定默认值,如 linux/include/netfilter-ipv4/ip_conntrack.h 中所指定。我们将在查看每个协议时更详细地查看这一点;但是,我们不会在本章中广泛使用它们,因为它们在 conntrack 内部以外的地方没有使用。此外,根据此状态的更改方式,连接被销毁之前的时间默认值也会改变。
最近,iptables patch-o-matic 中发布了一个新的补丁,称为 tcp-window-tracking。这个补丁在其他东西中添加了所有上述超时,并将它们添加到特殊的 sysctl 变量中,这意味着它们可以在系统运行时动态更改。因此,每次想要更改超时时就不需要重新编译内核了。可以通过使用 /proc/sys/net/ipv4/netfilter 目录中提供的特定系统调用来更改这些超时。你应该特别查看 /proc/sys/net/ipv4/netfilter/ip_ct_* 变量。
当连接在两个方向上都看到了流量时,conntrack 条目将擦除 [UNREPLIED] 标志,然后重置它。该条目告诉我们,该连接在两个方向上都没有看到任何流量,将被 [ASSURED] 标志替换,该标志位于条目的末尾附近。[ASSURED] 标志告诉我们,该连接是确定的,如果我们达到最大可能的跟踪连接数,它不会被擦除。因此,标记为 [ASSURED] 的连接不会被擦除,与非确定连接(那些没有标记为 [ASSURED] 的连接)相反。连接跟踪表可以容纳多少连接取决于一个变量,该变量可以通过最近内核中的 ip-sysctl 函数设置。该条目所持有的默认值根据你的内存大小而有很大差异。在 128 MB 的 RAM 上,你将获得 8192 个可能的条目,而在 256 MB 的 RAM 上,你将获得 16376 个条目。你可以通过 /proc/sys/net/ipv4/ip_conntrack_max 设置来读取和设置你的设置。
用户空间状态
[edit | edit source]正如你所看到的,数据包在内核本身中可能处于几种不同的状态,具体取决于我们讨论的是什么协议。然而,在内核外部,我们只有前面描述的 4 种状态。这些状态主要可以与状态匹配一起使用,然后状态匹配将能够根据数据包当前的连接跟踪状态来匹配数据包。有效状态为 NEW、ESTABLISHED、RELATED 和 INVALID 状态。下表将简要解释每种可能的状态
这些状态可以与 --state 匹配一起使用,以根据数据包的连接跟踪状态来匹配数据包。这就是状态机对于我们的防火墙如此强大而高效的原因。以前,我们经常不得不打开 1024 以上的所有端口,以便让所有流量重新进入我们的本地网络。有了状态机,就不再需要这样做了,因为我们现在只需要为返回流量打开防火墙,而不需要为所有其他类型的流量打开防火墙。
TCP 连接
[edit | edit source]在本节和接下来的几节中,我们将更仔细地研究状态以及它们是如何针对三种基本协议 TCP、UDP 和 ICMP 处理的。此外,我们将更仔细地研究在默认情况下如何处理连接,如果它们不能归类为这三种协议中的任何一种。我们选择从 TCP 协议开始,因为它本身就是一个有状态的协议,并且在 iptables 的状态机方面有很多有趣的细节。
TCP 连接总是以 3 次握手的方式启动,这建立并协商实际的连接,数据将通过该连接发送。整个会话从一个 SYN 包开始,然后是一个 SYN/ACK 包,最后是一个 ACK 包来确认整个会话的建立。此时,连接已建立,可以开始发送数据。最大的问题是,连接跟踪如何连接到这个过程中?实际上很简单。
就用户而言,连接跟踪对于所有连接类型的工作原理基本相同。请查看下面的图片,了解数据流在连接的不同阶段进入哪个状态。正如你所看到的,连接跟踪代码并没有真正遵循 TCP 连接的流程,从用户的角度来看。一旦它看到一个包(SYN),它就认为连接是 NEW。一旦它看到返回包(SYN/ACK),它就认为连接是 ESTABLISHED。如果你仔细想想,你就会明白为什么。通过这种特殊的实现,你可以允许 NEW 和 ESTABLISHED 包离开你的本地网络,只允许 ESTABLISHED 连接返回,并且这将完美地工作。相反,如果连接跟踪机器将整个连接建立视为 NEW,那么我们实际上永远无法阻止外部连接到我们的本地网络,因为我们必须允许 NEW 包再次进入。为了使事情更加复杂,内核内部使用了许多其他内部状态来处理 TCP 连接,但这些状态在用户空间不可用。粗略地说,它们遵循 RFC 793 - 传输控制协议第 21-23 页中指定的 state 标准。
正如你所看到的,从用户的角度来看,这实际上非常简单。然而,从内核的角度来看,整个结构要复杂一些。让我们看一个例子。考虑连接状态在 /proc/net/ip_conntrack 表中是如何变化的。第一个状态是在连接中收到第一个 SYN 包时报告的。
tcp 6 117 SYN_SENT src=192.168.1.5 dst=192.168.1.35 sport=1031 \ dport=23 [UNREPLIED] src=192.168.1.35 dst=192.168.1.5 sport=23 \ dport=1031 use=1
如上条目所示,我们处于一个精确的状态,其中已发送 SYN 数据包(已设置 SYN_SENT 标志),但尚未发送任何回复(请注意 [UNREPLIED] 标志)。当我们在另一个方向看到另一个数据包时,将到达下一个内部状态。
tcp 6 57 SYN_RECV src=192.168.1.5 dst=192.168.1.35 sport=1031 \ dport=23 src=192.168.1.35 dst=192.168.1.5 sport=23 dport=1031 \ use=1
现在我们已经收到了相应的 SYN/ACK 作为回复。一旦接收到此数据包,状态就会再次改变,这次变为 SYN_RECV。SYN_RECV 告诉我们原始 SYN 已成功发送,并且 SYN/ACK 回复数据包也已正确通过防火墙。此外,此连接跟踪条目现在已在两个方向上看到流量,因此被认为已得到回复。这不是明确的,而是假设的,就像上面的 [UNREPLIED] 标志一样。一旦我们看到 3 次握手中的最终 ACK,最后一步将完成。
tcp 6 431999 ESTABLISHED src=192.168.1.5 dst=192.168.1.35 \
sport=1031 dport=23 src=192.168.1.35 dst=192.168.1.5 \ sport=23 dport=1031 use=1
在最后一个例子中,我们已经收到了 3 次握手中的最终 ACK,并且连接已进入 ESTABLISHED 状态,就 iptables 的内部机制而言。在几个数据包之后,连接也将变为 [ASSURED],如本章介绍部分所示。当 TCP 连接关闭时,它以以下方式完成并经过以下状态。
如您所见,连接在发送最后一个 ACK 之前永远不会真正关闭。请注意,此图仅描述了在正常情况下如何关闭连接。例如,如果拒绝连接,则可以通过发送 RST(重置)来关闭连接。在这种情况下,连接将在预定的时间后关闭。
当 TCP 连接关闭时,连接进入 TIME_WAIT 状态,默认情况下设置为 2 分钟。这是为了确保即使连接已关闭,所有乱序到达的数据包仍能通过我们的规则集。这用作一种缓冲时间,以便卡在某个拥塞路由器中的数据包仍然可以到达防火墙或连接的另一端。
如果连接由 RST 数据包重置,则状态将变为 CLOSE。这意味着连接默认情况下有 10 秒的时间才能彻底关闭。RST 数据包不会以任何方式进行确认,并且会直接断开连接。除了我们已经介绍过的状态之外,还有一些其他的状态。
以下是 TCP 流可能采取的所有状态及其超时值的完整列表。
这些值绝对不是绝对的。它们可能会随着内核版本的改变而改变,也可能通过 /proc/sys/net/ipv4/netfilter/ip_ct_tcp_* 变量在 proc 文件系统中改变。但是,默认值应该在实践中相当稳定。这些值以节拍(或 1/100 秒)设置,因此 3000 表示 30 秒。
还要注意,状态机中的用户空间不查看 TCP 数据包中设置的 TCP 标志。这通常是不好的,因为您可能希望允许 NEW 状态的数据包通过防火墙,但是当您指定 NEW 标志时,大多数情况下是指 SYN 数据包。
UDP 连接
[edit | edit source]UDP 连接本身不是有状态连接,而是无状态连接。有几个原因,主要是因为它们不包含任何连接建立或连接关闭;最重要的是它们缺乏排序。以特定顺序接收两个 UDP 数据报并不能说明它们发送的顺序。但是,仍然可以在内核中设置连接上的状态。让我们看看如何跟踪连接以及它在 conntrack 中可能是什么样子。
如您所见,连接的建立方式与 TCP 连接几乎完全相同。也就是说,从用户空间的角度来看。在内部,conntrack 信息看起来完全不同,但本质上细节相同。首先,让我们看看初始 UDP 数据包发送后的条目。
udp 17 20 src=192.168.1.2 dst=192.168.1.5 sport=137 dport=1025 \ [UNREPLIED] src=192.168.1.5 dst=192.168.1.2 sport=1025 \ dport=137 use=1
从第一个和第二个值可以看出,这是一个 UDP 数据包。第一个是协议名称,第二个是协议编号。这与 TCP 连接完全相同。第三个值标记此状态条目可以生存多少秒。在此之后,我们获得了我们已经看到的数据包的值以及从发起数据包发送者那里到达我们的连接上的数据包的未来期望。这些是源、目的地、源端口和目标端口。此时,[UNREPLIED] 标志告诉我们到目前为止还没有对数据包的响应。最后,我们得到了返回数据包的预期列表。请注意,后者的条目顺序与第一个值的顺序相反。此时超时设置为 30 秒,这是默认值。
udp 17 170 src=192.168.1.2 dst=192.168.1.5 sport=137 \ dport=1025 src=192.168.1.5 dst=192.168.1.2 sport=1025 \ dport=137 use=1
此时,服务器已经看到对发送出去的第一个数据包的回复,并且连接现在被认为是 ESTABLISHED。正如您所看到的,这在连接跟踪中没有显示。主要区别在于 [UNREPLIED] 标志现在已经消失了。此外,默认超时已更改为 180 秒,但在本例中,它现在已减少到 170 秒——在 10 秒内,它将变为 160 秒。不过,还有一件事是缺失的,并且可能会发生一些变化,那就是上面描述的 [ASSURED] 标志。为了在跟踪的连接上设置 [ASSURED] 标志,必须在该连接上有一些流量。
udp 17 175 src=192.168.1.5 dst=195.22.79.2 sport=1025 \ dport=53 src=195.22.79.2 dst=192.168.1.5 sport=53 \ dport=1025 [ASSURED] use=1
此时,连接已变得可靠。该连接与前面的示例完全相同,除了 [ASSURED] 标志。如果此连接在 180 秒内未使用,它将超时。180 秒是一个相对较低的值,但对于大多数用途来说应该足够。对于每个与同一条目匹配并通过防火墙的数据包,此值将重置为其完整值,就像所有内部状态一样。
ICMP 连接
[edit | edit source]ICMP 数据包远非有状态流,因为它们仅用于控制,永远不会建立任何连接。但是,有四种 ICMP 类型会生成返回数据包,它们有两种不同的状态。这些 ICMP 消息可以采用 NEW 和 ESTABLISHED 状态。我们谈论的 ICMP 类型是回显请求和回复、时间戳请求和回复、信息请求和回复,以及地址掩码请求和回复。在这其中,时间戳请求和信息请求已经过时,很可能可以直接丢弃。但是,回显消息在 ping 主机等多种设置中使用。地址掩码请求并不常用,但在某些情况下可能有用,值得允许。为了了解这可能是什么样子,请查看以下图像。
如上图所示,主机向目标发送回显请求,防火墙将其视为 NEW。然后目标用回显回复进行响应,防火墙将其视为状态 ESTABLISHED。当看到第一个回显请求时,以下状态条目将进入 ip_conntrack。
icmp 1 25 src=192.168.1.6 dst=192.168.1.10 type=8 code=0 \ id=33029 [UNREPLIED] src=192.168.1.10 dst=192.168.1.6 \ type=0 code=0 id=33029 use=1
如您所见,此条目看起来与 TCP 和 UDP 的标准状态略有不同。协议在里面,超时也在里面,还有源地址和目标地址。但是,问题出现在此之后。我们现在有 3 个新的字段,称为类型、代码和 id。它们并不特殊,类型字段包含 ICMP 类型,代码字段包含 ICMP 代码。这些都在 ICMP 类型附录中提供。最后一个 id 字段包含 ICMP ID。每个 ICMP 数据包在发送时都会设置一个 ID,当接收方接收到 ICMP 消息时,它会在新的 ICMP 消息中设置相同的 ID,以便发送方能够识别回复,并能够将其与正确的 ICMP 请求联系起来。
下一个字段,我们再次将其识别为 [UNREPLIED] 标志,我们之前已经见过它。与之前一样,此标志告诉我们目前正在查看一个仅在一个方向上看到流量的连接跟踪条目。最后,我们看到了回复 ICMP 数据包的回复预期,它是原始源和目标 IP 地址的反转。至于类型和代码,这些将更改为回复数据包的正确值,因此回显请求将更改为回显回复,依此类推。ICMP ID 从请求数据包中保留下来。
回复数据包被认为是 ESTABLISHED,正如我们已经解释过的。但是,我们可以确定,在 ICMP 回复之后,在相同的连接中绝对不会再有任何合法流量。为此,一旦回复通过 Netfilter 结构传播,连接跟踪条目就会被销毁。
在上述每种情况下,请求被认为是 NEW,而回复被认为是 ESTABLISHED。让我们更仔细地考虑一下。当防火墙看到请求数据包时,它将其视为 NEW。当主机向请求发送回复数据包时,它被认为是 ESTABLISHED。
请注意,这意味着回复数据包必须与连接跟踪条目中给定的标准相匹配,才能被视为已建立,就像所有其他流量类型一样。
ICMP 请求的默认超时时间为 30 秒,您可以在 /proc/sys/net/ipv4/netfilter/ip_ct_icmp_timeout 条目中更改此值。通常,这应该是一个很好的超时时间,因为它能够捕获大多数传输中的数据包。
ICMP 的另一个非常重要的部分是它用于告知主机特定 UDP 和 TCP 连接或连接尝试发生了什么。由于这个简单的原因,ICMP 回复通常会被识别为与原始连接或连接尝试相关。一个简单的例子是 ICMP 主机不可达或 ICMP 网络不可达。如果我们的主机尝试与其他主机建立不成功的连接,则这些消息应始终被发送回我们的主机,但网络或主机可能已关闭,因此最后一个尝试到达目标站点的路由器将回复 ICMP 消息告诉我们。在这种情况下,ICMP 回复被视为相关数据包。以下图片应该可以解释它的外观。
在上面的示例中,我们向特定地址发送 SYN 数据包。这被防火墙视为新的连接。但是,数据包试图到达的网络不可达,因此路由器向我们返回网络不可达的 ICMP 错误。连接跟踪代码可以识别此数据包与已添加的跟踪条目相关。因此,ICMP 回复将正确发送到客户端,然后客户端将希望中止。同时,防火墙销毁了连接跟踪条目,因为它知道这是一个错误消息。
如果 UDP 连接遇到上述任何问题,也会出现与上述相同的行为。所有作为 UDP 连接回复发送的 ICMP 消息都视为相关消息。考虑以下图像。
这次,UDP 数据包被发送到主机。此 UDP 连接被视为新的。但是,该网络被途中的某些防火墙或路由器在管理上禁止。因此,我们的防火墙收到了一个 ICMP 网络禁止的回复。防火墙知道此 ICMP 错误消息与已打开的 UDP 连接相关,并将其作为相关数据包发送到客户端。此时,防火墙销毁了连接跟踪条目,客户端收到 ICMP 消息,并希望中止。
默认连接
[edit | edit source]在某些情况下,conntrack 机器不知道如何处理特定的协议。如果它对该协议不了解,或者不知道它的工作原理,就会发生这种情况。在这些情况下,它会回到默认行为。例如,默认行为用于 NETBLT、MUX 和 EGP。这种行为看起来非常类似于 UDP 连接跟踪。第一个数据包被视为新的,回复流量等等被视为已建立。
使用默认行为时,所有这些数据包都将获得相同的默认超时时间。这可以通过 /proc/sys/net/ipv4/netfilter/ip_ct_generic_timeout 变量设置。此处的默认值为 600 秒,即 10 分钟。根据您尝试通过使用默认连接跟踪行为的链路发送的流量类型,可能需要更改此值。特别是如果您通过卫星等网络传输流量,这可能需要很长时间。
复杂协议和连接跟踪
[edit | edit source]某些协议比其他协议更复杂。当涉及到连接跟踪时,这意味着这些协议可能更难正确跟踪。这些协议的典型例子是 ICQ、IRC 和 FTP 协议。这些协议中的每一个都在数据包的实际数据有效负载中携带信息,因此需要特殊的连接跟踪帮助程序才能使其正常工作。
以 FTP 协议为例。FTP 协议首先打开一个称为 FTP 控制会话的单一连接。当我们通过此会话发出命令时,其他端口将被打开以承载与该特定命令相关联的其余数据。这些连接可以通过两种方式进行,主动或被动。当连接被主动建立时,FTP 客户端向服务器发送一个端口和 IP 地址以进行连接。之后,FTP 客户端打开端口,服务器从自己的端口 20(称为 FTP-Data)连接到该指定端口,并通过它发送数据。
这里的问题是,防火墙将不知道这些额外的连接,因为它们是在协议数据的实际有效负载中协商的。因此,防火墙将无法知道它应该允许服务器通过这些特定端口连接到客户端。
解决此问题的方法是向连接跟踪模块添加一个特殊的帮助程序,该帮助程序将扫描控制连接中的数据以查找特定语法和信息。当它遇到正确的信息时,它会将该特定信息添加为相关信息,并且服务器将能够跟踪连接,这要归功于该相关条目。考虑以下图片以了解 FTP 服务器连接回客户端时的状态。
被动 FTP 以相反的方式工作。FTP 客户端告诉服务器它想要一些特定数据,服务器会回复一个连接的 IP 地址和端口。客户端收到此数据后,将从自己的端口 20(FTP-data 端口)连接到该特定端口,并获取相关数据。换句话说,如果您的防火墙后面有一个 FTP 服务器,除了标准 iptables 模块之外,您还需要此模块才能让 Internet 上的客户端正确连接到 FTP 服务器。如果您对用户极其严格,并且只希望他们访问 Internet 上的 HTTP 和 FTP 服务器并阻止所有其他端口,也是如此。考虑以下图像及其对被动 FTP 的影响。
某些 conntrack 帮助程序已在内核本身中可用。更具体地说,截至本文撰写时,FTP 和 IRC 协议已包含 conntrack 帮助程序。如果您在内核本身中找不到所需的 conntrack 帮助程序,您应该查看用户空间 iptables 中的 patch-o-matic 树。patch-o-matic 树可能包含更多 conntrack 帮助程序,例如用于 ntalk 或 H.323 协议的帮助程序。
Conntrack 帮助程序可以静态编译到内核中,也可以作为模块编译。如果它们作为模块编译,您可以使用以下命令加载它们
modprobe ip_conntrack_*
请注意,连接跟踪与 NAT 无关,因此如果您也正在进行 NAT 连接,则可能需要更多模块。例如,如果您想 NAT 并跟踪 FTP 连接,您还需要 NAT 模块。所有 NAT 帮助程序都以 ip_nat_ 开头,并遵循该命名约定;因此,例如,FTP NAT 帮助程序将命名为 ip_nat_ftp,而 IRC 模块将命名为 ip_nat_irc。conntrack 帮助程序遵循相同的命名约定,因此 IRC conntrack 帮助程序将命名为 ip_conntrack_irc,而 FTP conntrack 帮助程序将命名为 ip_conntrack_ftp。
如何构建规则
[edit | edit source]正如我们已经解释的,每个规则都是内核查看的一行,以找出如何处理数据包。如果满足所有条件(或匹配),我们将执行目标(或跳转)指令。通常我们会以类似于这样的语法编写我们的规则
iptables [-t table] command [match] [target/jump]
没有任何规定说目标指令必须是行中的最后一个函数。但是,您通常会坚持这种语法以获得最佳可读性。无论如何,您将看到的大多数规则都是以这种方式编写的。因此,如果您阅读了其他人的脚本,您很可能会识别出语法并轻松理解规则。
如果您想使用其他表而不是标准表,您可以在指定 [table] 的位置插入表规范。但是,不需要明确说明要使用哪个表,因为默认情况下 iptables 使用 filter 表来实现所有命令。您也不必只在规则中的这一点处指定表。它几乎可以设置在行中的任何地方。但是,将表规范放在开头是或多或少标准的做法。
但有一点需要考虑:命令应始终放在最前面,或者可选地直接放在表规范之后。我们使用“command”来告诉程序要做什么,例如插入规则或将规则添加到链的末尾,或者删除规则。我们将在下面进一步讨论这一点。匹配是我们发送到内核的规则部分,它详细说明了数据包的具体特征,是什么使它与所有其他数据包不同。在这里,我们可以指定数据包来自哪个 IP 地址、来自哪个网络接口、目标 IP 地址、端口、协议或其他任何内容。我们可以使用大量的不同匹配,我们将在下面进一步讨论这些匹配。
最后我们有了数据包的目标。如果所有匹配都满足了某个数据包,我们会告诉内核如何处理它。例如,我们可以告诉内核将数据包发送到我们自己创建的另一个链,该链是该特定表的组成部分。我们可以告诉内核直接丢弃数据包,不再进行处理,或者我们可以告诉内核向发送者发送指定的回复。与本节中的其余内容一样,我们将在下面进一步讨论它。
表格
[edit | edit source]-t 选项指定要使用的表。默认情况下,使用 filter 表。我们可以使用 -t 选项指定以下表之一。请注意,这是一个极其简短的摘要
命令
[edit | edit source]在本节中,我们将介绍所有不同的命令以及如何使用它们。该命令告诉 iptables 如何处理我们发送到解析器的规则的其余部分。通常我们想要在某个表中添加或删除某些内容。以下命令可用于 iptables
除非您只是想查看 iptables 的内置帮助或获取命令的版本,否则您应始终输入完整的命令行。要获取版本,请使用 -v 选项,要获取帮助信息,请使用 -h 选项。像往常一样,换句话说。接下来是一些可以在不同命令中使用的选项。请注意,我们会告诉您哪些命令可以使用这些选项以及它们会产生什么影响。还要注意,这里不包含任何影响规则或匹配的选项。相反,我们将在本章的后面部分介绍匹配和目标。
选项
匹配
[edit | edit source]首先,我们有通用的匹配,它们可以在所有规则中使用。然后我们有 TCP 匹配,它们只能应用于 TCP 数据包。我们有 UDP 匹配,它们只能应用于 UDP 数据包,还有 ICMP 匹配,它们只能用于 ICMP 数据包。最后,我们有特殊的匹配,例如状态、所有者和限制匹配等等。这些最终的匹配又进一步细分为更多子类别,即使它们可能并不一定是不同的匹配。
通用匹配
[edit | edit source]本节将介绍通用匹配。通用匹配是一种始终可用的匹配,无论我们使用哪种协议,或者加载了哪些匹配扩展。使用这些匹配不需要任何特殊参数;换句话说。我还包括了 --protocol 匹配,即使它更特定于协议匹配。例如,如果我们想使用 TCP 匹配,我们需要使用 --protocol 匹配并将 TCP 作为选项发送给匹配。但是,--protocol 本身也是一个匹配,因为它可以用于匹配特定协议。以下匹配始终可用。
通用匹配
隐式匹配
[edit | edit source]这些是隐式加载的匹配。隐式匹配是隐含的、理所当然的、自动的。例如,当我们匹配 --protocol tcp 而不使用任何其他条件时。目前,三种协议有三种类型的隐式匹配。它们是 TCP 匹配、UDP 匹配和 ICMP 匹配。基于 TCP 的匹配包含一组仅适用于 TCP 数据包的唯一条件。基于 UDP 的匹配包含另一组仅适用于 UDP 数据包的条件。ICMP 数据包也是如此。另一方面,可以有显式匹配,它们是显式加载的。显式匹配不是隐含的或自动的,您必须专门指定它们。对于这些匹配,您使用 -m 或 --match 选项,我们将在下一节中讨论。
TCP 匹配
[edit | edit source]这些匹配是特定于协议的,并且仅在使用 TCP 数据包和流时可用。要使用这些匹配,您需要在尝试使用它们之前在命令行中指定 --protocol tcp。请注意,--protocol tcp 匹配必须位于协议特定匹配的左侧。从某种意义上说,这些匹配是隐式加载的,就像 UDP 和 ICMP 匹配是隐式加载的一样。其他匹配将在 TCP 匹配部分之后在本节的后续部分中进行介绍。
UDP 匹配
[edit | edit source]将仅与 UDP 数据包一起使用。当您指定 --protocol UDP 匹配时,这些匹配会隐式加载,并且在进行此指定后会可用。请注意,UDP 数据包不是面向连接的,因此没有在数据包中设置不同的标志以提供有关数据报应该执行的操作(例如打开或关闭连接,或者它们是否应该简单地发送数据)的信息。UDP 数据包也不需要任何类型的确认。如果它们丢失,它们就会简单地丢失(不考虑 ICMP 错误消息等)。这意味着与 TCP 数据包相比,UDP 数据包的匹配要少得多。请注意,状态机将处理所有类型的数据包,即使 UDP 或 ICMP 数据包被视为无连接协议。状态机在 UDP 数据包上的工作方式与在 TCP 数据包上的工作方式基本相同。
ICMP 匹配
[edit | edit source]这些是 ICMP 匹配。从某种意义上说,这些数据包比 UDP 数据包更短暂,即生命周期更短,因为它们是无连接的。ICMP 协议主要用于错误报告以及连接控制等。ICMP 不是 IP 协议的从属协议,而是一种增强 IP 协议并帮助处理错误的协议。ICMP 数据包的报头与 IP 报头非常相似,但在许多方面有所不同。该协议的主要特征是类型报头,它告诉我们数据包的用途。例如,如果我们尝试访问不可访问的 IP 地址,通常会收到 ICMP 主机不可达的回复。有关 ICMP 类型的完整列表,请参阅 ICMP 类型的附录。ICMP 数据包只有一个可用的 ICMP 特定匹配,希望这应该足够了。当我们使用 --protocol ICMP 匹配时,此匹配会隐式加载,并且我们可以自动访问它。请注意,所有通用匹配也可以使用,因此除了其他事项之外,我们还可以匹配源地址和目标地址。
显式匹配
[edit | edit source]显式匹配是指必须使用 -m 或 --match 选项专门加载的匹配。例如,状态匹配要求在输入您要使用的实际匹配之前使用指令 -m state。其中一些匹配可能是特定于协议的。有些可能与任何特定协议无关——例如连接状态。它们可能是 NEW(尚未建立的连接的第一个数据包)、ESTABLISHED(已在内核中注册的连接)、RELATED(由较旧的已建立连接创建的新连接)等等。少数可能只是为了测试或实验目的而发展而来,或者只是为了说明 iptables 的功能。这反过来意味着并非所有这些匹配乍一看都有用。然而,您个人很可能会发现某些显式匹配的用途。而且,随着每个新 iptables 版本的发布,不断有新的匹配出现。您是否会找到它们的用途取决于您的想象力和需求。隐式加载的匹配和显式加载的匹配之间的区别在于,隐式加载的匹配将在您匹配 TCP 数据包的属性时自动加载,而显式加载的匹配永远不会自动加载——您需要自己发现并激活显式匹配。
限制匹配
[edit | edit source]限制匹配扩展必须使用 -m limit 选项显式加载。例如,此匹配可以用来有效地限制特定规则的日志记录等。例如,您可以使用它来匹配所有不超过给定值的包,并且在超过此值后,限制对所述事件的日志记录。想想时间限制:您可以限制某个规则在某个时间范围内匹配的次数,例如减少 DoS syn 泛洪攻击的影响。这是它的主要用法,当然还有更多用法。限制匹配也可以通过在限制匹配前面添加 ! 标志来反转。它将被表示为 -m limit ! --limit 5/s。这意味着所有数据包在超出限制后都会被匹配。
为了进一步解释限制匹配,它基本上是一个令牌桶过滤器。想象有一个漏桶,桶以每时间单位 X 个数据包的速度漏水。X 的定义取决于我们获得的匹配数据包数量,因此如果我们获得 3 个数据包,则桶以每时间单位 3 个数据包的速度漏水。--limit 选项告诉我们每时间单位向桶中补充多少个数据包,而 --limit-burst 选项告诉我们桶最初有多大。因此,设置 --limit 3/minute --limit-burst 5,然后接收 5 个匹配项将清空桶。20 秒后,桶会补充另一个令牌,以此类推,直到再次达到 --limit-burst 或直到它们被使用。
请考虑以下示例,以进一步说明这可能是什么样子。
- 我们使用 -m limit --limit 5/second --limit-burst 10 设置一个规则。limit-burst 令牌桶最初设置为 10。每个与规则匹配的数据包都会使用一个令牌。
- 我们得到与规则匹配的数据包,1-2-3-4-5-6-7-8-9-10,所有数据包都在 1/1000 秒内。
- 令牌桶现在为空。一旦令牌桶为空,否则符合规则的数据包不再与规则匹配,并将继续到下一个规则(如果有),或命中链策略。
- 每隔 1/5 秒如果没有匹配的包,令牌计数就会增加 1,直到达到最大值 10。在收到 10 个包后 2 秒,我们将再次剩下 10 个令牌。
- 当然,对于每个收到的包,桶的令牌数量都会减少 1。
MAC(以太网介质访问控制)匹配可以用来根据包的 MAC 源地址进行匹配。截至撰写本文档时,这种匹配功能有一些限制,但在未来可能会得到改进,变得更加实用。这种匹配只能用于根据源 MAC 地址进行匹配。
请注意,要使用此模块,我们需要使用 -m mac 选项显式加载它。我之所以说这一点,是因为很多人想知道是否应该使用 -m mac-source,而实际上不应该。
标记匹配扩展用于根据包所设置的标记进行匹配。标记是一个特殊的字段,仅在内核中维护,它与包在计算机中传输时相关联。标记可供不同的内核例程用于诸如流量整形和过滤之类的任务。截至目前,在 Linux 中只有一种设置标记的方法,即 iptables 中的 MARK 目标。这以前是用 ipchains 中的 FWMARK 目标完成的,这就是为什么人们在高级路由领域仍然提到 FWMARK 的原因。标记字段当前设置为无符号整数,或 32 位系统上 4294967296 个可能的取值。换句话说,你很可能很长时间不会遇到这个限制。
多端口匹配扩展可以用来指定多个目标端口和端口范围。如果没有此匹配功能,你将不得不使用多个相同类型的规则来匹配不同的端口。
你不能同时使用标准端口匹配和多端口匹配,例如,你不能这样写:--sport 1024:63353 -m multiport --dport 21,23,80。这将无法工作。事实上,如果你这样写,iptables 会优先处理规则中的第一个元素,而忽略 multiport 指令。
所有者匹配扩展用于根据创建包的进程身份进行匹配。所有者可以指定为发出该命令的用户、组、进程、会话或命令本身的进程 ID。此扩展最初是作为 iptables 用途的一个例子而编写的。所有者匹配只在 OUTPUT 链中起作用,原因很明显:几乎不可能从另一端找出发送包的实例的身份信息,或者从中间跳跃到真实目标的实例的身份信息。即使在 OUTPUT 链中,它也不太可靠,因为某些包可能没有所有者。这类臭名昭著的包(除其他外)是不同的 ICMP 响应。ICMP 响应永远不会匹配。
状态匹配扩展与内核中的连接跟踪代码结合使用。状态匹配访问 conntracking 机器的包的连接跟踪状态。这使我们能够知道连接处于什么状态,并且适用于几乎所有协议,包括无状态协议,例如 ICMP 和 UDP。在所有情况下,连接将有一个默认超时时间,然后它将从连接跟踪数据库中删除。此匹配需要通过向规则添加 -m state 语句来显式加载。然后你就可以使用一个名为 state 的新匹配。
TOS 匹配可以用来根据包的 TOS 字段进行匹配。TOS 代表**服务类型**,由 8 位组成,位于 IP 首部。此匹配通过向规则添加 -m tos 来显式加载。TOS 通常用于通知中间主机流及其内容的优先级(它实际上并没有通知,而是通知流的任何特定要求,例如必须以最快的速度发送,或者需要能够发送尽可能多的有效载荷)。不同的路由器和管理员如何处理这些值取决于他们自己。大多数人根本不在乎,而另一些人则尽力对这些包及其提供的数据做一些有益的事情。
TTL 匹配用于根据位于 IP 首部中的 TTL(生存时间)字段进行匹配。TTL 字段包含 8 位数据,每当它被客户端和接收主机之间的中间主机处理一次,它就会减 1。如果 TTL 达到 0,则会向发送包的一方发送一个 ICMP 类型 11 代码 0(传输过程中 TTL 等于 0)或代码 1(重新组装过程中 TTL 等于 0)的报文,通知它出现的问题。此匹配仅用于根据包的 TTL 进行匹配,而不会更改任何内容。顺便说一下,这适用于所有类型的匹配。要加载此匹配,你需要向规则添加 -m ttl。
目标/跳转告诉规则如何处理与规则匹配部分完全匹配的包。有几个基本目标,ACCEPT 和 DROP 目标,我们将首先讨论它们。但是,在我们这样做之前,让我们简要地看一下跳转是如何完成的。
跳转规范与目标定义完全相同,只是它需要在同一个表内的链中进行跳转。要跳转到一个特定的链,前提是该链存在。正如我们已经解释过的,用户定义的链是用 -N 命令创建的。例如,假设我们在 filter 表中创建一个名为 tcp_packets 的链,如下所示:iptables -N tcp_packets
然后我们可以向它添加一个跳转目标,如下所示
iptables -A INPUT -p tcp -j tcp_packets
然后我们将从 INPUT 链跳转到 tcp_packets 链,并开始遍历该链。当我们到达该链的末端时,我们会被丢回到 INPUT 链,并且包会从跳转到另一个链(本例中是 tcp_packets)的规则下面一步开始遍历。如果一个包在其中一个子链中被 ACCEPT,它也会在超集链中被 ACCEPT,并且它不会再遍历任何超集链。但是,请注意,该包将按照正常方式遍历其他表中的所有其他链。
另一方面,目标指定对目标包采取的操作。例如,我们可以根据我们的需要来 DROP 或 ACCEPT 该包。我们可能还想采取其他一些操作,我们将在本节后面部分对此进行描述。跳转到目标可能会带来不同的结果。有些目标会导致包停止遍历该特定链和上面的链,如上所述。此类规则的典型例子是 DROP 和 ACCEPT。停止的规则不会通过该链中或上面链中的任何其他规则。其他目标可能会对包采取操作,然后包将继续通过同一组链中的其他规则。这方面的典型例子是 LOG、ULOG 和 TOS 目标。这些目标可以记录包、对其进行修改,然后将其传递给同一组链中的其他规则。例如,我们可能会: