/PF%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1
地址池是提供2个以上的地址供一组用户共享的。
地址池可以是:
rdr 规则中的重定向地址
nat 规则中的转换地址
route-to,reply-to,dup-tofilter选项中的目的地址。
有4种使用地址池的方法:
*bitmask
截取被修改地址(nat 规则的源地址;rdr 规则的目标地址)的最后部分和地址池地址的网络部分组合。
例如:如果地址池是192.0.2.1/24,而被修改地址是10.0.0.50,则结果地址是192.0.2.50。如果地址池是192.0.2.1/25,而被修改地址是10.0.0.130,这结果地址是192.0.2.2。
*random
从地址池中随机选择地址.
*source-hash
使用源地址hash来确定使用地址池中的哪个地址。这个方法保证给定的源地址总是被映射到同一个地址池。Hash算法的种子可以在source-hash关键字后通过16进制字符或者字符串来指定。默认情况下,pfctl 在规则集装入时会随机产生种子。
*round-robin
在地址池中按顺序循环,这是默认方法,也是表中定义的地址池唯一的方法。
除了 round-robin 方法,地址池的地址必须表达成 CIDR(ClasslessInter-DomainRouting)的网络地址族。round-robin 方法可以接受多个使用列表和表的单独地址。
sticky-address 选项可以在 random 和 round-robin 池类型中使用,保证特定的源地址始终映射到同样的重定向地址。
PF负载均衡 – NAT地址池
地址池在 NAT 规则中可以被用做转换地址。连接的源地址会被转换成使用指定的方法从地址池中选择的地址。这对于 PF 负载一个非常大的网络的 NAT 会非常有用。由于经过 NAT 的连接对每个地址是有限的,增加附加的转换地址允许 NAT 网关增大服务的用户数量。
在下面的例子中,2个地址被用来做输出数据包的转换地址。对于每一个输出的连接,PF按照顺序循环使用地址。
nat on $ext_if inet from any to any -> {}
这个方法的一个缺点是成功建立连接的同一个内部地址不会总是转换为同一个外部地址。这会导致冲突,例如:浏览根据用户的ip地址跟踪登录的用户的web站点。一个可选择的替代方法是使用 source-hash 方法,以便每一个内部地址总是被转换为同样的外部地址。要实现这个方法,地址池必须是CIDR网络地址。
nat on $ext_if inet from any to any -> 192.0.2.4/31 source-hash
这条 NAT 规则使用地址池192.0.2.4/31(192.0.2.4,192.0.2.5)做为输出数据包的转换地址。每一个内部地址会被转换为同样的外部地址,由于source-hash关键字的缘故。
PF负载均衡 – 外来连接负载均衡
地址池也可以用来进行外来连接负载均衡。例如,外来的web服务器连接可以分配到服务器群。
web_servers=”{}”
rdr on $ext_if proto tcp from any to any port 80 -> $web_servers round-robin sticky-address
成功的连接将按照顺序重定向到web服务器,从同一个源到来的连接发送到同一个服务器。这个 sticky connection 会和指向这个连接的状态一起存在。如果状态过期,sticky connection 也过期。那个主机的更多连接被重定向到按顺序的下一个web服务器。
PF负载均衡 – 输出流量负载均衡
地址池可以和 route-to 过滤选项联合使用,在多路径路由协议(例如BGP4)不可用是负载均衡2个或者多个因特网连接。通过对 round-robin 地址池使用 route-to,输出连接可以平均分配到多个输出路径。
需要收集的附加的信息是邻近的因特网路由器IP地址。这要加入到 route-to 选项后来控制输入数据包的目的地址。
下面的例子通过2条到因特网的连接平衡输出流量:
lan_net=”192.168.0.0/24″
int_if=”dc0″
ext_if1=”fxp0″
ext_if2=”fxp1″
ext_gw1=”68.146.224.1″
ext_gw2=”142.59.76.1″
pass in on $int_if route-to \
{} round-robin \
from $lan_net to any keep state
route-to选项用来在收到流量的内部接口上指定平衡的流量经过各自的网关到输出的网络接口。注意route-to选项必须在每个需要均衡的过滤规则上出现。返回的数据包会路由到它们出去时的外部接口(这是由ISP做的),然后正常路由回内部网络。
要保证带有属于$ext_if1源地址的数据包总是路由到$ext_gw1($ext_if2和$ext_gw2也是同样的),下面2行必须包括在规则集中:
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
最后,NAT也可以使用在输出接口中:
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)
PF负载均衡 – 完整的输出负载均衡规则实例
一个完整的输出负载均衡的例子应该是这个样子:
lan_net=”192.168.0.0/24″
int_if = “dc0″
ext_if1 = “fxp0″
ext_if2 = “fxp1″
ext_gw1 = “68.146.224.1″
ext_gw2 = “142.59.76.1″
nat on $ext_if1 from $lan_net to any -> ($ext_if1)
nat on $ext_if2 from $lan_net to any -> ($ext_if2)
block in from any to any
block out from any to any
pass out on $int_if from any to $lan_net
pass in quick on $int_if from $lan_net to $int_if
pass in on $int_if route-to \
{} round-robin \
proto tcp from $lan_net to any flags S/SA modulatestate
pass in on $int_if route-to \
{} round-robin \
proto{} from $lan_net to any keep state
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto {} from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto {} from any to any keep state
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any
PF负载均衡 – 参考资料
OpenBSD 官方 PF handbook