免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: minok
打印 上一主题 下一主题

菜鸟100问 [复制链接]

论坛徽章:
0
111 [报告]
发表于 2006-12-09 07:41 |只看该作者

基本配置

PF: 重定向 (端口转发)

------------------------------------------------------------------------------
简介

如果在办公地点应用了NAT,内部网所有的机器都可以访问因特网。
^-^  (参见pf中文手册)
^-^
==============================================================================

论坛徽章:
0
112 [报告]
发表于 2006-12-09 07:48 |只看该作者

基本配置

PF: 规则生成捷径

------------------------------------------------------------------------------
简介

PF提供了许多方法来进行规则集的简化。规则集越简单,就越容易理解和维护。

使用宏

宏是非常有用的,因为它提供了硬编码地址,端口号,接口名称等的可选替代。在一个规则集中,服务器的IP地址改变了?没问题,仅仅更新一下宏,不需要弄乱你花费了大量时间和精力建立的规则集。

通常的惯例是在PF规则集中定义每个网络接口的宏。如果网卡被另一网卡取代,例如,用intel代替3com,可以更新宏,过滤规则集会和以 前功能一样。另一个优点是,如果在多台机器上安装同样的规则集,某些机器会有不同的网卡,使用宏定义网卡可以使的安装的规则集进行最少的修改。
# define macros for each network interface
IntIF = "dc0"
ExtIF = "fxp0"
DmzIF = "fxp1"

另一个惯例是使用宏来定义IP地址和网络,这可以大大减轻在IP地址改变时对规则集的维护。

# define our networks
IntNet = "192.168.0.0/24"
ExtAdd = "24.65.13.4"
DmzNet = "10.0.0.0/24"

如果内部地址扩展了或者改到了一个不同的IP段,可以更新宏为:

IntNet = "{ 192.168.0.0/24, 192.168.1.0/24 }"

当这个规则集重新载入时,任何东西都跟以前一样。

使用列表

这例子使得RFC1918定义的内部地址不会传送到因特网上,如果发生传送的事情,可能导致问题。

例(1)
block in quick on tl0 inet from 127.0.0.0/8 to any
block in quick on tl0 inet from 192.168.0.0/16 to any
block in quick on tl0 inet from 172.16.0.0/12 to any
block in quick on tl0 inet from 10.0.0.0/8 to any
block out quick on tl0 inet from any to 127.0.0.0/8
block out quick on tl0 inet from any to 192.168.0.0/16
block out quick on tl0 inet from any to 172.16.0.0/12
block out quick on tl0 inet from any to 10.0.0.0/8

例(2)
block in quick on tl0 inet from { 127.0.0.0/8, 192.168.0.0/16, \
172.16.0.0/12, 10.0.0.0/8 } to any
block out quick on tl0 inet from any to { 127.0.0.0/8, \
192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }

这个规则集从8行减少到2行。如果联合使用宏,还会变得更好:

例(3)
NoRouteIPs = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, \
10.0.0.0/8 }"
ExtIF = "tl0"
block in quick on $ExtIF from $NoRouteIPs to any
block out quick on $ExtIF from any to $NoRouteIPs

注意虽然宏和列表简化了pf.conf文件,但是实际是这些行会被pfctl(8)扩展成多行,因此,上面的例(2),例(3)实际扩展成例(1): 可以看到,PF扩展仅仅是简化了编写和维护pf.conf文件,实际并不简化pf(4)对于规则的处理过程。

宏不仅仅用来定义地址和端口,它们在PF的规则文件中到处都可以用:

pre = "pass in quick on ep0 inet proto tcp from "
post = "to any port { 80, 6667 } keep state"

# David‘s classroom
$pre 21.14.24.80 $post

# Nick‘s home
$pre 24.2.74.79 $post
$pre 24.2.74.178 $post

扩展后:

pass in quick on ep0 inet proto tcp from 21.14.24.80 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 21.14.24.80 to any \
port = 6667 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.79 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.79 to any \
port = 6667 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.178 to any \
port = 80 keep state
pass in quick on ep0 inet proto tcp from 24.2.74.178 to any \
port = 6667 keep state

PF 语法

PF能够自动插入某些关键字而不必在规则中明确写出,关键字的顺序也是随意的。

减少关键字

要定义全部拒绝的策略,使用下面2条规则:

block in all
block out all

这可以简化为:

block all

如果没有指定方向,PF会认为规则适用于数据包传递的进、出2个方向。

同样的, "from any to any" 和 "all" 子句可以在规则中省略,例如

block in on rl0 all
pass in quick log on rl0 proto tcp from any to any port 22 keep state

可以简化为:

block in on rl0
pass in quick log on rl0 proto tcp to port 22 keep state
第一条规则阻塞rl0上从任意到任意的进入数据包,第二条规则允许rl0上端口22的TCP流量通过。

Return 简化

用于阻塞数据包,回应TCP RST或者ICMP不能到达的规则集可以这么写:

block in all
block return-rst in proto tcp all
block return-icmp in proto udp all
block out all
block return-rst out proto tcp all
block return-icmp out proto udp all

