Page tree

如需转载请标注内容地址为: https://wiki.shileizcc.com/confluence/display/firewall/nftables

Skip to end of metadata
Go to start of metadata

未经允许不得转载

iptables 与 nftables 的差别

在内核中,nftables 与 iptables 的过滤系统有重大的差异。nftables 不仅替代了 iptables 的功能,而且替代了 ip6tables 用于 IPv6、arptavles 用于 ARP 过滤、etables 用于以太网桥过滤的功能。nftables 的命令语法与 iptables 的命令语法有所不同,nftables 拥有使用额外脚本的能力。nftables 的管理程序叫做 nft,防火墙构建于此命令基础之上。

不同于 iptables,nftables 并不包含任何的内置表。由管理员决定需要哪些表并添加这些表的处理规则。

nftables 基本语法

nft 命令提供了用于构建防火墙的管理程序。nftables 命令的基本语法以 nft 程序本身开头,接下来是命令和子命令,以及各种各样的参数和表达式。下面是一个例子:

$ nft <command><subcommand><chain><rule definition>

典型的命令有 add、list、insert、delete 和 flush。

典型的子命令包括 tables、chain 和 rule。

ntftables 特性

nftables 拥有一些高级的类似编程语言的能力,例如定义变量和包含外部文件。nftables 也可以用于多种地址族的过滤和处理。这些地址族如下提示:

  • ip:IPv4 地址。
  • ip6:IPv6 地址。
  • inet:IPv4 和 IPv6 地址。
  • arp:地址解析协议(ARP)地址。
  • bridge:处理桥接数据包。

当没有指定地址族时,默认的是 IP。能够处理不同地址族的能力意味着 nftables 打算替代其他过滤机制,例如 etables 和 arptables。

nftables 的整个处理架构用于决定规则将应用于哪个地址族。然后,nftables 会使用一个或多个表,其中包含了一个或多个规则链,规则链则包含了处理规则。nftables 的处理规则由地址、端口、接口或包含在当前数据包中的其他数据等表达式以及诸多 drop、queue 和 continue 等声明组成。

注意:表包含规则链;规则链包含规则。

特定的地址族包含钩子,它是的 nftables 可以当数据包在 Linux 的网络堆栈中传输时访问到数据包。这意味着您可以在数据包被传递到路由之前或在它处理完毕之后对数据包执行一些操作。对 ip、ipv6 和 inet 地址族来说,可以应用下面的钩子。

  • prerouting:刚到达且并未被 nftables 的其他部分所路由或处理的数据包。
  • input:已经被接受而且已经经过 prerouting 钩子的传入数据包。
  • forward:如果数据包将被发送到另一个设备,它将会通过 forward 钩子。
  • output:从本地系统传出的数据包。
  • postrouting:仅仅在离开系统之前,postrouting 钩子使得可以对数据包进行进一步的处理。

ARP 地址族只能使用 input 钩子和 output 钩子。

nftables 语法

nft 命令本身有一些可以从命令行传入的选项,它们并不直接与定义过规则链相关。这些命令行选项包括如下。

ntables 命令语法表

命令说明
--debug <level, [level]>在 <level> 处 (例如:scanner、parser、eval、netlink、mnl、segtree、porto-ctx、或全部) 添加调试。
-h | --help显示基本帮助。
-v | --version显示 nft 的版本号。
-n | --numeric以数字方式显示地址和端口号信息而不执行名称解析。
-a | --handle显示规则句柄。
-I | --includepath <directory>将 <directory> 添加到包含文件的搜索路径中。
-f | --file <filname>将 <filename> 文件的内容包含进来。
-i | --interactive从命令行读取输入。

nftables 中没有预定义的表。同样的,由自定义希望在 nftables 系统中使用的表。定义一个规则的命令依赖于是在表、规则链还是在规则上进行操作。

表语法

在表上进行操作时,有下述四个命令可用。

  • add:添加一个表。
  • delete:删除一个表。
  • list:显示一个表中的所有规则链和规则。
  • flush:清除一个表中的所有规则链和规则。

可以使用下面的命令列出那些可用的表(以 root 权限运行):

$ nft list tables

记住,与 iptables 不同,nftables 中并没有默认表。因此,如果没有任何表被定义,则 list tables 命令则会返回空。如果刚刚建立了 nftables 而且还没有用它定义防火墙,那么这将会是预期内的行为。可以定义一个拥有普通防火墙规则链和规则的表,像这样:

$ nft add table filter

一旦防火墙的表被添加,list tables 命令将返回表的名称:

table filter

更多关于表的信息可以通过下面的命令收集:

$ nft list table filter

这样做会显示关于表的信息,包括任何定义在表中的规则链:

tableip filter {
}

例如所示,filter 表使用 IP 地址族,而且它目前为空。

