可以在规则中使用附加的可选匹配模式。在规则中,可以没有,也可以有多个选项,它们可以在前面加上not运算符,也可以用or来连接。 可以使用的选项如下所示(按照字母顺序):
这是一个注释 在一个规则中插入一段文字作为注释。在后面所有的东西都被作为注释来处理。你可以使用只有注释的规则,它将只有一个count动作。
bridged layer2的别名
diverted 只和一个转发界面产生的数据包相匹配。
diverted-loopback 只匹配于从divert堆栈重新回到IP堆栈的进入的数据包。
diverted-output 只匹配于从divert堆栈重新回到IP堆栈的向外发送的数据包。
dst-ip ip-address 和目的地址是参数中指定的IPv4地址之一的数据包相匹配。
{dst-ip6 | dst-ipv6} ip6-address
和目的地址是参数中指定的IPv6地址之一的数据包相匹配。
dst-port ports 和目的端口是参数中指定端口之一的数据包相匹配。
established 和设置了RST和ACK位的TCP数据包相匹配。
ext6hdr header
匹配于IPv6包的扩展头中包括参数指定的报头的数据包。可用的报头包括:
Fragment, (frag), Hop-to-hop options (hopopt), any type of Rout-
ing Header (route), Source routing Routing Header Type 0
(rthdr0), Mobile IPv6 Routing Header Type 2 (rthdr2), Destination
options (dstopt), IPSec authentication headers (ah), and IPSec
encapsulated security payload headers (esp).
flow-id labels
匹配于包含指定流量标签的IPv6数据包。labels是一个用逗号隔开的流量标签号列表。
frag
匹配于IP报文中,不是第一个段的分段。需要注意的是这些数据包不存在下一个协议头(例如:TCP,UDP),所以任何于协议头相关的选项,都不会和它们相匹配。
gid group
如果发接收或传输的TCP或UDP数据包隶属于该指定组group,则匹配。一个group可以用名称,也可以用代号。(译注:group为系统中的组,下面还有uid,指的是user id。)
jail prisonID
匹配于所有发送自或发往被囚禁的TCP或UDP包,囚禁标识用prisonID给出。
icmptypes types
匹配于指定列表中的icmp类型的包。类型列表可以是单种类型的任意组合,用逗号隔开。不支持范围。支持的单个类型如下:
echo reply (0), destination unreachable (3), source quench (4),
redirect (5), echo request (8), router advertisement (9), router
solicitation (10), time-to-live exceeded (11), IP header bad
(12), timestamp request (13), timestamp reply (14), information
request (15), information reply (16), address mask request (17)
and address mask reply (18).
icmp6types types
匹配于指定列表中的icmp6类型的包。类型列表可以是单种类型的任意组合,用逗号隔开。不支持范围。支持的单个类型如下:
in | out
分别匹配于进入或流出的数据包。in和out是互斥的(实际上,out就是指不是in)。
ipid id-list
仅对IPv4数据包有效。匹配于ip_id字段为指定id-list列表中数值的包。id-list的规则和port一样,可以是单个的数字,也可以是一个列表,还可以是一个范围。
iplen len-list
仅对IPv4数据包有效。匹配于所有长度为指定len-list列表中数值的包,长度值括头和数据。len-list的规则和port一样,可以是单个的数字,也可以是一个列表,还可以是一个范围。
ipoptions spec
仅对IPv4数据包有效,如果在头中的IP选项中,包含spec参数列表中指定的选项,则匹配。spec参数列表可以用逗号隔开。可以使用的IP选项如下:
ssrr(严格源路由)、lsrr(宽松源路由)、rr(记录包路由)、和ts(时间戳)。可以用叹号'!'表示没有这个选项。
ipprecedence precedence
仅对IPv4数据包有效,如果优先级字段的值和指定的precedence相同,则匹配。
ipsec
匹配于曾经和IPSEC相关的包。(例如:内核存在选项IPSEC和IPSEC_FILTERTUNNEL选项时,在IPSEC中,被加密的包和正确解密的包。)
提示:这地方的ipsec和后面将提到的ipsec不同,ipsec协议将只检查IP的协议字段,而不管内核是不是支持,也不管IPSEC数据是否有效。
还需要注意:如果内核没有IPSEC支持,这个标识将被忽略而不给出任何消息。在处理规则的时候,就像ipsec不存在一样,不会影响对其它关键字的处理。
iptos spec
对于IPv4包,如果tos字段包含spec列表中指定的值,则匹配。支持的IP服务格式为:
lowdelay (IPTOS_LOWDELAY), throughput (IPTOS_THROUGHPUT),
reliability (IPTOS_RELIABILITY), mincost (IPTOS_MINCOST),
congestion (IPTOS_CE). The absence of a particular type may be
denoted with a `!'.
最小延迟(IPTOS_LOWDELAY),最大呑吐量 (IPTOS_THROUGHPUT),
最高可靠性 (IPTOS_RELIABILITY), 最低费用 (IPTOS_MINCOST),
拥挤?? (IPTOS_CE)。可以用叹号“!”来表示没有这个选项。(译注:congestion(IPTOS_CE):没找到资料)
ipttl ttl-list
仅对IPv4数据包有效,如果它的生存时间包含在ttl-list中,则匹配。ttl-list同ports列表一样,既可以是一个单独的值,也可以是一个列表或一个范围,还可以是服务名称。
ipversion ver
匹配于IP版本字段等于指定的ver的数据包。
keep-state
如果匹配,防火墙将创建一个动态规则,它的默认动作是匹配在源和目的的IP/port之间,使用同一协议的双向流量。动态规则有一定的生存期(受一系列内核变量的控制),生存时间在每遇到匹配的包时,都进行刷新。
layer2
仅匹配第二层的包。例如:从ether_demux()和ether_output_frame()来,通过ipfw的包。
limit {src-addr | src-port | dst-addr | dst-port} N
在规则指定的相同参数下,防火墙只允许N个连接。可以指定至少一个源地址和目的地址。目前,仅支持IPv4。
{ MAC | mac } dst-mac src-mac
匹配于指定的dst-mac和src-mac地址。可以用any来表示所有的MAC地址,或者用冒号分开的6组16进制的数字,还可以在后面指定有效位数。掩码位数的指定方法有如下两种:
1、用斜杠“/”后跟随着有效位数的方法。例如,要指定33位的有效地址,可以用:
MAC 10:20:30:40:50:60/33 any
2、 用逻辑和符号“&”跟随一个6组用冒号隔开的位掩码,例如:一个最后16位为有效位的地址:
MAC 10:20:30:40:50:60&00:00:00:00:ff:ff any
需要注意“&”符号在许多shell中有特殊意义,所以在用的时候,通常需要进行转义处理。
注:源MAC地址和目的MAC地址可以互换,但是IP地址是不可以的。(译注:没读懂)
mac-type
如果数据包中,以太网类型字段中的值等于参数mac-type指定值中的一个,则匹配。mac-type的指定方式同ports(例如:单一的值,范围等)。对于vlan,ipv4,ipv6之类的已知类型,可以用符号名称来表示。 mac-type的值可以采用十进制或十六进制(以0x开头),但是在打印的时候,只输出16进制(除非使用-N选项来尝试解析符号名称)。
proto protocol
匹配于指定protocol协议的包。
recv | xmit | via {ifX | if* | ipno | any}
匹配于接收、传输或者通过某个界面的数据包。界面可以是一个网卡名称(ifx),或者设备名(if*),或者是IP地址,或者是其它界面。 via关键字使防火墙检查通过某个界面的所有数据包。如果是recv或xmit代替了via,则只在界面上检查相应的接收或传输方向的数据包。如果同时指定了两个,则也同时检查接收至界面和传输出界面的数据包。例如:
ipfw add deny ip from any to any out recv ed0 xmit ed1
recv也可检查某界面上流出或注入的数据包,但是xmit只能检查某界面上流出的数据包。所以,在使用xmit的时候,必须同时指定out。
一个数据包可以没有接收或传输界面:源自本地主机的数据包没有接收界面,目的为本地主机的数据包没有传输界面。(译注:为了好理解,recieve意思为接收自,xmit意思为传输至)
setup
匹配于设置了SYN位,而没有设置ACK位的TCP包。这就是“'tcpflags syn,!ack'”的缩写。(译注:注意引号当中有个单引号)
src-ip ip-address
仅对IPv4数据包有效,匹配于源IP是参数ip-address中指定地址之一的包。
src-ip6 ip6-address
仅对IPv6数据包有效,匹配于源IP是参数ip-address中指定地址之一的包。
src-port ports
匹配于源端口是参数ports中指定端口之一的包。
tagged tag-list
如果数据包的tags包含在参数tag-list中,则匹配。tag-list格式和ports一样,可以是一个单一的值,也可以是一个列表或范围。tags是用来给规则打标签的一个参数。(具体情况可以参见tags参数)
tcpack ack
仅对TCP包有效。如果TCP包的头部设置了ACK字段,则匹配。
tcpdatalen tcpdatalen-list
对于TCP数据包,如果TCP的长度是参数tcpdatalen-list中的一个,则匹配。tcpdatalen-list的规则同ports一样,可以是一个单一的值,也可以是一个列表或范围。
tcpflags spec
仅对TCP包有效。如果TCP的头部包含参数spec中指定的值,则匹配。spec是一个用逗号隔开的一个标志列表。支持的TCP标志有:
fin,syn,rst,psh,ack和urg。可以在前面加上叹号:“!”取反。包含tcpflags的规则可能永远都不会匹配于一个非零偏移的分段包。详情可以参看frag选项。
tcpseq seq
仅对TCP包有效。如果TCP头部的序列号(sequece)字段为参数seq指定的值,则匹配。
tcpwin win
仅对TCP包有效。如果TCP头部的窗口(window)字段为参数win指定的值,则匹配。
tcpoptions spec
仅对TCP包有效。如果TCP头部的选项字段(option)为参数指定的spec,则匹配。支持的TCP选项(option)有:
mss (最大分段长度), window (tcp窗口大小建议), sack (选择性的ack), ts (rfc1323 时间戳) and cc (rfc1644 t/tcp 连接计数)。可以用前置的叹号“!”来表示取反。(译注:sack表示选择性的ack,常用来乱序传输TCP数据,它可以用来查找特定的遗失的数据报,所以可以快速恢复状态)
uid user
如果发出或接收的tcp或UDP数据包隶属于参数user指定用户,则匹配。user可以是用户名,也可以是用户的序号。
verrevpath
对于进入的数据包,将对包的源地址路由表进行检查。如果包进入系统的界面和包路由流出的界面相同(译注:也就是数据包的路由界面正确),则匹配。否则是不匹配。所有流出的包和没有流入界面的包,都匹配。
这个选项的名称和功能都和思科的IOS命令类似:
ip verify unicast reverse-path
这个选项可以用制作anti-spoofing(反欺骗)规则,来防止源地址来自不正确的界面。还可以阅读antispoof选项。
versrcreach
对于进入的数据包,将对包的源地址路由表进行检查。如果对于源地址的路由存在,但是不是默认的路由或黑洞/拒绝路由,则匹配。否则不匹配。所有流出的包都匹配。 这个选项的名称和功能都和思科的IOS命令类似:
ip verify unicast source reachable-via any
这个选项可以用来制作anti-spoofing(反欺骗)规则,来阻止所有源地址不可到达的包。(注:这段不是很懂)
对于进入的数据包,则检查源地址是不是属于一个直接连接的网络。如果来自直接连接的网络,则数据包的流入界面和连接的网络进行对比。如果源地址的界面和直接连接的网络界面不一致,则不匹配。否则匹配。所有流出的包都匹配。
这个选项常用来制作anti-spoofing(反欺骗)规则,用来阻止试图进入直接连接的网络,但是不是通过那个界面。这个选项和verrevpath相似,但是比它范围窄一些,因为它只检查来自直接连接网络的数据包,而verrevpath检查所有流入的包。
ipfw同时也是流量整形工具(dummynet)的用户界面。 dummynet先用ipfw防火墙选出所需的数据包,然后再将这些包分成不同的流量。在数据包选择的过程中,可以利用所有的ipfw参数。根据本地规则的不同,一个流量含有的数据包可以属于一个TCP连接,也可以属于指定的源/目的主机、也可以属于整个子网络、还可以属于某一种协议等。
同一个流量下的数据包将通过下面两种对象之一,这两种对象是实现流量管理的基本要素。
pipe 一个管道用来模拟一个给定带宽、延迟、队列大小和丢包率的连接。当数据包从防火墙中分类以后,就进入管道的头部,然后根据管道的配置再通过管道。
queue 一个队列就是一个WF2Q+(Worst-case Fair Weighted Fair Queueing,译注:没找到中文翻译)策略的实现,WF2Q+是一个对WFQ的改进策略。 每个队列都对应于一个weight和一个相关的pipe流量。所有和一个pipe相关的存积的流量(例如,在队列中的数据包),将根据每个队列 weight的比例,来共同分享pipe所指定的带宽。需要注意:weight并不是优先级。虽然在有较高weight流量的数据包积压的时候,一个有较低weight的流量依然能保证分享到一定的带宽。(译注:好象这就是WFQ)
实际上,pipe用来实施带宽的限制,而queues则用来决定不同的流量怎么样来分享这些带宽。(译注:这是流量整形中最难理解的部分,本人费了近两天的时间才搞清楚这些关系。)
pipe和queue配置可用的命令格式如下:
pipe number config pipe-configuration
queue number config pipe-configuration
pipe专用的参数如下:
bw bandwidth | device
Bandwidth, 单位为: [K|M]{bit/s|Byte/s}.
如果设置为0,则是没有带宽限制。这些单位必须紧跟在数字后面。(译注:也就是不能有空格之类的东西。)就如下例一样:
ipfw pipe 1 config bw 300Kbit/s
如果用一个设备名来代替上面的数值,如:
ipfw pipe 1 config bw tun0
那么,这种设备将提供传输时钟,到目前为止,只有在ppp上跑的tun(4)设备才有这种能力。
delay ms-delay
传播延迟是以毫秒为单位的。实际上,这个值近似等于一个时钟嘀嗒(典型的是10ms,但是,建议在内核配置中,使选项HZ=1000,这样可以将其减少到1ms或更少)的倍数,默认为0时,表示没有延迟。(译注:clock tick是计算机中,时间的最小单位。本人理解不一定正确:括号的内容说的就是clock tick,而不是指延迟的单位。)
queue专用参数如下:
pipe pipe_nr
将一个队列queue连接到一个指定的管道pipe。多个具有不同weight值的队列可以连接到同一个管道,这些队列将共用一个pipe指定的带宽。
weight weight
指定一个weight值,用在匹配这个队列的流量上。weight的范围是1-100,默认为1。
最后,下面的参数,可以用在pipe和queue中:
buckets hash-table-size
指定用来存储队列的哈希表的大小。默认是64,范围是16-65536。可以用内核变量net.inet.ip.dummynet.hash_size来调整这个值。
mask mask-specifier
从ipfw规则送到pipe或queue的数据包可以再进一步划分成多个流量,每个流量都有一个动态的pipe或者queue。这些流量的分类标识,是在 pipe或queue的配置中,用IP地址、端口号和协议的掩码组合来区分(译注:是“和”,不是“或”)。对于不同的流量标识,将自动创建一个新的 pipe或queue,参数和原始的对象一样,用来匹配后来发到pipe或queue的数据包。
这样,当用动态管道pipe的时候,每个流量将使用和原始的管道相同的流量,然而,对于动态的队列queue来说,每个流量去共同分享原始的queue所相关的那个pipe流量。可以用下列掩码格式的组合:
dst-ip mask, dst-ip6 mask, src-ip mask, src-ip6 mask, dst-port
mask, src-port mask, flow-id mask, proto mask , all,
all的意思指的是所有的位。
noerror
当一个包被dummynet的队列或管道丢弃的时候,将在内核中产生一个错误,来通知调用例程。当一个队列设备满了的时候,也会产生一个这样的错误。如果设置了这个参数,则在成功的传输数据包之后,将报告调用例程,这对于一些专业的,模拟远程路由上的丢失或堵塞的实验,是很有用的。
plr packet-loss-rate
丢包率。参数packet-loss-rate是一个界于0和1之间的浮点数,为0时,表示不丢包,为1时表示全丢。丢包率在内部用第31位表示。(译注:不是很明白,也许是表示默认值为31)
queue {slots | sizeKbytes}
队列的长度,用槽(slot)或size(Kbytes)表示。默认是50槽,这个数值正是以太网典型的队列大小。注意,对于慢速的连接,必须使这个值小,否则将会导致严重的队列延迟。比如:在一个管道为30Kbit/s的队列中,50个以太网最大长度的包,即总长度为600Kbit,将会现 20秒的延迟。(译注:翻译这句查了很多资料,结果网上大多数的资料都把人引入一个岐途,让人越看越不明白。实际上这句是警告我们:在限速的时候,如果限制的速度比较小,那么就要注意队列长度别太大。) 如果在某个界面上的数据包长度大于MTU,比如说在一个本地回路上出现16KB的包,那将是更糟糕的。(译注:还没有测试到底能糟糕到什么程度,老外说话,有时候比较幽默。)
red | gred w_q/min_th/max_th/max_p
启用RED(Random Early Detection)队列算法机制。w_q和max_p是界于0和1(不包含1)之间的浮点数,min_th和max_th是一个表示队列管理的阈值的整数(如果队列用字节定义,则阈值用字节表示,否则用槽表示)。dummynet(4)也支持gentle RED(gred)。有三个内核变量可以用来控制RED:
net.inet.ip.dummynet.red_lookup_depth
在连接空闲时,用来指定计算队列的平均命中率。(默认为256,必须大于0)(译注:对RED不懂,只能从字面翻译)
net.inet.ip.dummynet.red_avg_pkt_size
指定期望有数据包的平均大小。(默认为512,必须大于0)
net.inet.ip.dummynet.red_max_pkt_size
定义期望的数据包的最大值,仅当queue阈值用字节表示的时候才能使用(默认为1500,必须 大于0)
对于IPv6的数据包,dummynet还有许多限制。必须注意的一个,送到某个界面的link-local数据包经过dummynet后,就不可用了,因为在外部的路径中就被丢弃掉了。所在要记住,link-local数据包不会通过dummynet。(译注:link-local数据包是IPv6中定义的一个本地地址,用在自动配置、没有路由的链接中等。)