可以简化为::

block return

当PF看到return关键字,PF可以智能回复合适应答,或者完全不回复,取决于要阻塞的数据包使用的协议。

关键字顺序

在大多数情况下,关键字的顺序是非常灵活的。例如,规则可以这么写:

pass in log quick on rl0 proto tcp to port 22 \
flags S/SA keep state queue ssh label ssh
也可以这么写:
pass in quick log on rl0 proto tcp to port 22 \
queue ssh keep state label ssh flags S/SA

其他类似的顺序也能够正常工作。

论坛徽章:
0
113 [报告]
发表于 2006-12-09 07:55 |只看该作者

高级配置

PF: 运行选项

------------------------------------------------------------------------------

使用set指定运行选项是控制pf的选择。

set block-policy
设定过滤规则中block动作的默认行为。
+ drop - 数据包悄然丢弃.
+ return - TCP RST 数据包返回给遭阻塞的TCP数据包,ICMP不能到达数据包返回给其它。
注意单独的过滤规则可以重写默认的响应。

set debug
设定 pf的调试级别。
+ none - 不显示任何调试信息。
+ urgent - 为严重错误产生调试信息,这是默认选择。
+ misc - 为多种错误产生调试信息。(例如,收到标准化/整形的数据包的状态,和产生失败的状态)。.
+ loud - 为普通条件产生调试信息(例如,收到被动操作系统检测信息状态)。

set fingerprints file
设定应该装入操作系统特征文件来识别操作系统,默认是 /etc/pf.os.

set limit
frags - 在内存池中进行数据包重组的最大数目。默认是5000。
src-nodes - 在内存池中用于追踪源地址(由stick-address 和 source-track选项产生)的最大数目,默认是10000。
states - 在内存池中用于状态表(过滤规则中的keep state)的最大数目,默认是10000。

set loginterface int
设定PF接口卡要统计(进/出流量,放行/阻塞)数据包的数目。统计数目一次只能用于一张卡。注意 match, bad-offset, 等计数器和状态表计数器不管 loginterface是否设置都会被记录。

set optimization
为以下的网络环境优化PF:
+ normal - 适用于绝大多数网络,这是默认项。
+ high-latency - 高延时网络,例如卫星连接。
+ aggressive - 自状态表中主动终止连接。大大减少繁忙防火墙的内存需求,但要冒空闲连接时被过早断开的风险。
+ conservative - 特别保守的设置。避免在内存需求过大时断开空闲连接,会稍微增加CPU的使用率。

set state-policy
设定PF在状态保持时的行为。这种行为可以被单条规则所改变。见状态保持章节。
+ if-bound - 状态绑定到产生它们的接口。如果流量匹配状态表的条目,但不是由条目中记录的接口通过,这个匹配会失败。数据包要么匹配一条过滤规则,或者被丢弃/拒绝。
+ group-bound - 行为基本和if-bound相同,除了数据包允许由同一组接口通过,例如所有的ppp接口等。
+ floating - 状态可以匹配任何接口上的流量。只要数据包匹配状态表条目,不管是否匹配它通过的接口,都会放行。这是默认的规则。

set timeout
interval - 丢弃过期的状态和数据包碎片的秒数。
frag - 不能重组的碎片过期的秒数。

例如:

set timeout interval 10
set timeout frag 30
set limit { frags 5000, states 2500 }
set optimization high-latency
set block-policy return
set loginterface dc0
set fingerprints /etc/pf.os.test
set state-policy if-bound

论坛徽章:
0
114 [报告]
发表于 2006-12-09 08:04 |只看该作者

高级配置

PF: 流量整形 (数据包标准化)

------------------------------------------------------------------------------
简介

流量整形是将数据包标准化。避免出现非法数据包。流量整形指引的简单形式是:

scrub in all

这会对所有接口上到来的数据包进行流量整形。

一个不在接口上进行流量整形的原因是要透过PF使用NFS。一些非openbsd发送(和等待)的数据包,对设置不分片位的数据包进行分片。这会被流量整形拒绝。这个问题可以通过设置no-df选项解决。另一个原因是某些多用户的游戏在进行流量整形通过PF时存在连接问题。除了这些案例,强烈推荐对所有的数据包进行流量整形。

流量整形可以选择特定的数据包进行整形, 而对没指定的数据包不起作用。

选项

流量整形有下面的选项:

no-df
清除不分片位的IP数据包头。尤其是对于NFS。某些操作系统产生带有不分片位和用0填写IP包头中分类域,推荐使用no-df和random-id 联合使用解决。
random-id
仅适用于选择的数据包重组后,不进行分片的输入数据包。
min-ttl num
增加IP包头中的最小存活时间(TTL)。
max-mss num
增加在TCP数据包头中最大分段值(MSS)。
fragment reassemble
在传递数据包到过滤引擎前缓冲收到的数据包碎片,重组它们成完整的数据包。优点是过滤规则仅处理完整的数据包,忽略碎片。缺点是需要内存缓冲数据包碎片。这是没有设置分片选项时的默认行为。这也是能和NAT一起工作的唯一分片选项。
fragment crop
重复的碎片被丢弃,重叠的被裁剪。与碎片重组不同,碎片不会被缓冲,而是一到达就直接传递。
fragment drop-ovl
跟 fragment crop 相似,所有重复和重叠的碎片和其他更多的通信碎片会被丢弃。
reassemble tcp
TCP连接状态标准化。当使用了 scrub reassemble tcp时,方向(进/出)不用说明,会执行下面的标准化过程:
+ 连接双方都不允许减少它们的IP TTL值。这样做是为了防止攻击者影响防火墙的连接状态。
+ 用随机数字调整TCP数据包头中的 RFC1323 时间戳。这可以阻止窃听者推断主机在线的时间和猜测NAT网关后面有多少主机。