此例子中的表叫做 filter,但它也可以被叫做任何名称,例如将其替换为 firewall。然而,通常的使用和 nftables 文档中的名称以及这里的例子都把该表称为 filter。

当要列出规则时,添加 -a 选项以查看句柄号是很有用的。句柄可以很容易的被用于修改或删除一条规则。

当列出防火墙规则时,nftables 将执行地址和端口解析。这个行为可以使用 -n 选项修改。添加两个 -n 选项可以同时防止地址和端口的解析,如下所示:

$ nft list table filter-nn

规则链语法

当在规则链上进行操作时,共有下述六个命令可用:

  • add:将在一条规则链添加到一个表中。
  • create:在一个表中创建一条规则链,除非该表中已经存在同名的规则链。
  • delete:删除一条规则链。
  • flush:清除一条规则链中的所有规则。
  • list:显示一条规则链中的所有规则。
  • rename:修改一条规则链的名称。

在添加一条规则链时,可以定义钩子。而且,可以将选择的优先级添加到规则链的定义中。

有三种基本的规则链类型,它们可以包含规则而且可以连接到之前描述过的钩子。规则链类型和钩子类型需要在规则链创建期间被定义,在通常的防火墙情境中,它们对规则链操作来说至关重要。如果规则链类型和钩子类型未被定义,数据包将不会被路由到此规则链。

三种基本的规则链类型如下:

  • filter:用于数据包过滤层。
  • route:用于数据包路由。
  • nat:用于网络地址转换(Network Address Translation,NAT)。

可以添加其他规则链以使用相似的规则组。当数据包的基础规则链中传输时,处理过程可以被路由到一个或多个用户定义的规则链以进行额外的处理。

当添加一条规则链时,必须指定规则链将要添加到的表。例如,下面的命令添加 input 规则链到 filter 表:

$ nft add chain filter input { type filter hook input priority 0 \; }

这条命令声明一个叫做 input 的规则链将被添加到名为 filter 的表中。规则链的类型是 filter,而且它将以优先级 0 被附加到 input 钩子。当从命令行中输入此命令时,需要在括号之间加一个空格跟一个分号。当次命令在本地 nft 脚本中使用时,空格和反斜线可以被忽略。

添加到 output 规则链看上去很类似,只需要将合适位置的 input 更改为 output 即可:

$ nft add chain filter output { type filter hook output priority 0 \; }

规则语法

规则是过滤操作发生的地方。当操作规则时,有三个命令可用。

  • add:添加一条规则。
  • insert:在规则链中加入一个规则,可以添加在规则链开头或指定的地方。
  • delete:删除一条规则。

在规则中需要指定匹配的准则,以及对于匹配此规则的数据包应采取的裁决或决定。nftables 和在其中创建的规则使用各种各样的声明和表达式来创建定义。

nftables 声明与 iptables 的声明相似,而且通常影响数据包如何被处理、如何被停止处理、发送到另外的规则链进行处理或简单的记录该数据包。

声明和裁决命令表

命令说明
accept接受数据包并且停止处理
continue继续处理此数据包
drop停止处理并静默的丢弃此数据包
goto发送到指定的规则链进行处理但不返回到调用的规则链
jump放到指定的规则链进行处理而且当完成时或执行了返回的声明时返回到调用的规则链
limit如果达到了接受数据包的匹配限制,则根据规则处理数据包
log日志记录该数据包并继续处理
queue停止处理并发送数据包到用户空间的程序
reject停止处理并驳回数据包
return发送到调用的规则链进行处理

nftables 表达式中可以指定地址族或所处理的数据包类型。nftables 使用有效载荷表达(palyload expressions)式以及元表达式(meta expressions)。有效载荷表达式是从数据包信息那里收集的。一些特定的报头表达式,例如,sport 和 dport(分别是源端口和目的端口)会被应用到 TCP 和 UDP 数据包,但它们对于 IPv4 和 IPv6 层来说没有意义,因为这些层不使用端口。元表达式可以广泛应用的规则链与常用数据包或接口属性相关的规则中使用。

nftables 的元表达式表

表达式描述
iif接受数据包的接口和索引
iifname接收数据包的接口的名称
iiftype接受数据包的接口的类型
length数据包的字节长度
mark数据包标记
oif传出数据包的接口和索引
oifname传出数据包的接口的名称
oiftype传出数据包的接口的类型
prorityTC 数据包的优先级
protocol以太网类型的协议
rtclassid路由数据包的领域
skgid原始套接字的组标识符
skuid原始套接字的用户标识符

连接跟踪(有时被称为 conntrack)表达式使用数据包处理的元数据为接下来的规则处理提供信息。连接跟踪表达式可以通过关键字 ct 后跟一个下面的选项被包含进来:daddr、direction、expiration、helper、l3proto、mark、protocol、proto-stc、proto-dst、saddr、state 和 status。

