|
先翻译一部分PF文档出来, 兄弟们看看有哪些语句不通顺,翻译错误的地方请指出来, 回贴或发到renhw895@sohu.com给我,我好边翻译后边的文档边修改前面的错误! 谢谢!
PF: The OpenBSD Packet Filter
Packet Filter(后面我们简单叫:PF)是openbsd系统用来过滤tcp传输和进行网络地址转换的一个工具。PF通常用来管理TCP/IP传输和带宽管理及数据包的优先级管理。从openbsd3.0开始PF已作为系统的基本内核包含在系统中了。之前使用的firewall/NAT将不再使用。
PF最初是由Daniel Hartmeier开发的, 现在主要开发管理负责人是Daniel和OpenBSD开发团队。
这个文档是PF运行在OpenBSD系统上的一个基本介绍。它是对系统man pages的一个补充, 并不能取代它们。本文档并没包含所有PF的特性, 可能不会随man pages一起更新。
这份文档主要集中于在OpenBSD3.4使用。PF一直在开发, OpenBSD3.4 和OpenBSD-current之间可能有一些改变和增加。 读者最好先看看自己系统上的man pages。
PF: Configuration
Activation
打开PF并使它能在boot时阅读配置文件, 你需要修改/etc/rc.conf并将PF这一行改为如下所示:
pf=YES
重启系统它就可以工作了。
当然你也可以使用pfctl(8)这个程序来打开和关闭PF:
pfctl –e
pfctl –d
这只是打开和关闭PF, 它并不会从配置文件中导入规则设置。规则设置需要另外导入, 可以在PF启动之前或之后。
Configuration
PF在rc脚本中启动时从/etc/pf.conf中导入规则设置。 /etc/pf.conf是默认的配置文件, 会被系统rc脚本加载进去; pfctl(8)会加载解析这个文本文件并将它插入pf(4)中。如果还有别的规则链可以在启动后加入。同其它unix程序一样, PF有很好的适应性。
pf.conf 文件由七部分组成:
Macros: 用户可以为 hold IP addresses、 interface name等定义变量。
Tables: 为有效使用的IP地址定义结构。
Options: 各种选项控制PF如何工作。
Scrub: 重新对数据包进行规范化并分片整理。
Queueing: 带宽管理及数据包优先级管理。
Translation: 管理网络地址转换及数据包转发。
Filter Rules: 当数据包通过端口时允许对数据包进行过滤和阻塞。
除macros and tables之外, 别的选项都应该尽可能包含中配置文件中。
空白行忽略, 以#开头的行当成注释。
Control
启动后, 可以使用pfctl(8)来管理pf操作。如下面的一些例子:
# pfctl –f /etc/pf.conf 载入pf.conf配置文件
# pfctl –nf /etc/pf.conf 解析pf.conf文件, 但不载入。
# pfctl –Nf /etc/pf.conf 只从文件中载入NAT规则链。
# pfctl –Rf /etc/pf.conf 只从文件中载入过滤规则链。
# pfctl –sn 显示当前的NAT规则链
# pfctl –sr 显示当前的过滤规则链
# pfctl –ss 显示当前的状态
# pfctl –si 显示过滤状态和计数
# pfctl –sa 显示所有能显示的东西。
具体命令可参考 pfctl (8) manpage。
Lists and Macros
Lists
Lists允许你在一条规则中指定类似类型的规格说明。 例如:各种protocols, 端口号, 地址等。所以在过滤规则中不必为每一个IP地址都进行阻塞, 可以用将详细的IP地址放在一个lists中写进一条规则链中。Lists通常定义在{ }括号之中。
当pfctl(8)载入的规则链中有lists时, 它会将它们分成几条规则来执行。如:
block out on fxp0 from { 192.168.0.1, 10.5.32.6 } to any
分解成:
block out on fxp0 from 192.168.0.1 to any
block out on fxp0 from 10.5.32.6 to any
各种lists可以详细的写进规则链, 并不是只能写进过滤规则中。
Rdr on fxp0 proto tcp from any to any port { 20 80 } -> \
192.168.0.6
block out on fxp0 proto { tcp udp } from { 192.168.0.1, \
10.5.32.6 } to any port { ssh telnet }
lists中每个items是随意排列的。
Macros
Macros用来给IP地址、端口号, 接口名等定义一个别名。Macros可以简化设置PF规则链的复杂性并使管理变得更加容易。
Macros名称必须以字母开头, 可以包含字母、数字和下划线。Macros名称不能是保留关键字如:pass、out、queue等。
ext_if = “fxp0”
block in on $ext_if from any to any
这里建了一个macro叫ext_if, 一个macro可以在它建立后进行引用, 但它名字前必须有包含$符号。
Macros 同样可以发展成一个lists, 如:
friends = “{ 192.168.1.1, 10.0.2.5, 192.268.43.53 }”
Macros可以进行递归定义。自从引号内宏没有扩展下列语法必须被使用:
host1 = “192.168.1.1”
host2 = “192.168.1.2”
all_hosts = “{“$host1 $host2 “}”
现在macro $all_hosts被扩展到:192.168.1.1, 192,168.1.2。
PF: Tables
Introduction
Table用来控制一组IPv4 (和/或) IPv6 地址。使用table查找非常快, 它会消耗很少的内存并且执行速度比lists快。因为这样, table在一组5000条地址中的查找速度比一组50条地址中的查找只慢一点点。Table用在filter、scrub、 net、redirection等规则的源地址和目的地址中,但不能用在nat规则中的转发地址中或fileter规则中的routing options中。Table 可以在/etc/pf.conf中创建或利用pfctk(8)使用。
Configuration
在pf.conf中, 使用table指令创建tables。下面是每个属性的详细说明:
const – table建立后table中的内容将不再改变。如果不使用这个属性, pfctl(8)可以随时从table中添加或删除地址,even when running with a securelevel(7) of two or greater.
persist – 即使没有一条规则使用它, kernel也将这个table保存在内存中。如果不使用这个属性, 当最后一个规则不在使用这个table时, the kernel会自动删除它。
例如:
table < goodguys > { 192.0.2.0/24 }
table < rfc1918 > const { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table < spammers > persist
block in on fxp0 from { < rfc1918 >, < spammers > } to any
pass in on fxp0 from < goodguys > to any
Addresses同样可以使用 取反( or “not” )标示符, 如:
table < goodguys > { 192.0.2.0/24, !192.0.2.5 }
goodguys table将匹配192.0.2.0/24中除192.0.2.5之外的所有地址。
提示:table name通常包含在< >括号内。
Tables也可以中一个文本文件中获取IP地址列表。
Table < spammers > persist file “/etc/spammers”
Block in on fxp0 from < spammers > to any
/etc/spammers文件中每一行应该包含一条IP 地址。如果有行以#开头将当作注释忽略掉。
Manipulating with pfctl
可以使用pfctl(8)来处理tables。 如这个例子:
# pfctl –t spammers –Tadd 218.70.0.0/16
如果< spammers >table不存在将创建它。显示table中地址:
# pfctl –t spammers –Tshow
-v 选项同可以和 –Tshow一起用来显示统计每一个table。从table中删除地址:
# pfctl –t spammers –Tdelete 218.70.0.0/16
想了解更多关于pfctl控制tables的信息可以查看 pfctl(8)。
Specifying Addresses
除了IP地址被指定外, 也可以使用主机名指定主机。当一个主机名解析成IP 地址时, IPV4和IPV6的结果都包含在一个table里。可以为IP 地址指定一个有效的接口名加入到table中, 或在为所有的地址指定接口关键字的情况下加入到table中。(原文:IP addresses can also be entered into a table by specifying a valid interface name or the self keyword in which case all addresses assigned to the interface(s) will be added to the table.)
Address Matching
对table中的地址查找将返回精细的匹配。它允许这样创建tbales:
table <goodguys> { 172.16.0.0/16, !172.16.1.0/24, 172.16.1.100}
block in on dc0 all
pass in on dc0 from <goodguys> to any
通过dc0接口进来的任何数据包将把它的源地址与table <goodguys>进行匹配。
172.16.50.5 – 精确匹配:172.16.0.0/16; 数据包匹配tables, 将通过。
172.16.1.25 – 精确匹配:!172.16.1.0/24; 匹配172.16.1.0/24, 但这个地址是取反操作, 也就是匹配172.16.1.0/24的数据包都不能通过, 所以这个数据包不能通过。
172.16.1.100 – 匹配:172.16.1.100; 数据包通过。
10.1.4.55 – 没有匹配规则, 将阻塞。
PF: Options
Options用来控制PF的操作。Options指定用在/etc/pf.conf里设置指令。
Set block-policy
为filter rules设置缺省行为:阻塞动作
drop – 数据包默默地drop。
return – TCP RST数据包返回一个阻塞的TCP包,ICMP UNREACHABLE 包返回阻塞的UDP包。其它的包将silently dropped。
注意:单个的filter rules可以越过缺省回应。
Set limit
flags – 内存池中数据包重新组装的最大数(为scrub rules设置)。缺省5000。
states – 内存池中保存使用的全局table状态的最大数(flter rules指定存在的状态)。缺省:10000。
Set loginterface int
设置PF收集统计数据如:bytes in/out and packets passed/blocked时使用的接口。仅仅每次为一个接口统计收集数据, 如匹配规则, 坏偏移量等。不管loginterface 是否被设置, 计数器和table计数器都将被记录。
Set optimization
在下面的网络环境中优化PF:
normal – 适用于所有的网络, 这个是缺省的。
high-latency – 用于如人造卫星等高反应时间的网络。
aggressive – 迅速去中state table里终止连接。在繁忙的防火墙冒着去掉无用连接的风险来减少内存需求。
conservative – 极保守的设置。这避免在使用更多的内存情况下去掉无用连接并稍微增加了处理器的使用率。
Set timeout
interval – 清除终止的状态和数据包碎片的秒数。
flag – 未组装的分片终止秒数。
Examples:
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
PF:Scrub
Introduction
“Scrubbing”是数据包标准化、正常化;使到到达最终目地地的数据包解释没有歧义。Scrub指令也可以重新组合分片的数据包,阻止一些操作系统攻击的形式,去掉含有无用flag组合的TCP数据包。如下面简单的scrub指令:
scrub in all
这将清理所有端口进来的数据包。
如果通过PF使用一个NFS传输, 那不能在一个接口上使用scrub。一些非openbsd系统平台发送(and expect)奇怪的数据包 – 分片数据包没有设置“do not fragment”位,它(可能会)拒绝使用scrub整理。这能使用no-df选项解决。别的原因:一些多媒体游戏程序在通过一个使用了scrub设置的PF防火墙时连接会有问题。除了这些不平常的原因外,scrubbing all packets被着重推荐使用的。
Scrub指令语法与filtering 语法很相似,使用它可以很容易地选择清理可靠的数据包和其它的数据包。
下面的链接有更多关于scrub的原理和介绍:(文章名:网络入侵检测)
http://www.icir.org/vern/papers/norm-usenix-sec-01-html/index.html
Options
Scrub有下面一些选项:
no-df
从IP数据包头清理don’t fragment位。一些操作系统产生设置了don’t fragment位的分片数据包。NFS是最明显的!scrub如果不设置no-df选项将清除所有这些数据包。一些操作系统产生在片头包含了一个zero IP identification的don’t fragment数据包。推荐no-df 和random-id结合在一起使用。
random-id
将某些操作系统发送到外面的数据包中IP identification field中使用的随机数值替换成一个可预见的值。这个选项适用于向外发送在随意重新组合后没有分片的数据包。
min-ttl num
强制放一个最小 Time To Live ( TTL )到IP数据包包头。
max-mss num
强制放一个最大Maximum Segment Size ( MSS )到TCP数据包包头。
fragment reassemble
在通过filter engine前将缓冲区进来的分片包重新组合成一个完整的数据包。这样做的优势是filter rules只处理完整的数据包而可以忽略分片数据包(碎片包)。缺点是需要增加内存容量来缓冲分片数据包。当没有fragment选项指定时这个是缺省设置。也只有这个fragment 选项能与NAT一起工作。
fragment crop
主要用于将相同的分片抛弃和裁切一些交迭的分片。并不像分片重组,到达的分片并不进行缓冲而是尽快的通过。
fragment drop-ovl
与fragment crop相似,会更进一步将相应的分片的所有相同或重叠的分片抛弃。
Example:
Scrub in on fxp0 all fragment reassemble min-ttl 15 max-mss 1400
PF: Queueing
Queueing
在等候处理时将一些信息进行存储、排序。在计算机网络里,当数据包从某主机上发送出来,在等候操作系统处理时它们进入一个队列。操作系统将决定对某队列或某队列上的数据包进行处理。网络性能影响操作系统处理数据包的顺序。例如:想像一个用户正在运行两个程序:SSH和FTP。直观地, 由于SSH的the time-sensitive性质,SSH数据包将比FTP数据包进行优先处理;当客户端使用一个KEY连接到服务器时, 立刻有一个回应,但FTP传输却几乎因任何通知而延迟了几秒钟。那么路由器在处理SSH连接数据包前是如何处理FTP连接数据包的呢?SSH连接数据包将保持进一个队列(或如果队列没有足够的空间存储所有数据包的话, 路由器可能抛弃一些数据包)和SSH会话可能出现滞后或断开。改进队列的策略运用,使网络带宽在不同的程序、用户和电脑间进行共享。
注意队列只能用于发送往外面的数据包上。当从一个接口进来的数据包已太迟对它进行排列了 – 在从接口处接收它时已消耗了网络带宽。唯一的解决方案是:在邻近的路由器上启用队列,或如果一个收到数据包的主机起代理路由器的作用,对存在于路由器内部接口上的数据包进行排列。
Schedulers
调度程序决定对队列进行处理和排序。OpenBSD默认情况下使用First In First Out ( FIFO )调度程序。FIFO队列就像在超市或银行里排队等候处理一样 – 队列的第一组第一个处理。新到的数据包将加到队列的尾端。如果一个队列排满, 新到的数据包将被抛弃。这就是队尾抛弃。
OpenBSD支持两个额外的调度程序:
Class Based Queueing
Priority Queueing
Class Based Queueing
Class Based Queueing ( CBQ )是一个队列算法,用来区分网络连接的带宽中的多样的队列或classes。每个队列基于源地址或目的地址、端口号或网络协议等分配。队列可以随意的从可以利用的父队列里分配到带宽。可以给交互式的传输队列优先权,如SSH,可以先处理大的数据包,如FTP。
CBQ被安排进一个分等级的样式中。在顶层的root队列定义了全部的带宽。 子队列在root队列下建立,每个子队列可以从root队列分得一部分带宽。例如:像下面这样定义队列:
Root Queue ( 2 Mbps )
Queue A ( 1 Mbps )
Queue B ( 500 Kbps )
Queue C ( 500 Kbps )
在这例中, 总带宽设置为2 megabits per second( Mbps )。将这个带宽分配给与3个子队列。
更进一步使用层次对队列定义。在不同用户间公平的分配带宽和分类他们的传输以便不致于使用某协议的传输分配不到带宽,队列结构如下所示:
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)
如果FTP传输队列使用超过了900Kbps带宽,而用户A的传输队列使用的带宽少于1Mbps(因为SSH传输队列使用的带宽少于分配的100Kbps),FTP传输将从用户A里借用剩下的带宽。这样, 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队列进行优先权比较, 因为它们处于不同的优先权分支上。
想更进一步了解的CBQ详细说明和理论,可访问这个网站。
Priority Queueing
Priority Queueing ( PRIQ )为网络接口的各样队列中每一个队列分配唯一的优先权。具有高优先权的队列通常在低优先权队列前处理。
PRIQ里的队列结构很干脆 – 你不能在队列中再定义队列。root队列设置为拥有全部带宽,子队列直接从root队列下定义。考虑下面例子:
Root Queue (2Mbps)
Queue A (priority 1)
Queue B (priority 2)
Queue C (priority 3)
root队列定义为含有2Mbps的带宽并且它下面定义了3个子队列。具有最高优先权的(有最高优先权数字)队列被首先服务。当那个队列中的所有数据包处理完后, 或那个队列为空,PRIQ移到具有第二优先权的队列进行处理。在给定的队列中(翻译者加:在进行处理的队列中), 数据包以First In First Out(FIFO)进行处理。
重要提示:当使用PRIQ时你必须小心的计划队列。因为PRIQ通常优先处理优先权较高的队列,当具有高优先权队列持续接收数据包时可能会导致低优先权的队列的数据包被延迟或抛弃。
Random Early Detection
Random Early Detection是拥塞回避算法。它的工作是避免网络拥塞以保证队列不被填满。它不断地计算队列的平均长度并与两个threshold(最小的shreshold和最大的threshold)进行比较。当队列的平均长度小于最小threshold时没有数据包被抛弃。当平均长度大于最大threshold时所有新到达的数据包都被抛弃。当平均长度在两者之间时, 可能会基于计算队列的平均长度来抛弃数据包。换句话说, 当队列平均长度逼进最大threshold时, 大量的数据包会被抛弃。当抛弃数据包时, RED随机地抛弃某个连接中的数据包。使用大量带宽的连接的数据包有更高的可能性被抛弃。
RED非常有用,它可以避免全局同步,在网络传输爆发的情况下进行调节。(有点不清楚, 请指正。原文:RED is useful because it avoids a situation known as global synchronization and it is able to accommodate bursts of traffic)。由于同一时刻若干连接中有数据包会抛弃,全局同步(Global synchronization)提供了全部吞吐量的降低状况。例如,在网络拥塞出现时,路由器为10个FTP连接进行传输, 这些连接的数据包被除数抛弃(在使用FIFO的队列中),全部吞吐量会急剧地抛弃。这并不是理想情况, 因为它会减少所有FTP连接的吞吐量,也就是说网络不再能发挥出最大的潜力。RED提供随机地从某个连接中抛弃数据包来替代上面的选择。使用高带宽的连接的数据包越有可能会被抛弃。这样,高带宽的连接被节流,拥塞会避免,全部吞吐量明显的降低将不会出现。另外,RED能处理爆发网络传输,因为在队列还没排满前它已开始抛弃数据包。当瀑发传输到来时它已有足够的空间来存储新到的数据包。
当传输协议可能反应网络出现爆发情况时RED会被应用。这就是说在大多数情况下RED应该应用于TCP传输而不是UDP或ICMP传输。
想了解更多关于RED的原理和技术可访问这个网站。
Explicit Congestion Notification
Explicit Congestion Notification(ECN)与RED一起工作, 通报两台通信的主机中的拥塞的通信路径。它允许RED在数据包包头设置一个标记来替代将数据包抛弃。发送主机有支持ECN, 它可以读取这个标记因此来节流它的网络传输。
更多的ECN信息可查看RFC 3168。
Configuring Queueing
自从OpenBSD3.0开始, Alternate Queueing( ALTQ )作为基本系统执行的一部分。从OpenBSD 3.3开始已整合进PF里了。OpenBSD上的ALTQ实现支持the Class Based Queueing(CBQ)和Priority Queueing(PRIQ)调度程序。它同样支持Random Early Detection(RED)和Explicit Congestion Notification(ECN)。
因为ALTQ已合并到PF里了,所以PF必须启用队列。在配置一节中有如何启动PF工作的介绍。
Queueing 在/etc/pf.conf里配置。这里有两个指令用来配置队列(queueing)。
altq on – 在一个接口上启动队列,定义使用哪个调度程序和创建root队列。
queue – 为子队列定义特性。
altq on 指令的语法为:
altq on interface scheduler bandwidth bw qlimit qlim \
tbrsize size queue { queue_list }
interface – 队列使用的网络接口。
scheduler – 使用的队列调度程序。可能的值有cbq和priq。一个时间一个接口上只能使用一种调度程序。
bw – 调度程序能使用的总带宽。This may be specified as an absolute value using the suffixes b, Kb, Mb, and Gb to represent bits, kilobits, megabits, and gigabits per second, respectively or as a percentage of the interface bandwidth。
qlim – 队列保存的数据包的最大数。这个参数是可选择的, 默认为50。
size – 使用字节设置the token bucket regulator的大小。如果不指定,这个大小将基于接口的带宽。
queue_list – 在root队列下创建的子队列列表。
例如:
altq on fxp0 cbq bandwidth 2Mb queue { std, ssh, ftp }
这个在fxp0接口使用CBQ, 总带宽设置为2Mbps,定义了三个子队列:std、ssh和ftp。
queue指令的语法为:
queue name bandwidth bw priority pri qlimit qlim \
scheduler ( sched_options ) { queue_list }
name – 队列名。必须与altq on 指令中queue_list中定义的队列名之一相匹配。使用cbq时队列名同样要与先前queue指令中queue_list中的队列名之一相匹配。队列名不能长于15个字符。
bw – 调度程序使用总带宽。This may be specified as an absolute value using the suffixes b, Kb, Mb, and Gb to represent bits, kilobits, megabits, and gigabits per second, respectively or as a percentage of the interface bandwidth。
pri – 队列的优先权。使用cbq时范围为0 -> 7,使用priq时范围为0 -> 15。优先公0是最低的。如果不指定,默认指定1。
qlim – 队列保存的数据包的最大数。这个参数是可选择的, 默认为50。
scheduler – 使用哪个调度程序。可选择:cbq或priq。必须与root队列使用的调度程序相同。
sched_options – 更多控制调度程序行为的选项:
default – 定义一个缺省队列, 当数据包与别的队列不能匹配时都将进入这个队列中。这个队列必须正确定义。
red – 在队列中启用Random Early Detection(RED)。
rio – 让RED与IN/OUT一起使用。在这个模式下,RED维持多样的平均队列长度和多样的threshold值,每一个IP服务水平的质量。
ecn – 在这个队列上启用Explicit Congestion Notification(ECN)。ENC需要RED一起使用。
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队列从root队列中分到了50%(1Mbps)的带宽并将它设置成默认队列(default queue)。ssh队列又从中定义了两个子队列,ssh_login队列和ssh_bulk队列。ssh_login队列比ssh_bulk队列的优先权高并且两个队列都启动了ECN选项。ftp队列分到了500kbps的带宽并设置了优先权3。它可以从父队列中借用额外的带宽并启动了RED选项。
Assigning Traffic to a Queue
将网络传输分配给队列,队列关键字和PF’s filter rules一起使用。例如,考虑如下filter rules设置:
pass out on fxp0 from any to any port 22
可以使用队列关键字为匹配规则的数据包指定队列:
pass out on fxp0 from any to any port 22 queue ssh
当与block指令一起使用队列关键字时,结果是任何TCP RST或ICMP不能到达的数据包都将分配到指定的队列中。
注意除了altq on指令定义的端口外别的端口的数据可能会附加到队列上。(这句有些疑问,原文:Note that queue tagging can happen on an interface other than the one defined in the altq on directive ):
altq on fxp0 cbq bandwidth 2Mb queue { std, ftp }
queue std cbq(default)
queue ftp bandwidth 1.5Mb
队列启用的fxp0端口但事情发生在dc0端口上。如果数据包匹配存在于fxp0端口的pass rule。它们将加入到ftp队列中。这种类型的队列在路由器上很有用。
基本上随队列关键字给出的只有一个队列,如果有第二个名字被指定,那队列用于低延迟服务型的数据包(packets with a Type of Service(ToS)of low-delay)和有没数据负荷的TCP ACK数据包。一个非常有用的例子是使用ssh 。SSH login会话将设置 ToS 为低延迟而SCP和SFTP会话却不会。PF可以使用登陆连接的数据包与没有登陆连接的数据包的不同属性来将数据包分配到不同的队列中。这就可以把登陆连接数据包的优先权设置在文件传输数据包之上。
pass out on fxp0 from any to any port 22 queue(ssh_bulk, ssh_login)
上面将SSH login会话连接属性的数据包分配到ssh_login队列中,将SCP和SFTP连接属性的数据包分配到ssh_bulk队列中。由于ssh_login具有较高的优先权,SSH login连接的数据包会在SCP 和SFTP连接的数据包前面处理。
在不对称连接中, 把TCP ACK数据包分配到高优先权队列是很有用处的,that is, 在ADSL连网中, 上传和下载连接使用不同的带宽。在使用ADSL传输线路中,当上传通道流量过多时下载通道将使用,下载通道将忍受因为TCP ACK数据包想使用的上载通道处于拥塞状态而只好使用下载通道了。测试显示了很好的结果,上载通道的带宽应该设置小于连接线路提供的能力。例如,如果ADSL线路最大上传带宽为640kbps,那么最好将root队列的带宽设置为600kbps,这样性能会好一些。试验将产生最好的设定带宽。
当在规则中使用队列关键字保持那种状态时:
pass in on fxp0 proto tcp from any to any port 22 flags S/SA \
keep state queue ssh
PF将在状态table入口记录队列,数据包移回到fxp0接口匹配状态连接并加入到ssh队列的尾部。注意尽管即使队列关键字运行在过滤进来的网络传输规则中,目的是为外出的网络连接指定相应的队列;上面的规则并不队列进来的数据包。
Example # 1: Small, Home Network
[ Alice ] [ Charlie ]
| | ADSL
---+-----+-------+------ dc0 [ OpenBSD ] fxp0 -------- ( Internet )
|
[ Bob ]
在这例中,OpenBSD用于有三个工作站的小型家庭网络的网关。网关主要用于执行包过滤和NAT。连接internet的连接是一个ADSL连接,有640kbps的上载带宽和2Mbps的下载带宽。
这个网络的队列方案是:
1、为Bob分配80Kbps的下载带宽,当Alice or Charlie没有使用大量下载时他可以玩在线游戏。允许在网络空闲时Bob使用的带宽大于80Kbps。
2、SSH连接和即时通讯传输比平常传输拥有更高的优先权。
3、DNS查询和答复拥有第二高优先权。
4、向外传输的TCP ACK数据包比一般的向外传输的数据包拥有更高的优先权。
下面是这个网络的规则方案。注意pf.conf指令仅仅包含前面介绍过的命令;nat, rdr, options等都没有显示。
# enable queueing on the external interface to control traffic going to
# the Internet. use the priq scheduler to control only priorities. set
# the bandwidth to 610Kbps to get the best performance out of the TCP
# ACK queue.
altq on fxp0 priq bandwidth 610Kb queue { std_out, ssh_im_out, dns_out, \
tcp_ack_out }
# define the parameters for the child queues.
# std_out - the standard queue. any filter rule below that does not
# explicitly specify a queue will have its traffic added
# to this queue.
# ssh_im_out - interactive SSH and various instant message traffic.
# dns_out - DNS queries.
# tcp_ack_out - TCP ACK packets with no data payload.
queue std_out priq(default)
queue ssh_im_out priority 4 priq(red)
queue dns_out priority 5
queue tcp_ack_out priority 6
# enable queueing on the internal interface to control traffic coming in
# from the Internet. use the cbq scheduler to control bandwidth. max
# bandwidth is 2Mbps.
altq on dc0 cbq bandwidth 2Mb queue { std_in, ssh_im_in, dns_in, bob_in }
# define the parameters for the child queues.
# std_in - the standard queue. any filter rule below that does not
# explicitly specify a queue will have its traffic added
# to this queue.
# ssh_im_in - interactive SSH and various instant message traffic.
# dns_in - DNS replies.
# bob_in - bandwidth reserved for Bob's workstation. allow him to
# borrow.
queue std_in cbq(default)
queue ssh_im_in priority 4
queue dns_in priority 5
queue bob_in bandwidth 80Kb cbq(borrow)
# ... in the filtering section of pf.conf ...
alice = "192.168.0.2"
bob = "192.168.0.3"
charlie = "192.168.0.4"
local_net = "192.168.0.0/24"
ssh_ports = "{ 22 2022 }"
im_ports = "{ 1863 5190 5222 }"
# filter rules for fxp0 inbound
block in on fxp0 all
# filter rules for fxp0 outbound
block out on fxp0 all
pass out on fxp0 inet proto tcp from (fxp0) to any flags S/SA \
keep state queue(std_out, tcp_ack_out)
pass out on fxp0 inet proto { udp icmp } from (fxp0) to any keep state
pass out on fxp0 inet proto { tcp udp } from (fxp0) to any port domain \
keep state queue dns_out
pass out on fxp0 inet proto tcp from (fxp0) to any port $ssh_ports \
flags S/SA keep state queue(std_out, ssh_im_out)
pass out on fxp0 inet proto tcp from (fxp0) to any port $im_ports \
flags S/SA keep state queue(ssh_im_out, tcp_ack_out)
# filter rules for dc0 inbound
block in on dc0 all
pass in on dc0 from $local_net
# filter rules for dc0 outbound
block out on dc0 all
pass out on dc0 from any to $local_net
pass out on dc0 proto { tcp udp } from any port domain to $local_net \
queue dns_in
pass out on dc0 proto tcp from any port $ssh_ports to $local_net \
queue(std_in, ssh_im_in)
pass out on dc0 proto tcp from any port $im_ports to $local_net \
queue ssh_im_in
pass out on dc0 from any to $bob queue bob_in
Examples # 2: Company Network
( IT Dept ) [ Boss's PC ]
| | T1
--+----+-----+---------- dc0 [ OpenBSD ] fxp0 -------- ( Internet )
| fxp1
[ COMP1 ] [ WWW ] /
| /
--+----------'
在这一例中, OpenBSD用于一个公司的防火墙。在它们的DMZ网络部分中运行着公司的www服务器, 用户使用FTP上传到他们的服务器上。IT部门把他们的子网连接到主干网上,老板办公室里有台电脑用于收发email和浏览网页。使用双向传输都是1.5Mbps的T1连接到internet。别的网段都使用快速以太网(100Mbps)。
网络管理员决定使用下面的方案:
1、 限制www和internet之间的双向网络传输为500Kbps。
2、 内部网络与www之间没有带宽限制。
3、 给www与internet之间的HTTP传输比别的传输(如FTP)更高的优先权。
4、 为IT部门预备500Kbps, 这样他们可以下载升级软件。当有剩余网络带宽时, 可以使用超过500Kbps的带宽。
5、 老板的电脑到internet的连接传输比别的连接传输的优先权高。
下面是这个网络的规则方案。注意pf.conf指令仅仅包含前面介绍过的命令;nat, rdr,
options等都没有显示。
# enable queueing on the external interface to queue packets going out
# to the Internet. use the cbq scheduler so that the bandwidth use of
# each queue can be controlled. the max outgoing bandwidth is 1.5Mbps.
altq on fxp0 cbq bandwidth 1.5Mb queue { std_ext, www_ext, boss_ext }
# define the parameters for the child queues.
# std_ext - the standard queue. also the default queue for
# outgoing traffic on fxp0.
# www_ext - container queue for WWW server queues. limit to
# 500Kbps.
# www_ext_http - http traffic from the WWW server
# www_ext_misc - all non-http traffic from the WWW server
# boss_ext - traffic coming from the boss's computer
queue std_ext cbq(default)
queue www_ext bandwidth 500Kb { www_ext_http, www_ext_misc }
queue www_ext_http priority 3 cbq(red)
queue www_ext_misc priority 1
queue boss_ext priority 3
# enable queueing on the internal interface to control traffic coming
# from the Internet or the DMZ. use the cbq scheduler to control the
# bandwidth of each queue. bandwidth on this interface is set to the
# maximum. traffic coming from the DMZ will be able to use all of this
# bandwidth while traffic coming from the Internet will be limited to
# 1.0Mbps (because 0.5Mbps (500Kbps) is being allocated to fxp1).
altq on dc0 cbq bandwidth 100% queue { net_int, www_int }
# define the parameters for the child queues.
# net_int - container queue for traffic from the Internet. bandwidth
# is 1.0Mbps.
# std_int - the standard queue. also the default queue for outgoing
# traffic on dc0.
# it_int - traffic to the IT Dept network.
# boss_int - traffic to the boss's PC.
# www_int - traffic from the WWW server in the DMZ.
queue net_int bandwidth 1.0Mb { std_int, it_int, boss_int }
queue std_int cbq(default)
queue it_int bandwidth 500Kb cbq(borrow)
queue boss_int priority 3
queue www_int cbq(red)
# enable queueing on the DMZ interface to control traffic destined for
# the WWW server. cbq will be used on this interface since detailed
# control of bandwidth is necessary. bandwidth on this interface is set
# to the maximum. traffic from the internal network will be able to use
# all of this bandwidth while traffic from the Internet will be limited
# to 500Kbps.
altq on fxp1 cbq bandwidth 100% queue { internal_dmz, net_dmz }
# define the parameters for the child queues.
# internal_dmz - traffic from the internal network.
# net_dmz - container queue for traffic from the Internet.
# net_dmz_http - http traffic.
# net_dmz_misc - all non-http traffic. this is also the default queue.
queue internal_dmz # no special settings needed
queue net_dmz bandwidth 500Kb { net_dmz_http, net_dmz_misc }
queue net_dmz_http priority 3 cbq(red)
queue net_dmz_misc priority 1 cbq(default)
# ... in the filtering section of pf.conf ...
main_net = "192.168.0.0/24"
it_net = "192.168.1.0/24"
int_nets = "{ 192.168.0.0/24, 192.168.1.0/24 }"
dmz_net = "10.0.0.0/24"
boss = "192.168.0.200"
wwwserv = "10.0.0.100"
# default deny
block on { fxp0, fxp1, dc0 } all
# filter rules for fxp0 inbound
pass in on fxp0 proto tcp from any to $wwwserv port { 21, \
> 49151 } flags S/SA keep state queue www_ext_misc
pass in on fxp0 proto tcp from any to $wwwserv port 80 \
flags S/SA keep state queue www_ext_http
# filter rules for fxp0 outbound
pass out on fxp0 from $int_nets to any keep state
pass out on fxp0 from $boss to any keep state queue boss_ext
# filter rules for dc0 inbound
pass in on dc0 from $int_nets to any keep state
pass in on dc0 from $it_net to any queue it_int
pass in on dc0 from $boss to any queue boss_int
pass in on dc0 proto tcp from $int_nets to $wwwserv port { 21, 80, \
> 49151 } flags S/SA keep state queue www_int
# filter rules for dc0 outbound
pass out on dc0 from dc0 to $int_nets
# filter rules for fxp1 inbound
pass in on fxp1 proto { tcp, udp } from $wwwserv to any port 53 \
keep state
# filter rules for fxp1 outbound
pass out on fxp1 proto tcp from any to $wwwserv port { 21, \
> 49151 } flags S/SA keep state queue net_dmz_misc
pass out on fxp1 proto tcp from any to $wwwserv port 80 \
flags S/SA keep state queue net_dmz_http
pass out on fxp1 proto tcp from $int_nets to $wwwserv port { 80, \
21, > 49151 } flags S/SA keep state queue internal_dmz
|
|