实例:

scrub in on fxp0 all fragment reassemble min-ttl 15 max-mss 1400
scrub in on fxp0 all no-df
scrub on fxp0 all reassemble tcp

论坛徽章:
0
115 [报告]
发表于 2006-12-09 08:12 |只看该作者

高级配置

PF: 锚定和命名规则集

------------------------------------------------------------------------------
简介

除了主要的规则集,PF还可以载入子规则集。由于子规则集可以使用pfctl(8)操作,这提供了一个动态修改活动规则集的方法。正如表被用来保存动态地址列表,子规则用来保存动态过滤设定,nat,rdr和binat规则。

子规则集是通过使用锚定,附加到主规则集。有4种类型的锚定规则:

* anchor name - 检测锚定名称中的所有规则
* binat-anchor name - 检测锚定名称中的binat规则。
* nat-anchor name -检测锚定名称中的nat规则。
* rdr-anchor name -检测锚定名称中的rdr规则。

只有主规则集可以包含锚定规则。

命名规则集

命名规则集是被配置了名称的一组过滤和/或转换规则。一个锚定点可以包含多个的类似规则集。当PF在主规则集中碰到锚定规则,它会按字母顺序,检测附加到锚定点的所有规则集。处理过程会在主规则集中继续,直到匹配了带quick的规则,或者在锚定中匹配了认为是结束的转换规则,锚定规则和主规则才不再继续执行。

例如:

ext_if = "fxp0"

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

这条规则集设定了fxp0接口上默认拒绝进出的所有流量的策略。然后通过的流量保持状态,后面是一个锚定规则集名称是goodguys。锚定可以通过2个方法替换为规则:
* 使用可载入的规则
* 使用 pfctl

可载入的规则使pfctl通过读入一个文本文件,代替指定的锚定和命名规则集。例如:

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

当主规则集载入时,/etc/anchor-goodguys-ssh 该文件列出的规则中命名为ssh的规则集会被载入到名称为goodguys的锚定点。

要使用pfctl为锚定点增加规则,可以使用下面这样的命令:

# echo "pass in proto tcp from 192.0.2.3 to any port 22" \
| pfctl -a goodguys:ssh -f -

这增加了一条防线规则到goodguys锚定点并命名为ssh。PF在主规则中到达goodguys锚定点时,会检测这条规则(包括其他加入的过滤规则)。

规则也可以通过文本文件载入和保存:

# 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:www -f /etc/anchor-goodguys-www

这从/etc/anchor-goodguys-www 文件载入规则到goodguys锚定点命名为www。

过滤和转换规则也可以(使用同样的语法和选项)载入命名规则集,类似主规则集载入普通的规则。一个警告:命名规则集中使用的宏必须同时被定义,在主规则集中定义的宏对命名规则集不可见。

每一个命名规则集,和主规则集一样,和其他规则集独立存在的。对于某个规则集的操作,比如删除一个规则集,不会影响其他的规则集。另外,在主规则集中可随意移动一个锚定点的位置,而不受影响。

锚定选项

锚定规则可以随意指定接口,协议,源和目的地址,标记等等,使用的是和过滤规则同样的语法。如果这些信息存在,仅处理匹配锚定规则定义的数据包。例如:

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:allowed -f -

因此,尽管过滤规则中没有指定接口,协议,端口,由于锚定规则的定义,主机192.0.2.10只允许使用ssh连接。

操作命名规则集

命名规则集的操作是通过pfctl实现的。可以不用重新载入主规则集就在规则集中删除和增加规则。

要列出附属于ssh锚定规则集中的规则,可以使用:

# pfctl -a ssh:allowed -s rules

要删除这个规则集中所有过滤规则:

# pfctl -a ssh:allowed -F rules

如果规则集名称省略,这个动作应用于锚定里的所有规则。

命令的详细列表,可以查看pfctl(8)。

论坛徽章:
0
116 [报告]
发表于 2006-12-09 08:33 |只看该作者

高级配置

PF: 队列和优先级

------------------------------------------------------------------------------
队列

使用队列是为了按顺序保存一些等待处理的数据。在计算机网络中,当数据包由一台主机发出后,他们将进入一个等待队列,由操作系统决定哪个队列或者某个队列中的哪些包将被处理。数据包的处理顺序将影响网络性能。例如,一个用户打开了两个网络程序:SSH和FTP,由于SSH的时效性要求,在理想情况下SSH数据包将先于FTP数据包被处理。通过定义队列策略,网络带宽可以公平地分配。