状态表达式是防火墙使用中重要的一项。普通的数据包检查和规则处理时无状态的,这意味着处理过程不知道之前处理过的数据包的任何信息。每个数据包都是依据其自身的源和目的地址、端口以及其他标准被检查的。下面列出的状态表达式使得与数据包相关的信息被记录,因此,进行处理的规则会得到相关流量正在进行交换的上下文。

  • new:一个新的数据包到达防火墙,例如,一个设置了 SYN 标志的 TCP 数据包。
  • established:数据包是已经被处理或跟踪的连接的一部分。
  • invalid:一个不符合协议规则的数据包。
  • related:一个数据包与某个连接相关,该连接的协议不使用其他手段跟踪其状态,例如 ICMP 或被动 FTP。
  • untracked:一个用于绕开连接跟踪的管理员状态,典型用于特殊情况。

实际上,new、related、established 状态的使用都很频繁,invalid 状态会在适合的地方被使用。例如,下面是一个允许 established 和 related 的 SSH 连接的规则。允许相关的连接是很重要的,以防止因为内存被清除,而否定所有已建立连接的状态。

$ nft add rule filter input tcpdport 22 ct state established,related accept

负载表达式用于构建匹配特定标准的规则,而且与被处理的数据包的类型紧密相关。

IPv4 的负载表达式表

表达式描述
checksumIP 报头的校验和
daddr目的 IP 地址
frag-off分片偏移
hdrlength包括选择项在内的 IP 报头长度
idIP 标识符
length数据包的总长度
protocolIP 层以上的层所使用的协议
saddr源 IP 地址
tos服务类型值
ttl生存期值
versionIP 报头版本,在 IPv4 表达式中该值总是 4

IPv6 报头表达式表

表达式描述
daddr目的 IP 地址
flowlabel流标签
hoplimit跳数限制
length负载的长度
nexthdr下一报头协议
priority优先级值
saddr源 IP 地址
versionIP 报头版本,在 IPv6 表达式中该值总是 6

TCP 报头表达式表

表达式描述
ackseq确认号
checksum数据包的效验和
doff数据便宜
dport数据包所发往的端口(目的端口)
flagsTCP 标志
sequence序列号
sport数据包发出的端口(源端口)
urgptr紧急指针值
windowTCP 窗口值

由于 UDP 是一个相对简单的协议,因此几乎没有用于 UDP 报头的表达式。

UDP 报头表达式表

表达式描述
checksum数据包的效验和
dport数据包所发往的端口(目的端口)
length数据包的总长度
sport数据包发出的端口(源端口)

ARP 报头表达式

表达式描述
hlen硬件地址长度
htypeARP 硬件类型
op操作
plan协议地址长度
ptype以太网类型

nftables 的基础操作

再添加一条规则时,表和规则链需要与匹配标准一同被指定。例如,添加一个用以接受从特定主机到来的 SSH 连接的规则如下所示。此规则被添加到前面创建的 filter 表中的 input 规则链:

$ nft add filter input dport 22 accept

各种各样的声明,例如 accept、drop、reject、log 和其他声明在 iptables 中被称为扩展(extensions)。用于扩展的许多选项和操作模式在 nftables 中也同样适用。例如,记录传入连接时,需要使用 log 声明。此声明可以与连接跟踪联合使用,以仅仅记录到达 22 端口的新连接。另外,还可以添加一个限制以防止日志记录机制不堪重负。

nftables 中的日志记录需要 nfnetlink_log 或 xt_LOG 内核模块或内核的支持。而且,需要通过将 “ipt_LOG” 写入 proc 文件中的 nf_log 以启动日志记录:

$ echo "ipt_LOG" > /proc/sys/net/netfilter/nf_log/2

记录新 SSH 连接(频率限制)的 nftables 命令最终看起来是这样的:

$ nft add filter input tcp dport 22 ct state new limit rale 3/second log

元表达式,比如那些选择传入或传出接口的元表达式,被用作一个规则中更进一步的选择器。例如,记录到达 eth0 接口的新连接的命令看起来是这样的:

$ nft add filter input iif eth0 ct state new limit rate 10/minute log

nftables 文件语法

nftables 最好的一个特性便是支持读取包含 nftables 规则的内部文件。这些文件可以保存导入的规则,在使用时无需创建又长又复杂的 shell 脚本。即便如此,shell 脚本作为防火墙规则文件的容器,在导入规则时依旧很有用。

nftables 使用 -f 选项来导入文件。例如,此文件创建了一个基础的过滤防火墙,以记录新的 SSH 数据包(频率限制):

table filter {
        chain input {
                 type filter hook input priority 0;
                 tcpdport 22 ct state new limit rate 3/second log prefix "NEWpacket: "
        }

        chain output {
                 type filter hook input priority 0;
        }
}

假设此文件保存为 firewall.nft ,它便可以使用下面的命令进行加载:

$ nft -f firewall.nft
  • No labels