Chinaunix首页 | 论坛 | 博客
  • 博客访问: 58898
  • 博文数量: 11
  • 博客积分: 687
  • 博客等级: 上士
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-10 10:56
文章分类
文章存档

2011年(1)

2010年(10)

分类: BSD

2010-01-11 19:42:23

  可以在规则中使用附加的可选匹配模式。在规则中,可以没有,也可以有多个选项,它们可以在前面加上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检查所有流入的包。

  Lookup 表常用来处理大量的分散的地址集,特别是成千上万个地址。可以使用高达128个不同的lookup项目,编号从0-127。

  每个项目格式为:addr[/masklen],将匹配于所有基地址相同(表示为一个IP地址或一个主机名)和掩码位数相同的地址(表示为一个IP地址或一个主机名)。如果掩码位数没指定,则默认为32。当在一个表中查寻一个IP地址的时候,将匹配一个最精确的项目。每个项目都有一个与之相关的32位无符号值,规则匹配代码可以使用它地进行检查。如果在添加规则时没有指定这个值,则默认为0。

  一个项目可以被添加进一个表(add),或者从一个表中删除(delete),或者列出一个表的项目(list),还可以被清除(flush)。

   每个表在内部存储时,使用和路由表相同的基数树方式。可以参考route(4)
  
Lookup表现在只支持IPv4。
  
tablerg提供了一个功能,它可以用在规则规则的动作、规则的参数或规则的选项中,使防火墙在表中寻找一个指定的值。
   当然后fwd的时候,可以使用IP地址或主机名的格式来指定一个表的项目。可以参考示例章节的“使用表和tablearg关键字”。

  每个规则都属于32个不同规则集中的一个,规则集编号从0到31。规则集编号31是为默认规则保留的。

  默认情况下,在添加一个新的规则时,除非指定set N属性,否则规则将被放入规则集0中。规则集可以被独立地和原子性地被启用或禁止,所以,这个方法提供了一个配置防火墙和切换规则的快速的简易的方法。启用或禁止规则集的方法是:

         ipfw set [disable number ...] [enable number ...]

  在上面的书写格式中,可以指定多个enable或disable。在命令中指定的每一个规则集,都会被单独处理。默认所有的规则集都是启用的。

   当你禁止一个规则集时,除了一个特殊的情况之外,它的所有规则就像是在防火墙配置里不存在一样:

  在规则被禁止之前创建的动态规则,会一直保持住,直到过期为止。如果你想删除掉一个动态规则,你必须明确地删除创建它的父规则。

  规则集号可以用move来改变。

         ipfw set move {rule rule-number | old-set} to new-set

  并且,还可以交换两个规则集:

         ipfw set swap first-set second-set

  查看“示例”章节可以了解更多关于规则集的规则。

  
状态保持使防火墙可以在遇到匹配的指定数据包时,动态地创建一条相关的规则。支持动态规则的操作符有:check-state,keep-state和limit。

当一个数据包匹配于keep-state或limit规则时,将自动创建一个动态规则。可以匹配于所有的指定协议下的,基于同一个源IP/源端口、目的 IP/目的端口的地址对的数据包。(源和目的在这儿仅表示第一次匹配的地址,但是他们对于后面的数据包来说,是完全等价的)。动态规则在第一次遇到 check-state、keep-state或limit时被检查,动作也它父规则中的动作相同。
  提示:在动态规则中,只检查协议、IP地址、端口,不再检查其它的附加属性。(译注:比如TOS等)

  动态规则的一个典型应用,是在一个关闭的防火墙中,内部网络的第一个包TCP SYN通过时动态创建一个规则,就可以使以后的双向流量中,该次会话所有的数据包都通过,而不会被防火墙拒绝。

         ipfw add check-state
ipfw add allow tcp from my-subnet to any setup keep-state
ipfw add deny tcp from any to any

  一个近似的目的是有知UDP上,从内部网络的第一个UDP包可以创建一个动态规则,以便让后面的数据包通过防火墙。

         ipfw add check-state
ipfw add allow udp from my-subnet to any keep-state
ipfw add deny udp from any to any

  动态规则在一定的时间内将过期,这依赖于流量的状态和某些内核变量的控制。查看SYSCTL VARIABLES,以获取更多的细节。对于TCP会话来说,动态规则在临近失效时,可以发送一个keeplive包,来刷新这个状态。

 
在“示例”章节,有更多的如何使用动态规则的示例。

    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中定义的一个本地地址,用在自动配置、没有路由的链接中等。)
   Here are some important points to consider when designing your rules:

在规划你的规则的时候,要注意几点:
  1、记住要过滤in和out两个方向上的数据包,大多数的数据包都需要在两个方向上过滤。

  2、作测试时要小心,最好在控制台前做测试。如果不能在控制台前,一定要做好回溯的脚本,可以参考:/usr/share/examples/ipfw/change_rules.sh.

  3、不要忘记了本地回路。(译注:127.0.0.1)

  1、在多种情况下,分段的报文会被无条件地丢弃。头部小于20字节的TCP包,头部小于8字节的UDP包、头部小于4字节的ICMP包,都将被丢弃。这些包将会被记录为“pullup failed”,因为这些包中是不完整的。

  2、分段偏移量为1的TCP包将被无条件丢弃。这是一个有效的包,但是只有一个用途,就是去绕过防火墙。如果开启了日志功能的话,将报告被负1(-1)规则丢弃。

  3、如果你通过一个网络接入到系统,并且要执行kld来挂接ipfw模拟时,可能会出现问题。(译注:因为默认的ipfw规则是deny all。)建议命令如下:   

         kldload ipfw && \
ipfw add 32000 allow ip from any to any

   同样,执行下面的操作也是非常愚蠢的。(译注:因为flush命令要求本地确认,远程无法确认。所以最好用ipfw -q flush,这样就不要求确认了。)

         ipfw flush

  4、如果security level大于3的时候,防火墙规则将不能更改。(关于security level,参见init(8))

 原文地址
阅读(4367) | 评论(0) | 转发(0) |
0

上一篇:ipfw 中文手册(1)

下一篇:PF防火墙详解

给主人留下些什么吧!~~