注意队列只是对流出外部接口的数据包起作用。当数据包流入内部接口时再做队列将是非常迟的,因为耗用了带宽。唯一的解决办法是在相邻的路由器启用队列,或者主机被当作是个路由器,在数据包流出的接口上启用队列。

日程

日程用来规定执行哪条队列和顺序。默认情况下,OpenBSD使用先进先出(FIFO)队列。类似于排队上车,先到有位座,后到的只能等待。如果队列满了,新到的包将被丢弃,这就是所谓的“弃尾”。

OpenBSD支持另外两种日程:

* 基于类的队列
* 优先级队列

基于类的队列

基于类的队列(CBQ)是一种排序算法,它将网络连接带宽在很多队列和类中分摊,每个队列都拥有基于源、目的地址,端口号,协议等信息分配的网络流量。一个队列可以被随意配置带宽(借用它父队列带宽),前提是父队列没有占用该带宽。队列也有优先级,例如SSH和FTP,SSH数据包将优先被处理。

CBQ队列以分等级的方式部署,最高一级是根队列,用来定义全部带宽。子队列建立在根队列之下,每一个子队列可以分配根队列带宽。例如,定义如下队列:
Root Queue (2Mbps)

Queue A (1Mbps)
Queue B (500Kbps)
Queue C (500Kbps)

这里总带宽被设置为2Mbps,然后由子队列分割。

在子队列中仍然可以定义下一级策略。用来在不同用户中平等地分配带宽,同时对他们的流量进行分类,以便使某个协议不会抢占其他协议的带宽。具体队列结构定义如下:
Root Queue (2Mbps)

UserA (1Mbps)

ssh (50Kbps)
bulk (950Kbps)

UserB (1Mbps)

audio (250Kbps)
bulk (750Kbps)

http (100Kbps)
other (650Kbps)

注意各个队列的带宽之和不能超过自身父类队列的带宽。

当父类队列的一个子队列没用占用完分配给它的带宽时,该父类队列中的另一个子队列可以占用这部分带宽。
看下列配置:

Root Queue (2Mbps)

UserA (1Mbps)

ssh (100Kbps)
ftp (900Kbps, borrow)

UserB (1Mbps)

比如ssh队列没用完全占用100Kbps,而ftp队列的流量超过900Kbps时,ftp子队列将占用UserA父队列中剩余的带宽。使ftp子队列得到更多的带宽。随着ssh子队列流量的增加,被占用的这些带宽将被返还。

CBQ为每个队列分配一个优先级。负荷重的情况下,高优先级的队列早于低优先级的队列被处理,同样情况应用在同父类的子队列。同优先级的队列之间通过抢占方式轮流执行。例如:

Root Queue (2Mbps)

UserA (1Mbps, priority 1)

ssh (100Kbps, priority 5)
ftp (900Kbps, priority 3)

UserB (1Mbps, priority 1)

CBQ将以轮流抢占模式处理UserA和UserB队列,任何一个队列不能优先于另一个被处理。当UserA队列执行的时候,CBQ同时会处理它的子队列,这时,如果网络拥塞,ssh子队列会被优先处理,因为它的优先级高于ftp子队列。注意为什么ssh和ftp子队列不与UserA和UserB队列比较优先级,因为他们不在一个层上。

优先级队列

优先级队列(PRIQ)为一个网络接口上的多个队列逐一分配唯一的优先级。拥有高优先级的队列总是在低优先级队列前被处理。

不可以在一个队列中定义子队列。根队列用来定义全部带宽,其他队列定义在根队列之后。请看如下实例:

Root Queue (2Mbps)

Queue A (priority 1)
Queue B (priority 2)
Queue C (priority 3)

上面定义了一个有2Mbps带宽的根队列和3个子队列。最高优先级的队列被先处理,处理完后,PRIQ再处理下一优先级的队列。在一个队列中,各个包是按照先进先出原则进行处理。

需要注意的是当使用PRIQ时必须非常谨慎地进行设计,因为PRIQ的工作机制是先高后低,如果一个高优先级的

队列收到的数据包是持续的流,那么它将延时处理低优先级的队列,更有甚者导致丢包。

随机早期检测

随机早期检测 (RED)是一种避免网络拥塞的算法,它通过确认队列没有超长来避免网络拥塞。当丢掉一些包时, RED随机选择从哪些连接丢包,占用大带宽的连接被丢包的几率高。

RED的用处非常大,因为它可以避免一种被称为全体同步的状态,也可以调整突发流量。全体同步指多个连接的数据包在同一时间被丢弃导致吞吐量全部消失。例如,如果承载10个FTP连接流量的一台路由器出现拥塞,大部分包被丢弃,总的流量将迅速下降,这并不是最好的处理方法,因为所有的FTP连接都降低了流量,换句话说,这个网络将不会再次发挥最大潜能。RED通过只在随机挑选的连接上丢包来避免上述情况。占用大带宽的连接被丢包的几率高,这样,占用大带宽的连接将受到节制,避免了拥塞,同时总流量迅速降低的现象也不会出现。另外,RED可以处理突发流量,因为它在队列装满之前就开始丢弃数据包,当突发流量到来时,队列中有足够的空间保存新发来的数据包。

