[OpenBSD]

[上一小节: PF:运行选项] [总目录] [下一小节: 数据包的排队和优先]

PF: Anchor


目录


介绍

除了主规则集, PF还可以评估子规则集。因为子规则集可以在运行时通过pfctl(8)处理。它们提供了一个动态修改正在应用的规则集的简便方法。一个表格用来保存一组动态的地址列表, 一个子规则被用来保存一组动态的规则。一个子规则集通过一个Anchor附加到主规则集里。

Anchors可以被嵌套, 这种嵌套允许将子规则集链接到一起。Anchor规则将在Anchor被载入时被评估。例如, 位于主规则里的Anchor规则将产生Anchor附加点, 主规则集是这些anchors附加点的父系规则, 而且从带有 load anchor 指令的文件载入的Anchor规则将产生Anchor点, 这些anchor规则将那个Anchor当作其parent。

Anchor

一个Anchor是一个规则、表格以及其它已被命名的anchors的集合, 当PF遇到主规则集里面的一条anchor规则时, 它将评估包含在Anchor点内的规则, 就像评估主规则里的规则一样;(执行完anchor点内的规则)PF将继续处理主规则, 除非数据包匹配一条使用quick选项的过滤规则, 或者Anchor里的一条转换规则包含了最终的匹配并将放弃评估Anchor和主规则集两者里的所有规则。

例如:

ext_if = "fxp0"

block on $ext_if all
pass  out on $ext_if all keep state
anchor goodguys

这个规则集在fxp0上设定了一个双向默认拒绝策略, 然后将完全放行外出的通讯并保持状态, 然后创建一个名为goodguys的Anchor规则。anchor可以通过三种方法嵌入到规则里:

load规则命令pfctl从一个文本文件中读取规则并将这个特定的anchor插入到规则里, load规则必须在anchor规则之后。例如:

anchor goodguys
load anchor goodguys from "/etc/anchor-goodguys-ssh"

用pfctl为一个Anchor增加规则, 可以使用如下类型的命令:

# 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

要直接在主规则里载入规则(译者: 感觉这里直接说放入一个inline anchor更贴切一些,否则就是我没有理解。), 可以将anchor规则括在一对大括号以内:

anchor "goodguys" { 
   pass in proto tcp from 192.168.2.3 to port 22
}

inline anchors(直接插入的anchors)也可以包含更多的anchors。

 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
因为是直接插入的inline anchors, 所以(里面的)anchor有无名字就无所谓了。注意上例中的被嵌套的anchor怎么没有名字, 也请注意marco $allow 产生在这个anchor外(主规则集中),它怎么能在这个anchor里使用。

在一个anchor内你可以使用与主规则集相同的语法和选项来载入规则。不过, 除非你使用inline anchor(译者:严重怀疑原文这里缺了这个逗号) 否则, 所有在anchor内使用的 macro 必须在其内部被定义; 因为父系(上一集)规则集里定义的macro在这个anchor内不可见。

因为anchors可以被嵌套, 所以有可能指定PF评估一个特定anchor内的所有子anchor:

anchor "spam/*"

这条语法让PF对附加到anchor spam 上的每个子anchor的每条规则进行评估。所有的子anchor将按照字母顺序被评估, 但不递归遗传, 子anchor永远只在定义它们的Anchor内被评估。

每个anchor和主规则集一样, 与其它的规则集分别存在。对一个规则集进行的操作, 例如清除规则, 一点也不影响其它的。另外在主规则集里删除一个anchor点并没有删除这个anchor或这个anchor上附件的任何子anchor。 要删除一个anchor必须使用 pfctl(8) 将其所有规则清除, 而且这个anchor中必须没有任何子anchor。

Anchor选项

anchor规则可随意指定接口、协议、源和目标地址、标志等, 和其它规则使用的语法相同。如果这些信息给定后, anchor规则仅处理那些匹配自己的数据包, 例如:

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

anchor ssh 这条规则仅评估那些从接口fxp0进站并去往端口22的TCP数据包。然后被规则添加到anchor上像这样:

# echo "pass in from 192.0.2.10 to any" | pfctl -a ssh -f -

所以, 即便过滤规则没有指定一个接口、协议或端口, 因为anchor规则的定义, 192.0.2.10也将是被允许使用ssh连接的唯一主机。

相同的语法同样可以应用于inline anchors。

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    } }

操控Anchor

可以通过pfctl操控Anchor。pfctl可以在无需重新载入主规则集的情况下在一个anchor内添加或删除规则。

列出名为ssh的anchor的所有规则:

# pfctl -a ssh -s rules

删除同一个anchor的所有规则:

# pfctl -a ssh -F rules

完整的命令清单请参阅 pfctl(8). [上一小节: PF:运行选项] [总目录] [下一小节: 数据包的排队和优先]


[back] www@openbsd.org
$OpenBSD: anchors.html, v 1.25 2008/10/31 16:49:34 nick Exp $