--------------------------------------------------------------------------------
目录
介绍
锚
锚选项
处理锚
--------------------------------------------------------------------------------
介绍
除了主规则集, PF还可以评估子规则集。因为子规则集可以在运行时通过pfctl(8)处理。它们提供了一个动态修改运行规则集的简便方法。事实上一个表格用来保存一组动态的地址列表, 一个子规则集用来保存一组动态的过滤规则, nat, rdr, 和 binat 规则。
子规则集通过使用锚附加到主规则集上。 锚规则有四种类型:
anchor name - 评估锚 name 里的所有 过滤 规则
binat-anchor name - 评估锚 name 里的所有 binat 规则
nat-anchor name - 评估锚 name 里的所有 nat 规则
rdr-anchor name - 评估锚 name 里的所有 rdr 规则
锚可以被嵌套, 它考虑到将子规则集链接到一起。锚规则将在载入它们的锚上被评估。例如, 位于主规则里的锚规则将产生锚定点, 将主规则作为它们的父系规则, 而从带有装载锚命令的文件载入的锚规则将产生锚点, 将那个锚作为其父系锚。
锚
一个锚是一个过滤和/或转换规则、表格、其它已被命名的锚的集合, 当PF遇到主规则内的一条锚规则时, 它将评估包含在锚点内的规则, 就像评估主规则里的规则一样;然后将继续处理主规则, 除非数据包匹配一条使用quick选项的过滤规则, 或者锚里的一条转换规则包含了最终的匹配并将放弃评估锚和主规则集两者里的所有规则。
例如:
代码: 全选
ext_if = "fxp0"
block on $ext_if all
pass out on $ext_if all keep state
anchor goodguys
这个规则集在fxp0上设定了一个双向默认拒绝策略, 然后将完全放行外出的通讯并保持状态, 一个名为goodguys的锚规则被创建。宏可以通过三种方法嵌入规则:
使用一个载入规则
使用 pfctl(8)
指定内插在主规则集里的规则
载入规则使pfctl从一个文本文件中读取规则并插入一个指定的锚, 载入规则必须在锚规则之后。例如:
代码: 全选
anchor goodguys
load anchor goodguys from "/etc/anchor-goodguys-ssh"
用pfctl为一个锚增加规则, 可以使用如下类型的命令:
代码: 全选
# echo "pass in proto tcp from 192.0.2.3 to any port 22" | pfctl -a goodguys -f -
规则也可以被保存在一个文本文件中, 然后从这个文本文件载入:
代码: 全选
# cat >> /etc/anchor-goodguys-www
pass in proto tcp from 192.0.2.3 to any port 80
pass in proto tcp from 192.0.2.4 to any port { 80 443 }
# pfctl -a goodguys -f /etc/anchor-goodguys-www
要直接从主规则里载入规则, 可以将锚规则封装在一个大括号内:
代码: 全选
anchor "goodguys" {
pass in proto tcp from 192.168.2.3 to port 22
}
内联锚里也可以包含更多的锚。
代码: 全选
allow = "{ 192.0.2.3 192.0.2.4 }"
anchor "goodguys" { #<----内联锚
anchor { #<---内嵌锚
pass in proto tcp from 192.0.2.3 to port 80
}
pass in proto tcp from $allow to port 22 #<---在内联锚内使用的宏$allow
(译者注:这里最外层的锚inline anchor翻译成内联锚, 内联锚内的嵌套的锚nested anchor翻译成内嵌锚, 子锚)
里面含有内嵌锚的名字变成了可选项。注意上例中的嵌套的锚(内嵌锚)怎么没有名字, 也请注意宏 $allow 产生于锚外(主规则集中)而怎么能使用在锚内。
在一个锚内可以使用相同的语法和选项载入过滤或转换规则, 就像从主规则集里载入它们一样, 然而, 除非你使用的是内联锚, 否则任何在内嵌锚内使用的 宏 必须在内嵌锚内被定义;因为父系规则定义的宏在内嵌锚内不可见。
因为锚可以被嵌套, 所以可以指定评估一个特定锚内的所有子锚:
anchor "spam/*"
这条语法让将每个子锚的每条规则附加到锚 spam 上进行评估。所有的子锚将按照字母顺序被评估, 但不递归遗传, 子锚永远只在定义它们的锚内被评估。
每个锚和主规则集一样, 与其它的规则集分别存在。对一个规则集进行的操作, 例如清除规则, 一点也不影响其它的。另外在主规则集里删除一个锚点并没有删除这个锚或这个锚上附件的任何子锚。 要删除一个锚必须使用 pfctl(8) 将其从所有规则中清除, 而且这个锚中没有任何子锚。
锚选项
锚规则
锚规则可随意指定接口、协议、源/目标地址、标志等, 和过滤规则的语法相同。如果这些信息给定后, 锚规则仅处理那些匹配自己的数据包, 例如:
代码: 全选
ext_if = "fxp0"
block on $ext_if all
pass out on $ext_if all keep state
anchor ssh in on $ext_if proto tcp from any to any port 22
锚ssh里的规则仅评估那些从接口fxp0进入去往端口22的TCP数据包。将规则添加到锚上像这样:
代码: 全选
# echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f -
所以, 即便过滤规则没有指定一个接口、协议或端口, 因为锚规则的定义, 192.0.2.10也将是被允许使用ssh连接的唯一主机。
相同的语法同样可以应用于内联锚。
代码: 全选
allow = "{ 192.0.2.3 192.0.2.4 }"
anchor "goodguys" in proto tcp {
anchor proto tcp to port 80 {
pass from 192.0.2.3
}
anchor proto tcp to port 22 {
pass from $allow
}
}
处理锚
可以通过pfctl处理锚。它能被用来在一个锚内添加或删除规则而无需重新载入主规则集。
列出锚ssh的的所有规则:
代码: 全选
# pfctl -a ssh -s rules
删除锚ssh的所有规则:
代码: 全选
# pfctl -a ssh -F rules
完整的命令清单请参阅 pfctl(8).