RED只能被用在传输协议有能力反馈拥塞指示的情况。在大多数情况下,RED被用来处理TCP数据流而不是DUP或ICMP数据流。

外部拥塞告知

外部拥塞告知(ECN)与RED协作来发现两台主机网络通讯路径上的任何拥塞现象。原理是使RED在头包中设置一个标志位并返回而不是丢弃该包。假设发送端主机支持ECN,它将读到这个标志位信息并减少发出网络流量。

更多关于ECN的信息请参考RFC 3168

配置队列

交互队列(ALTQ)支持CBQ、PRIQ,也支持RED和ECN。

ALTQ队列定义在pf.conf中,有两种指令模式:

* altq on - 在某个接口上开启队列,定义使用哪些日程,建立根队列
* queue - 定义子队列的属性

altq的语法为:

altq on interface scheduler bandwidth bw qlimit qlim \
tbrsize size queue { queue_list }

* interface - 开启队列的网络接口。
* scheduler - 使用的队列日程。可能的取值是cbq和priq。某个接口在某个时间只能启动1个日程。
* bw - 日程所能用到的所有带宽。可以使用后缀b,Kb,Mb和Gb表示,可以是具体的数值也可以是当前接口带宽的百分比。
* qlim - 队列保存数据包的最大数量。该值是可选的,默认50。
* size - 承载容量的大小,单位bytes。如果没有指定,将基于接口带宽自动设置。
* queue_list - 在根队列下建立的一个子队列列表。

实例:

altq on fxp0 cbq bandwidth 2Mb queue { std, ssh, ftp }

这条策略在接口fxp0启用CBQ,总带宽设置为2Mbps,定义了3个子队列:std,ssh和ftp。

队列指令的语法是:

queue name [on interface] bandwidth bw [priority pri] [qlimit qlim] \
scheduler ( sched_options ) { queue_list }

* name - 队列的名称,必须与altq中定义的队列列表中的某个队列名称一致。对于cbq,还可以与以前定义的队列列表中的某个名称一致。长度不能超过15个字符。
* interface - 队列所生效的网络接口,是可选项,如果没指定,将在所有接口生效。
* bw - 队列可以使用的总带宽。可以是具体数值加上后缀b,Kb,Mb和Gb来表示,也可以是总带宽的百分比。该参数只有在使用cbq日程时可用。
* pri - 队列的优先级。对于cbq,优先级的范围是0~7,对于priq,范围是0~15。0是最低的优先级,如果没定义,默认优先级为1。
* qlim - 队列可以保存的最大包数,默认50。
* scheduler - 日程,cbq或者priq。必须和根队列一致。
* sched_options - 控制日程行为的更多选项:
+ default - 定义默认队列,当包不匹配其他队列时的默认值。
+ red - 在当前队列启用RED。
+ rio - 对进/出启用RED。在这种状态下,RED会维护多个平均队列长度和平均门限值,每个IP服务质量级别对应一个。
+ ecn - 在当前队列启用ECN。
+ borrow - 队列可以向父类借用带宽值,只被用于cbq日程模式。
* queue_list - 在当前队列下建立的一系列子队列。只有在cbq日程模式下有效。

继续上述实例:

queue std bandwidth 50% cbq(default)
queue ssh { ssh_login, ssh_bulk }
queue ssh_login priority 4 cbq(ecn)
queue ssh_bulk cbq(ecn)
queue ftp bandwidth 500Kb priority 3 cbq(borrow red)

这里将设置前面已经定义的队列。Std队列分配了根队列的50%带宽,也就是1Mbps,并被设置为默认队列。Ssh队列定义了两个子队列, ssh_login和ssh_bulk。前者ssh_login高于后者ssh_bulk的优先级,并且都开启ECN。ftp队列分配了500Kbps带宽,拥有第3优先级,当总带宽富余时它可以借用,同时也开启了RED。

为队列分配数据流

通过在PF过滤策略中增加queue关键字为队列分配流量。例如,假设某个策略集包含下面一条策略:

pass out on fxp0 from any to any port 22

上述的数据流可以通过queue关键字赋予一个特定的队列:

pass out on fxp0 from any to any port 22 queue ssh

当queue关键字应用到block时,任何TCP RST或者ICMP Unreachable数据包将被分配到特定队列。

注意队列除了可以在altq语句生效外,还可以在接口上生效:

altq on fxp0 cbq bandwidth 2Mb queue { std, ftp }
queue std cbq(default)
queue ftp bandwidth 1.5Mb

pass in on dc0 from any to any port 21 queue ftp

fxp0接口上指定了队列,但是这个队列却可以在dc0上生效。如果数据包匹配了fxp0接口外的那条pass策略,它们将被应用到ftp队列。这种用法在路由器上用处很广。
一般情况下queue关键字后面只有一个队列,如果有另外一个,这个队列将被用处理低延时的包和TCP ACK的包

