简介
前面文章主要介绍的是nftables的基本原理和基础的配置,如nftables基本的表、链、规则的创建和管理。本篇文章主要介绍的是表达式EXPRESSIONS。
在网络安全和数据处理中,表达式(Expressions)扮演着非常重要的角色。它们用于表示值,这些值可以是常量(如网络地址、端口号等),也可以是在规则集评估过程中从数据包中收集的数据。表达式可以通过二进制、逻辑、关系和其他类型的表达式组合来形成复杂或关系(匹配)表达式。此外,表达式还用作某些类型操作(如网络地址转换NAT、数据包标记等)的参数。
每个表达式都有其数据类型,这决定了符号值的大小、解析方式、表示形式以及与其他表达式进行类型兼容性检查的方式。数据类型对于确保表达式的正确执行和结果的准确性至关重要。
通过description命令显示表达式的类型及其数据类型的信息。还可以给出一个数据类型,nft将在其中显示有关该类型的更多信息。
describe expression | data type
数据类型
数据类型(Data Types)是极其重要的概念,它们决定了符号值的大小、解析方式、表示形式以及表达式之间的类型兼容性。一下我们介绍几种常见的数据类型:
INTEGER TYPE(整数类型)
Name | Keyword | Size | Base type |
Integer | integer | variable | - |
整数类型用于表示数值,可以是以十进制、十六进制或八进制形式指定的数字。整数类型的大小不是固定的,而是取决于它被使用的上下文或表达式。例如,在某些编程语言或系统中,整数可以是8位、16位、32位或64位,这取决于系统架构、编译器选项或程序员的指定。
BITMASK TYPE(位掩码类型)
Name | Keyword | Size | Base type |
Bitmask | bitmask | variable | integer |
位掩码类型用于表示一组位(bit),其中每个位都可以独立地设置为开(1)或关(0)。位掩码常用于控制选项或设置状态,因为它们允许在一个单独的值中存储多个布尔值。位掩码类型基于整数类型,因为整数提供了存储和操作位所需的底层机制。
STRING TYPE(字符串类型)
Name | Keyword | Size | Base type |
String | string | variable | - |
字符串类型用于表示文本数据,即一系列字符。字符串的开头通常是一个字母字符(a-zA-Z),后面可以跟零个或多个字母数字字符或特定字符(如/、-、_、.)。此外,任何被双引号(")包围的内容都被视为字符串。这允许在字符串中包含那些可能被视为特殊字符的字符。
#例如如何在网络过滤规则中指定接口名称。
# Interface name
filter input iifname eth0
# Weird interface name
filter input iifname "(eth0)"
LINK LAYER ADDRESS TYPE(链路层地址类型)
Name | Keyword | Size | Base type |
Link layer address | lladdr | variable | integer |
链路层地址类型(lladdr
)用于表示链路层地址,如以太网MAC地址。这些地址通常由一系列以冒号(:)分隔的两位十六进制数字组成,数量是可变的。尽管其大小是可变的,但每个MAC地址通常由6个八位字节(即48位)组成,但在指定时,格式上的冒号不计入实际大小。
#以太网目标MAC地址:这条规则指定了数据包输入过滤时,目标以太网MAC地址应为 00:0c:29:0f:37:05
filter input ether daddr 00:0c:29:0f:37:05
IPV4 ADDRESS TYPE(IPv4地址类型)
Name | Keyword | Size | Base type |
IPV4 address | ipv4_addr | 32 bit | integer |
IPv4地址类型(ipv4_addr
)用于表示IPv4地址。这些地址通常是32位的,并可以通过多种方式指定,包括点分十进制、点分十六进制、点分八进制、十进制、十六进制、八进制表示法或作为主机名。如果指定为主机名,则使用标准系统解析器进行解析。
#点分十进制表示法:这条规则指定了数据包输出过滤时,目标IPv4地址应为127.0.0.1(即本地回环地址)。
filter output ip daddr 127.0.0.1#主机名表示法:这条规则指定了数据包输出过滤时,目标IPv4地址应通过主机名localhost解析得出。
filter output ip daddr localhost
IPV6 ADDRESS TYPE(IPv6地址类型)
Name | Keyword | Size | Base type |
IPv6 address | ipv6_addr | 128 bit | integer |
IPv6地址类型(ipv6_addr
)用于表示IPv6地址。这些地址是128位的,并可以指定为主机名或一系列由冒号分隔的十六进制半字(每个半字通常为4位十六进制数)。为了与端口号区分,IPv6地址有时会被方括号([]
)包围。
#缩写回环地址:这条规则指定了数据包输出过滤时,目标IPv6地址应为缩写形式的回环地址::1
filter output ip6 daddr ::1#带方括号的IPv6地址:这条规则指定了在IPv6地址转换的预路由阶段,如果TCP目标端口为20000,则将其目的地址转换为[1df::d0],并指定目标端口为22。方括号的使用确保了1df::d0被正确解析为IPv6地址,而不是与端口号混淆
ip6 nat prerouting tcp dport 20000 dnat to [1df::d0]:22
BOOLEAN TYPE(布尔类型)
Name | Keyword | Size | Base type |
Boolean | boolean | 1 bit | integer |
布尔类型(boolean
)在用户空间中是一个语法辅助类型,主要用于在(通常是隐式的)关系表达式的右侧,将左侧表达式转换为布尔检查(通常用于检查存在性)。尽管布尔类型在底层实现上可能占用更多的存储空间(比如一个字节或更多),但在逻辑上它被视为1位大小,即只能存储两个值:0(假)或1(真)。在大多数上下文中,布尔类型被映射到整数类型,其中0表示假,非0值(如1)表示真。
关键字与值
Keyword | Value |
exists表示存在,对应值为1(真) | 1 |
missing表示不存在,对应值为0(假) | 0 |
表达式支持布尔比较(boolean comparison)
表达式(expressions)支持布尔比较(boolean comparison)是一种非常常见且重要的特性。布尔比较允许你根据两个或多个值之间的关系来评估表达式的结果为真(true)或假(false)。这种机制在条件语句(如if语句)、循环控制(如while循环)以及很多其他需要基于条件逻辑进行决策的场景中都是不可或缺的。
Expression | Behaviour |
fib | 检查路由是否存在。这通常用于过滤规则中,以确定数据包是否匹配特定的路由。 |
exthdr | 检查IPv6扩展头是否存在。这允许在IPv6流量中根据扩展头的存在性来过滤数据包。 |
tcp option | 检查TCP选项头是否存在。这允许基于TCP选项(如时间戳选项)的存在性来过滤TCP数据包。 |
#匹配存在的路由:这条规则表示如果输入的数据包存在匹配的路由(即fib daddr表达式为真),并且指定的入接口(iif)和出接口(oif)也匹配,则该数据包将被匹配。注意这里的exists关键字用于将fib daddr的结果转换为布尔值。
filter input fib daddr . iif oif exists#仅匹配IPv6非分片数据包:这条规则表示如果输入的数据包是IPv6数据包,并且没有分片扩展头(即frag扩展头不存在),则该数据包将被匹配。
filter input exthdr frag missing#匹配包含TCP时间戳选项的数据包:这条规则表示如果输入的数据包是TCP数据包,并且包含时间戳选项(即tcp option timestamp存在),则该数据包将被匹配。这允许基于TCP数据包的特定选项来过滤流量
filter input tcp option timestamp exists
ICMP TYPE TYPE(ICMP类型)
Name | Keyword | Size | Base type |
ICMP Type | icmp_type | 8 bit | integer |
ICMP(Internet Control Message Protocol,互联网控制消息协议)类型是一个用于方便指定ICMP头部类型字段的类型。ICMP是IP网络中的一个重要协议,用于发送控制消息,如错误报告、路由信息请求等。ICMP类型字段定义了ICMP消息的具体类型,每种类型都有其特定的用途和含义。
Keyword | Value | 解释 |
echo-reply | 0 | 表示ICMP回显应答消息,通常是对echo-request (ping请求)的响应 |
destination-unreachable | 3 | 表示目的不可达消息,用于通知发送方数据包无法到达其目的地 |
source-quench | 4 | 已废弃,原用于拥塞控制,但现在已被新的机制所取代 |
redirect | 5 | 表示重定向消息,用于指导发送方将数据包发送到更好的路由 |
echo-request | 8 | 表示ICMP回显请求消息,通常用于生成ping请求 |
router-advertisement | 9 | 路由器通告消息,用于动态地通知主机有关路由器的信息 |
router-solicitation | 10 | 路由器请求消息,用于请求路由器发送其通告。 |
time-exceeded | 11 | 表示生存时间(TTL)超过消息,用于通知发送方数据包在到达目的地之前已被丢弃,因为其TTL已减至0 |
parameter-problem | 12 | 表示参数问题消息,用于通知发送方其数据包中的某个字段有错误 |
timestamp-request | 13 | 时间戳请求消息,用于请求接收方记录并返回数据包的接收时间 |
timestamp-reply | 14 | 时间戳应答消息,是对timestamp-request 的响应,包含接收时间 |
info-request | 15 | 用于请求关于网络或主机的特定信息 |
info-reply | 16 | 是对info-request (信息请求)消息的响应。它包含了请求方所请求的信息 |
address-mask-request | 17 | 信息请求消息,用于请求有关地址掩码的信息(在某些实现中可能称为地址掩码请求) |
address-mask-reply | 18 | 信息应答消息,是对info-request 的响应,包含请求的信息 |
#匹配ping数据包:这条规则表示匹配输出方向上的ICMP数据包,其类型字段为echo-request(ping请求)或echo-reply(ping应答)。这通常用于允许或过滤ping操作,以测试网络连通性或进行故障排查。
filter output icmp type { echo-request, echo-reply }
ICMP CODE TYPE(ICMP代码类型)
Name | Keyword | Size | Base type |
ICMP Code | icmp_code | 8 bit | integer |
ICMP(Internet Control Message Protocol,互联网控制消息协议)代码类型用于方便地指定ICMP头部的代码字段。ICMP消息不仅由类型字段标识其大致的类别,还通过代码字段提供更具体的错误或信息类型。这使得接收方能够更准确地了解发送ICMP消息的原因。
Keyword | Value | 解释 |
net-unreachable | 0 | 表示网络不可达。这通常意味着没有到达目标网络的路由 |
host-unreachable | 1 | 表示主机不可达。这通常意味着目标主机在指定的网络上不存在或无法访问 |
prot-unreachable | 2 | 表示协议不可达。这表示目标主机不支持发送方尝试使用的协议 |
port-unreachable | 3 | 表示端口不可达。这表示目标主机上的特定端口没有监听或无法访问 |
frag-needed | 4 | 表示需要分片但DF(Don't Fragment)位被设置。这通常发生在数据包太大而无法通过某个网络段时,但发送方已请求不进行分片 |
net-prohibited | 9 | 表示网络被禁止。这通常是由于设置的策略,阻止数据包进入或离开指定的网络 |
host-prohibited | 10 | 表示主机被禁止。这通常表示目标主机已明确拒绝接收数据包,可能是出于安全或配置的原因 |
admin-prohibited | 13 | 表示管理禁止。这是一个更通用的“被禁止”代码,可能用于表示由于管理策略而阻止数据包传递的多种情况 |
ICMP代码的作用
ICMP代码与ICMP类型字段结合使用,提供了关于ICMP消息的更详细信息。这有助于接收方理解为什么发送了ICMP消息,并据此采取相应的行动。例如,如果接收到一个destination-unreachable
(类型3)和port-unreachable
(代码3)的ICMP消息,接收方就知道数据包无法到达目标端口,并可能尝试使用不同的端口或协议重新发送数据包。
注意事项
- 并非所有ICMP类型都有对应的代码字段。有些ICMP类型可能只使用类型字段,而不使用代码字段。
- ICMP代码的具体含义可能因不同的系统和网络实现而异。因此,在编写依赖于特定ICMP代码的逻辑时,需要仔细考虑这些因素。
- ICMP消息本身并不携带原始数据包的全部内容,而是包含有关原始数据包的一些关键信息(如IP头部和至少前8个字节的数据)。这有助于接收方了解哪些数据包遇到了问题,但可能不足以完全重建原始数据包。
ICMPv6 TYPE TYPE(ICMPv6 类型)
Name | Keyword | Size | Base type |
ICMPv6 Type | icmpx_code | 8 bit | integer |
ICMPv6(Internet Control Message Protocol version 6)类型用于方便地指定ICMPv6头部的类型字段。ICMPv6是IPv6协议栈中的一部分,用于发送控制消息,如错误报告、信息请求和响应等。与ICMPv4相比,ICMPv6在消息类型和目的上有所扩展,以支持IPv6网络的特定需求。
Keyword | Value | 解释 |
destination-unreachable | 1 | 表示目的不可达消息,用于通知发送方数据包无法到达其目的地 |
packet-too-big | 2 | 表示数据包太大,无法通过网络段而不进行分片。这通常与路径MTU发现过程相关 |
time-exceeded | 3 | 表示生存时间(TTL)或跳数限制(Hop Limit)超过,数据包在到达目的地之前已被丢弃 |
parameter-problem | 4 | 表示ICMPv6头部中的某个字段存在错误 |
echo-request | 128 | 表示ICMPv6回显请求消息,通常用于生成ping请求 |
echo-reply | 129 | 表示ICMPv6回显应答消息,是对echo-request 的响应 |
mld-listener-query | 130 | 组播侦听器发现(Multicast Listener Discovery, MLD)查询消息,用于发现网络上的组播侦听器 |
mld-listener-report | 131 | 组播侦听器报告消息,由组播侦听器发送以响应MLD查询或主动报告其存在 |
mld-listener-done | 132 | mld-listener-done 和 mld-listener-reduction :均标记为132,但mld-listener-reduction 可能是对mld-listener-done 的一个补充或特定用途的变体,用于指示组播侦听器数量的减少 |
mld-listener-reduction | 132 | |
nd-router-solicit | 133 | 邻居发现(Neighbor Discovery, ND)路由器请求消息,用于请求路由器发送其通告 |
nd-router-advert | 134 | 邻居发现路由器通告消息,包含有关网络配置的信息 |
nd-neighbor-solicit | 135 | 邻居发现邻居请求消息,用于请求邻居的链路层地址 |
nd-neighbor-advert | 136 | 邻居发现邻居通告消息,包含邻居的链路层地址 |
nd-redirect | 137 | 邻居发现重定向消息,用于指导发送方将数据包发送到更好的路由 |
router-renumbering | 138 | 路由器重编号消息,用于在IPv6网络中重新分配地址 |
ind-neighbor-solicit | 141 | 无组播邻居发现协议中的邻居请求报文 |
ind-neighbor-advert | 142 | 无组播邻居发现协议中的邻居通告报文 |
mld2-listener-report | 143 | MLD2 协议中的监听器报告 |
#匹配ICMPv6 ping数据包:这条规则表示匹配输出方向上的ICMPv6数据包,其类型字段为echo-request(ICMPv6 ping请求)或echo-reply(ICMPv6 ping应答)。这通常用于允许或过滤ICMPv6 ping操作,以测试IPv6网络的连通性或进行故障排查。
filter output icmpv6 type { echo-request, echo-reply }
ICMPv6 CODE TYPE(ICMPv6代码类型)
Name | Keyword | Size | Base type |
ICMPv6 Code | icmpv6_code | 8 bit | integer |
ICMPv6代码(Code)类型用于方便地指定ICMPv6头部的代码字段。这个字段提供了关于ICMPv6消息类型的进一步细分,以更精确地指示发生了什么问题或需要什么样的响应。
Keyword | Value | 解释 |
no-route | 0 | 表示没有到目标地址的路由。这通常是由于路由表中没有匹配的条目导致的 |
admin-prohibited | 1 | 表示由于管理策略,数据包被禁止传输。这通常是由网络管理员设置的规则所触发的 |
addr-unreachable | 3 | 表示目标地址不可达。这可能是因为目标地址不存在于链路上,或者地址是一个多播地址但当前没有侦听器 |
port-unreachable | 4 | 表示目标端口不可达。这意味着数据包已到达目标主机,但目标端口没有监听或无法访问 |
policy-fail | 5 | 表示由于路由策略失败,数据包被丢弃。这可能与路由策略、流量工程或安全策略有关 |
reject-route | 6 | 表示数据包被拒绝,因为存在一条明确拒绝该数据包的路由。这通常是为了防止某些类型的数据包进入网络而设置的 |
ICMPv6代码的作用
ICMPv6代码与ICMPv6类型字段结合使用,为接收方提供了关于为什么发送ICMPv6消息的详细信息。这有助于接收方理解数据包未能成功传输的原因,并据此采取相应的行动。例如,如果接收到一个destination-unreachable
(类型1)和no-route
(代码0)的ICMPv6消息,接收方就知道数据包无法到达其目的地,因为没有到目标地址的路由。
CONNTRACK TYPES
在Linux网络子系统中,conntrack
(连接跟踪)是一个重要的组件,用于跟踪和记录通过网络接口进出的网络连接。这有助于实现如NAT(网络地址转换)、防火墙规则等网络功能。您提供的表格概述了conntrack
表达式和语句中使用的几种类型及其关键字和值。
conntrack 类型
Name | Keyword | Size | Base type | 解释 |
conntrack state | ct_state | 4 byte | bitmask | 表示连接的状态,如新建、已建立、相关等 |
conntrack direction | ct_dir | 8 bit | integer | 表示数据包的方向,是原始数据包还是回复数据包 |
conntrack status | ct_status | 4 byte | bitmask | 提供有关连接状态的额外信息,如是否已确认、是否进行了NAT等 |
conntrack event bits | ct_event | 4 byte | bitmask | 标记连接跟踪过程中的事件,如新建连接、连接销毁等 |
conntrack label | ct_label | 128 bit | bitmask | 用于给连接分配标签,这些标签可以在运行时从配置文件中读取 |
conntrack state (ct_state)
Keyword | Value | 解释 |
invalid | 1 | 连接无效或已过期 |
established | 2 | 连接已建立 |
related | 4 | 连接与已建立的连接相关(如FTP数据连接) |
new | 8 | 新建的连接 |
untracked | 64 | 连接未被跟踪(可能由于配置或策略) |
conntrack direction (ct_dir)
Keyword | Value | 解释 |
original | 0 | 原始数据包的方向(从客户端到服务器) |
reply | 1 | 原始数据包的方向(从客户端到服务器) |
conntrack status (ct_status)
Keyword | Value | 解释 |
expected | 1 | 预期中的连接(如FTP主动模式下的数据连接) |
seen-reply | 2 | 已看到回复数据包 |
assured | 4 | 连接已得到保证 |
confirmed | 8 | 连接已确认 |
snat | 16 | 进行了源地址NAT |
dnat | 32 | 进行了目标地址NAT |
dying | 512 | 连接正在消亡(如超时后) |
conntrack event bits (ct_event)
这些事件位用于在连接跟踪过程中标记不同的事件
Keyword | Value | 解释 |
new | 1 | 新建连接事件 |
related | 2 | 相关连接事件 |
destroy | 4 | 连接销毁事件 |
reply | 8 | 回复数据包事件 |
assured | 16 | 连接得到保证的事件 |
protoinfo | 32 | 协议信息更新事件 |
helper | 64 | 使用了连接跟踪辅助模块的事件 |
mark | 128 | 连接被标记的事件 |
seqadj | 256 | 序列号调整事件(如TCP序列号调整) |
secmark | 512 | 安全标记更新事件 |
label | 1024 | 连接标签更新事件 |
conntrack label (ct_label)
ct_label
允许给连接分配一个或多个标签,这些标签可以在运行时从配置文件中读取,如 /etc/connlabel.conf
。这对于基于标签的过滤和策略实施非常有用。
这些conntrack
类型和关键字是网络编程和系统管理中的重要工具,它们允许开发者和管理员更精细地控制网络流量的处理和路由。
DCCP PKTTYPE TYPE
Name | Keyword | Size | Base type |
DCCP packet type | dccp_pkttype | 4 bit | integer |
在DCCP(Datagram Congestion Control Protocol,数据报拥塞控制协议)中,包类型(Packet Type)是一个4位的字段,用于指示DCCP数据包的不同类型和目的。这个字段位于DCCP头部中,并根据RFC 4340标准定义了不同的值。这些值帮助网络中的节点理解和处理不同类型的DCCP数据包。
Keyword | Value | 解释 |
request | 0 | 表示这是一个连接请求包,用于初始化一个新的DCCP连接 |
response | 1 | 是对request包的响应,表示接受或拒绝连接请求 |
data | 2 | 包含应用层数据,但不包含确认信息 |
ack | 3 | 是一个纯确认包,不包含应用层数据,仅用于确认收到的数据 |
dataack | 4 | 同时包含应用层数据和确认信息,用于减少网络中的包数量 |
closereq | 5 | 用于请求关闭一个已经建立的DCCP连接 |
close | 6 | 是对closereq包的响应,表示同意关闭连接 |
reset | 7 | 用于异常终止一个DCCP连接,比如当检测到严重错误时 |
sync | 8 | 用于在连接建立时或连接过程中同步双方的状态信息 |
syncack | 9 | 是对sync包的确认,表示收到了同步信息并准备继续 |
值得注意的是,值10到15是保留的,根据RFC 4340,这些值不应该被使用。在iptables中,这些保留值被标记为INVALID,意味着如果匹配到这些值,将被视为无效或不被识别的DCCP包类型。而在nftables中,你可以直接匹配这些数值范围(即10-15),但通常不推荐这样做,因为它们没有定义的具体用途。
总结
以上就是我们介绍的一些主要的数据类型,通过数据类型和表达式相互配合,可以帮助用户根据特定的需求构建和评估规则集,从而实现对数据包的精确控制和处理。通过结合不同类型的表达式,用户可以更灵活地管理网络流量和执行各种网络操作。