,这种包没有有效数据载荷。例如,当使用SSH时,SSH的登录会话将设置为低延时性,然而SCP和SFTP会话则不会。PF可以通过这些信息 对属于登录会话的数据包取出并重新排列,这对于赋予登录会话的数据包高优先级非常有用。

pass out on fxp0 from any to any port 22 queue(ssh_bulk, ssh_login)

这条策略将属于SSH登录连接的数据包分配给ssh_logind队列,属于SCP和SFTP连接的数据包分配给ssh_bulk队列。由于前者拥有比后者高的优先级,所以登录连接的数据包被优先处理。

在非对称连接情况下给TCP ACK包分配一个高优先级的队列将是很有用的,比如,ADSL就是一种非对称连接,因为它的上行和下行带宽不一致。如果上行通道已满,而恰在这时开始了下载动作,下载过程的启动需要客户端返回TCP ACK包,但此时该包由于上行阻塞不能及时到达下载服务器,下载过程将会进入等待状态。试验证明,为了取得好的效果,上行队列的带宽最好设置比实际带宽小一些。例如,一个ADSL线路最大上行带宽640Kbps,那么设置根队列600Kbps的带宽效果会很好。

使用keep state的队列策略:

pass in on fxp0 proto tcp from any to any port 22 flags S/SA \
keep state queue ssh

PF将在状态表中记录ssh队列,当数据从fxp0接口流出时,如果符合表中的记录,它将被放入ssh队列。尽管queue关键字影响流出的数据包,但上述队列不会对流入的数据包起作用。

实例 #1: 小型家庭网络

充当一个家庭网的网关,提供包过滤和NAT服务,家庭网中有3个客户端,因特网连接是通过ADSL实现,并有2Mbps下行和640Kbps上行的带宽。

^-^  (参见pf中文手册)
^-^

实例 #2: 公司网络

作为公司网络的防火墙,公司内部在DMZ区运行了WWW服务器,用户通过FTP上传他们的网站。IT部门有自己的子网,老板的电脑主要用来收发电子邮件和网页冲浪。防火墙通过1.5Mbps双向带宽的T1电路连接因特网,其他网段均使用快速以太网(100Mbps)。

^-^  (参见pf中文手册)
^-^
==============================================================================

论坛徽章:
0
117 [报告]
发表于 2006-12-09 08:40 |只看该作者

高级配置

PF: 地址池和负载均衡

------------------------------------------------------------------------------
简介

地址池是提供2个以上的地址供一组用户共享的。地址池可以是rdr规则中的重定向地址;可以是nat规则中的转换地址;也可以是route-to, reply-to, 和 dup-to filter选项中的目的地址。

^-^  (参见pf中文手册)
^-^
==============================================================================

论坛徽章:
0
118 [报告]
发表于 2006-12-09 08:48 |只看该作者

高级配置

PF: 数据包标记

------------------------------------------------------------------------------
简介
数据包标记是给数据包打内部标记的方法,以后可以在过滤和转换规则中使用。使用标记,有可能做这样的事情,比如在接口间产生信任关系,或者确定数据包是否经过了转换规则处理。也可能从基于规则的过滤中移出,开始执行基于策略的过滤。

给数据包打标记

要给数据包打标记,使用tag 关键字:

pass in on $int_if all tag INTERNAL_NET keep state

标记 INTERNAL_NET 会增加到任何匹配上述规则的数据包中。
注意keep state (或者 modulate state/synproxy state) 使用在标记数据包通过的规则中。

标记也可以通过宏来打,比如:

name = "INTERNAL_NET"
pass in on $int_if all tag $name keep state

有一组预先定义的宏也可以被使用。

* $if - 接口
* $srcaddr - 源 IP 地址
* $dstaddr - 目的 IP 地址
* $srcport - 源端口
* $dstport - 目的端口
* $proto - 协议
* $nr - 规则号

这些宏在规则集装入时扩展,而不是运行时。

标记遵循以下规则:

* 标记是粘性的。一旦一个标记被匹配的规则打到一个数据包,就不能被删除。但它可以被不同的标记替换。
* 由于标记的粘性,打了标记的数据包会一直保持,即使所有的规则都没有使用这个标记。
* 一个数据包一次最多只能打一个标记。
* 标记是内部标识符,标记不会被送到网上。

看看下面的例子:

(1) pass in on $int_if tag INT_NET keep state
(2) pass in quick on $int_if proto tcp to port 80 tag \
INT_NET_HTTP keep state
(3) pass in quick on $int_if from 192.168.1.5 keep state

* 按照规则1,$int_if 接口上收到的数据包会打上INT_NET 标记。
* $int_if 接口上收到的目标端口80的数据包根据规则1首先打上INT_NET 标记,然后根据规则2,被INT_NET_HTTP 标记替代。
* 根据规则3,$int_if 接口上收到的来自192.168.1.5的数据包,由于这是最终匹配规则,因此如果它们的目标端口是80,则标记是INT_NET_HTTP ,否则标记是INT_NET 。
除了过滤规则外, nat, rdr, binat转换规则也可以用tag关键字使用标记。

检查数据包标记

要检查先前已经打的标记,可以使用tagged关键字:

pass out on $ext_if tagged INT_NET keep state

为$ext_if输出的数据包打上INT_NET标记。反转匹配也可以使用!操作:

pass out on $ext_if tagged ! WIFI_NET keep state

过滤策略

定义的策略设定规则,说明哪种流量放行,哪种流量阻塞。如源/目的IP地址,协议等等, 数据包被分配到不同的策略。例如,检查下面的防火墙策略:

* 自内部LAN到DMZ的流量是允许的 (LAN_DMZ)。
* 自因特网到DMZ的服务器流量是允许的。 (INET_DMZ)
* 自因特网被重定向到spamd(8)是允许的 (SPAMD)
* 其他所有流量阻塞。

注意策略是如何覆盖所有通过防火墙的流量的。括号里面的项目是策略将使用的标记。
需要过滤和转换规则来把数据包分配到不同的策略。

rdr on $ext_if proto tcp from to port smtp \
tag SPAMD -> 127.0.0.1 port 8025

block all
pass in on $int_if from $int_net tag LAN_INET keep state
pass in on $int_if from $int_net to $dmz_net tag LAN_DMZ keep state
pass in on $ext_if proto tcp to $www_server port 80 tag INET_DMZ keep  
state

现在要设置定义策略的规则。

pass in quick on $ext_if tagged SPAMD keep state
pass out quick on $ext_if tagged LAN_INET keep state
pass out quick on $dmz_if tagged LAN_DMZ keep state
pass out quick on $dmz_if tagged INET_DMZ keep state

现在要建立整个规则集,修改分类规则。例如,如果pop3/SMTP服务器增加到了DMZ区,就需要增加针对POP3和SMTP流量的分类,如下:

mail_server = "192.168.0.10"
...
pass in on $ext_if proto tcp to $mail_server port { smtp, pop3 } \
tag INET_DMZ keep state

Email 流量会作为INET-DMZ策略的条目被放行。
完整的规则:

# macros
int_if = "dc0"
dmz_if = "dc1"
ext_if = "ep0"
int_net = "10.0.0.0/24"
dmz_net = "192.168.0.0/24"
www_server = "192.168.0.5"
mail_server = "192.168.0.10"

table persist file "/etc/spammers"

# classification -- classify packets based on the defined firewall
# policy.
rdr on $ext_if proto tcp from to port smtp \
tag SPAMD -> 127.0.0.1 port 8025

block all
pass in on $int_if from $int_net tag LAN_INET keep state
pass in on $int_if from $int_net to $dmz_net tag LAN_DMZ keep state
pass in on $ext_if proto tcp to $www_server port 80 tag INET_DMZ keep state
pass in on $ext_if proto tcp to $mail_server port { smtp, pop3 } \
tag INET_DMZ keep state

# policy enforcement -- pass/block based on the defined firewall policy.
pass in quick on $ext_if tagged SPAMD keep state
pass out quick on $ext_if tagged LAN_INET keep state
pass out quick on $dmz_if tagged LAN_DMZ keep state
pass out quick on $dmz_if tagged INET_DMZ keep state

标记以太网帧

打标记可以在以太网级别进行,如果执行标记/过滤的机器同时做为网桥。通过创建使用tag关键字的网桥过滤规则,PF可以建立基于源/目的MAC地址的过滤规则。网桥规则可以由brconfig(8)命令产生,例如:

# brconfig bridge0 rule pass in on fxp0 src 0:de:ad:be:ef:0 \
tag USER1

然后在 pf.conf文件中:

pass in on fxp0 tagged USER1

论坛徽章:
0
119 [报告]
发表于 2006-12-09 08:56 |只看该作者

附加主题

PF: 日志

------------------------------------------------------------------------------
简介

PF的包日志是由pflogd(8)完成的,它通过监听pflog0接口然后将包以tcpdump(8)二进制格式写入日志文件(一般在/val/log/pflog)。过滤规则定义的日志和log-all关键字所定义的日志都是以这种方式记录的。

读取日志文件

文本编辑器不能读取日志文件,必须使用Tcpdump来查看日志。

使用如下格式查看日志信息:

# tcpdump -n -e -ttt -r /var/log/pflog

使用tcpdump( 查看日志文件并不是实时的,若要实时查询日志信息需加上pflog0参数:

# tcpdump -n -e -ttt -i pflog0

当查看日志时需要特别注意tcpdump的详细协议解码(通过在命令行增加-v参数实现)。
为避免引发延时攻击,推荐在查询日志文件信息之前,先将该日志文件从防火墙上移走。

对日志文件的安全访问。默认情况下,pflogd 将在日志文件中记录96字节的包信息。访问日志文件将提供访问部分敏感包信息的途径(就像telnet(1)或者ftp(1)的用户名和密码)。

导出日志

由于pflogd以tcpdump二进制格式记录日志信息,因此可以使用tcpdump的特点。例如,只查看与特定端口匹配的包:

# tcpdump -n -e -ttt -r /var/log/pflog port 80

甚至可以限定具体的主机和端口:

# tcpdump -n -e -ttt -r /var/log/pflog port 80 and host 192.168.1.3

同样的方法可以应用到直接从pflog0接口读取的信息:

# tcpdump -n -e -ttt -i pflog0 host 192.168.4.2

注意这与包被记录到pflogd日志文件不相冲突;上述语句只以包被记录的形式显示。
除了使用标准的tcpdump(8)过滤规则外,OpenBSD的tcpdump过滤语言为读取pflogd而被扩展:

* ip -IPv4版本地址。
* ip6 - IPv6版本地址。
* on int - 包通过int接口。
* ifname int - 与 on int相同.
* rulenum num - 包匹配的过滤规则编号为num。
* action act - 对包的操作。可能是pass(通过)或者block(阻断)。
* reason res - 执行对包操作的原因。可能的原因是match(匹配), bad-offset, fragment, short, normalize(规格化), memory(内存)。
* inbound -入栈包。
* outbound - 出栈包。

举例:

# tcpdump -n -e -ttt -i pflog0 inbound and action block and on wi0

这将以实时方式显示被wi0接口阻断的入栈包的日志信息。

通过Syslog记录日志

很多情况下需要将PF日志记录以ASCII代码格式存储,或者(同时)把这些日志存到远程的日志服务器上。这些可以通过两个小的脚本文件实现,是对 openbsd配置文件和syslogd(8),日志守护进程的少许修改。Syslogd进程以ASCII格式存储日志,同时可以将日志存储到远程日志服务器。

首先我们必须建立一个用户,pflogger,使用 /sbin/nologin  shell最简单的建立用户的方法是使用adduser(8)。

完成后建立如下两个脚本:

/etc/pflogrotate
FILE=/home/pflogger/pflog5min.$(date "+%Y%m%d%H%M")
kill -ALRM $(cat /var/run/pflogd.pid)
if [ $(ls -l /var/log/pflog | cut -d " " -f -gt 24 ]; then
mv /var/log/pflog $FILE
chown pflogger $FILE
kill -HUP $(cat /var/run/pflogd.pid)
fi

/home/pflogger/pfl2sysl
for logfile in /home/pflogger/pflog5min* ; do
tcpdump -n -e -ttt -r $logfile | logger -t pf -p local0.info
rm $logfile
done

编辑root的cron 任务:

# crontab -u root -e

增加如下两行:

# rotate pf log file every 5 minutes
0-59/5 * * * * /bin/sh /etc/pflogrotate

为用户pflogger建立一个cron任务:

# crontab -u pflogger -e

增加如下两行:

# feed rotated pflog file(s) to syslog
0-59/5 * * * * /bin/sh /home/pflogger/pfl2sysl

将下行增加到 /etc/syslog.conf:

local0.info /var/log/pflog.txt

如果需要日志记录到远程日志服务器,增加:

local0.info @syslogger

确定主机syslogger已在hosts(5)中定义。

建立文件 /var/log/pflog.txt 使 syslog 可以向该文件写入日志:

# touch /var/log/pflog.txt

重启syslogd使变化生效:

# kill -HUP $(cat /var/run/syslog.pid)

所有符合标准的包将被写入/var/log/pflog.txt. 如果增加了第二行,这些信息也将被存入远程日志服务器syslogger。

脚本 /etc/pflogrotate 将执行,然后删除 /var/log/pflog ,因此
rotation of pflog by newsyslog(Cool 不再必需可以被禁用。然而, /var/log/pflog.txt 替代 /var/log/pflog and rotation of it 要被启用。 改变 /etc/newsyslog.conf 如下:

#/var/log/pflog 600 3 250 * ZB /var/run/pflogd.pid
/var/log/pflog.txt 600 7 * 24

PF 将日志以ASCII格式记录到/var/log/pflog.txt. 如果这样配置 /etc/syslog.conf, 系统将把日志存到远程服务器。存储过程不会马上发生,但是会在符合条件的包出现在文件中前5-6分钟实现。

==============================================================================

论坛徽章:
0
120 [报告]
发表于 2006-12-09 08:58 |只看该作者

附加主题

PF: 性能

------------------------------------------------------------------------------
“PF可以处理多少带宽?”
“我需要多少台计算机处理因特网连接?”

这个问题没有简单的答案。取决于每秒处理的包数和规则集的复杂程度。

体现PF性能的几个参数:

* 每秒处理包的数量. 一个1500字节的包和一个只有1个字节的包所需要的处理过程的数目几乎是一样的。
* 系统总线性能. PCI总线有更有效的带宽,与处理器的冲突更小。
* 网卡的效率. 一些网卡的工作效率要高于其他网卡。 建议使用千兆网卡,尽管所连接的网络不是千兆网,这些千兆网卡拥有高级的缓存,可以大幅提高性能。
* 规则集的设计和复杂性。规则越复杂越慢。越多的包通过keep和quick方式过滤,性能越好。对每个包的策略越多,性能越差。
* 值得一提: CPU 和内存。由于PF是基于内核的进程,它不需要swap空间。而需要内存。 32MB内存对小型办公室或者家庭应用足够。

==============================================================================
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP