為了使配置更容易,規(guī)則可以寫到一個文件里供ipfw處理,語法規(guī)則參照大綱欄最后一行(譯注:指本文最前面的語法部分最后一行,即:“ipfw
[-cfnNqS] [-p preproc [preproc-flags]]
pathname”)。注意必須是絕對路徑。這個文件會被逐行讀取并且將作為ipfw工具的參數(shù)處理。
作為選擇,你還可以使用-p
preproc參數(shù)來使用預(yù)處理程序,其中路徑是用管道來傳入的?梢允褂玫念A(yù)處理程序包括cpp和m4。如果preproc不是以”/“開頭,那么將搜
索PATH里的路徑。在使用它的時候,要謹(jǐn)慎,因為在很多時候,ipfw啟動時,系統(tǒng)文件可能沒有掛接(比如:文件系統(tǒng)是通過NFS掛接的)。一旦使用了
-p參數(shù),所有其它的參數(shù),都被傳送到預(yù)處理程序去等待處理。
ipfw的pipe和queue命令用來配置流量整形,你可以下面的“TRAFFIC SHAPER (DUMMYNET) CONFIGURATION”節(jié)看到看到相關(guān)內(nèi)容。
如果系統(tǒng)的world和內(nèi)核不能保持一致,ipfw的ABI將失效,以防你加入任何規(guī)則。這樣能保證你的順利地完成啟動過程。你可以利用ipfw臨時禁止的機(jī)會登錄你的網(wǎng)絡(luò),來修復(fù)你的問題。
PACKET FLOW(數(shù)據(jù)包流程)
一個數(shù)據(jù)包在幾個內(nèi)核變量的控制下,在協(xié)議棧的多個地方被防火墻檢查。這些地方和變量如下圖所示,要在頭腦中保持下圖,它對于規(guī)劃一下正確的規(guī)則集是非常重要的。
^ 到上層 V
| |
+----------->-----------+
^ V
[ip(6)_input] [ip(6)_output] net.inet(6).ip(6).fw.enable=1
| |
^ V
[ether_demux] [ether_output_frame] net.link.ether.ipfw=1
| |
+-->--[bdg_forward]-->--+ net.link.bridge.ipfw=1
^ V
| 到設(shè)備 |
如圖所示,根據(jù)數(shù)據(jù)包的源和目的,以及系統(tǒng)配置的不同,同一個數(shù)據(jù)包穿過防火墻的次數(shù)在0和4之間變化。
需要注意的是,在包通過不同棧的時候,頭會被加上或剝離,可能會導(dǎo)致這些包被檢查不到。例如:當(dāng)ipfw被ether_demux()調(diào)用的時
候,進(jìn)入的包將包括MAC頭;而當(dāng)ipfw被ip_input()或者ip6_input()調(diào)用的時候,同一個數(shù)據(jù)包的MAC頭將被剝離。
還需要注意的是:不論檢查發(fā)生在什么地方,也不論數(shù)據(jù)包源自哪里,每個數(shù)據(jù)包也整個規(guī)則進(jìn)行對照。(譯注:是整個規(guī)則集嗎?有時候只對照一部分
的時候就中止檢查)。如果一個規(guī)則包含的一些匹配模型或動作不符合某處的要求(比如:在ip_input或ip6_input處匹配MAC頭),那么匹配
模型將不會被匹配。然而,帶有not前綴操作符的匹配模型,總是可以和這些數(shù)據(jù)包相匹配。所以,如果有必要,在有很多地方可以選擇的時候,有能力的程序員
可以為寫出的規(guī)則集選擇一個合適的位置。skipto規(guī)則在這兒是非常有用的。例如:
# packets from ether_demux or bdg_forward
ipfw add 10 skipto 1000 all from any to any layer2 in
# packets from ip_input
ipfw add 10 skipto 2000 all from any to any not layer2 in
# packets from ip_output
ipfw add 10 skipto 3000 all from any to any not layer2 out
# packets from ether_output_frame
ipfw add 10 skipto 4000 all from any to any layer2 out
。▽,在這兒,沒有辦法區(qū)別ether_demux和bdg_forward)
SYNTAX(語法規(guī)則)
通常,每個關(guān)鍵字或者參數(shù)都是作為獨(dú)立的命令行參數(shù)來提供的,前后都不能有空格。關(guān)鍵字是區(qū)分大小寫的,而參數(shù)按照它們本身的含義,可以是,也可以不是區(qū)分大小寫的。(例如,udi要區(qū)分大小寫,而hostname沒有必要區(qū)分大小寫)
在ipfw2中,為了提高可讀性,可以在逗號后面加上一個空格。當(dāng)然,你也可以把整個命令(包括參數(shù))當(dāng)作一個參數(shù)來處理(譯注:就是加上雙引號,作為一個字符串放到某個命令中)。例如,以下幾種格式效果相同:
ipfw -q add deny src-ip 10.0.0.0/24,127.0.0.1/8
ipfw -q add deny src-ip 10.0.0.0/24, 127.0.0.1/8 (譯注:127前面有個空格)
RULE FORMAT(規(guī)則格式)
ipfw的規(guī)則格式如下:
[rule_number] [set set_number] [prob match_probability] action
[log [logamount number]] [altq queue] [{tag | untag} number] body
規(guī)則的 body 部分用來設(shè)定包過濾的信息,具體細(xì)節(jié)如下:
Layer-2 header fields 第二層頭段,什么時候可用
IPv4 and IPv6 Protocol TCP, UDP, ICMP, 協(xié)議等
Source and dest. addresses and ports 源和目的。地址和端口
Direction 數(shù)據(jù)包的流向,見“流量整形”一節(jié)
Transmit and receive interface 傳輸和接收界面,用名字或地址表示
Misc. IP header fields 組合IP頭字段,包括版本、服務(wù)類型、報文長度、唯一標(biāo)識、分段標(biāo)志、生存期
IP options IP選項字段
IPv6 Extension headers IPv6擴(kuò)展頭,包括分片報頭、中繼選項報頭、路由報頭、路路由選擇報頭、IP層安全服務(wù)選項、Source routing rthdr0, Mobile IPv6 rthdr2(譯注:最后兩項不知道怎么翻譯)
IPv6 Flow-ID IPv6的流量標(biāo)識
Misc. TCP header fields 組合tcp頭字段,有TCP標(biāo)志(syn,fin,ack,rst等)、序列號、回復(fù)號,窗口等。
TCP options TCP的選項
ICMP types ICMP包
ICMP6 types ICMP6包
User/group ID 本地棧所歸屬的用戶和組
Divert status 是不是源自一個divert接口(例如:natd(8))
需要注意,上面的很多信息中,比如源MAC和IP地址、TCP/UDP端口等,是比較容易偽造的,所以只對這些信息進(jìn)行過濾不能保證達(dá)到預(yù)期的效果。
rule_number
每個規(guī)則都有規(guī)則號,規(guī)則號從1-65535。65535是保留的默認(rèn)規(guī)則。ipfw將按規(guī)則號的順序依次檢查這些規(guī)則。可以有多個規(guī)則用同一
個規(guī)則號,在這種情況下,將按照它們的添加順序依次檢查或列出。如果一個規(guī)則沒有指定規(guī)則號,內(nèi)核將自動賦于一個規(guī)則號,使它成為默認(rèn)規(guī)則前的最后一個規(guī)
則(即小于65535)。自動添加的規(guī)則號有個步進(jìn)值,在不大于65535的情況下,每次添加規(guī)則時,都自動加上這一步進(jìn)值。它默認(rèn)是100,對應(yīng)于
net.inet.ip.fw.autoinc_step這個內(nèi)核變量。
set set_number
每個規(guī)則都對應(yīng)于一個規(guī)則集編號,規(guī)則集編號取值為:0-31。規(guī)則集可以單獨(dú)地被禁止或啟用,所以,它對于規(guī)則集的原子操作是
至關(guān)重要的。它還可以輕松地刪除掉一組規(guī)則。如果一個規(guī)則沒有指定規(guī)則集編號,它默認(rèn)的規(guī)則集編號就是0。規(guī)則集編號31是個特殊的規(guī)則集,它不能被禁
止,也不能用ipfw的flush命令刪除,它是默認(rèn)規(guī)則的規(guī)則集。規(guī)則集編號31可以用ipfw delete set
31命令刪除。(譯注:這在遠(yuǎn)程調(diào)試排斥式防火墻時特別有用,防止把自己鎖在外面。)
prob match_probability
這個語句只用來指定可能性(從0到1之間浮點(diǎn)值)。這在很多隨機(jī)丟包的應(yīng)用中,或者(在同dummynet聯(lián)用的情況下)模擬多路徑條件下無序包傳遞的效果中,是非常有用的。
注意:在檢查時,這個條件比其它所有條件都先被檢查,包括會有副作用的keep-state或者check-state。
log [logamount number]
當(dāng)一個包匹配到一個有l(wèi)og關(guān)鍵字的規(guī)則時,一條消息會被syslogd記錄到一個LOG_SECURITY設(shè)備中。記錄動作只會在同時滿足下
面兩個條件時才發(fā)生:1、內(nèi)核選項net.inet.ip.fw.verbose等于1(當(dāng)編譯內(nèi)核時帶著IPFIREWALL_VERBOSE參數(shù)時,
這是默認(rèn)值);2、所記錄的包數(shù)量還達(dá)不到logamount
number所指定的數(shù)量。如果沒有指定logamuont,則記錄的包的上限受內(nèi)核變量net.inet.ip.fw.verbose_limit的限
制。在這兩種情況中,logamount取值為零時,則取消記錄數(shù)量的限制。
當(dāng)記錄數(shù)量達(dá)到上限時,可以通過重置記錄計數(shù)器或包計數(shù)器的方式再重新開始記錄。詳細(xì)情況請查看resetlog命令。
注意:記錄的時間是在所有的包檢測條件都完成之后,并且在采取相應(yīng)的動作(接受、拒絕等)之前。
tag number
當(dāng)一個包和一個帶有tag關(guān)鍵字的規(guī)則相匹配時,一個指定的數(shù)字標(biāo)簽就被附加到這個包上,數(shù)字標(biāo)簽的范圍是1-65534。這個標(biāo)簽作為一個內(nèi)
部的記號(它不會從線路上發(fā)送出去),以便后來可以區(qū)分這些數(shù)據(jù)包。這有時候非常有用,比如:提供接口之間相互信任和開啟一個基于安全的過濾。一個包可以
同時有多個標(biāo)簽。標(biāo)簽是“頑固的”,意思就是只要標(biāo)簽被應(yīng)用到某個數(shù)據(jù)包上,那么它就一直存在,直到被明確地解除為止。這個標(biāo)簽在內(nèi)核中一直存在,但是一
旦數(shù)據(jù)包離開內(nèi)核,標(biāo)簽就會消失。例如:在當(dāng)把數(shù)據(jù)包發(fā)送到網(wǎng)絡(luò)或者發(fā)送到divert棧時,標(biāo)簽就會消失。
要檢查已經(jīng)存在的標(biāo)簽,可以用tagged規(guī)則選項,要刪除存在的標(biāo)簽,用untag關(guān)鍵字。
注意:既然標(biāo)簽是在內(nèi)核空間內(nèi)一直存在的,所以它們就可以被內(nèi)核的網(wǎng)絡(luò)子系統(tǒng)(使用mbuf_tags設(shè)備)設(shè)置或者是取消,而不僅僅依靠
ipfw的 tag和untag關(guān)鍵字。例如:可以存在一個netgraph(4)節(jié)點(diǎn)做流量分析,并且給數(shù)據(jù)包打上標(biāo)簽,以供后面的防火墻進(jìn)行檢查。
untag number
不可到達(dá)的同義詞。
reset
丟掉和本規(guī)則相匹配的數(shù)據(jù)包,如果是一個TCP數(shù)據(jù)包,則發(fā)送一個重置(RST)消息。搜索中止。
reset6
丟掉和本規(guī)則相匹配的數(shù)據(jù)包,如果是一個TCP數(shù)據(jù)包,則發(fā)送一個重置(RST)消息。搜索中止。
skipto number
跳到指定的規(guī)則,忽略掉比指定規(guī)則號小的規(guī)則。搜索從指定的規(guī)則號繼續(xù)。
tee port
將相匹配的數(shù)據(jù)包復(fù)制一份到divert(4)所綁定的端口。搜索繼續(xù)。
unreach code
丟棄和本規(guī)則相匹配的包,并且嘗試發(fā)送一條編號為指定編號的不可到達(dá)的ICMP消息。編號范圍是0-255,或者使用下列別名之一:net,
host, protocol, port, needfrag, srcfail, net-unknown,host-unknown,
isolated,net-prohib, host-prohib, tosnet, toshost,
filter-prohib,host-precedence or precedence-cutoff。搜索中止。
unreach6 code
丟棄和本規(guī)則相匹配的包,并且嘗試發(fā)送一條編號為指定編號的不可到達(dá)的ICMPv6消息。編號為0,1,3,4或者是下列別名之一:no-route, admin-prohib, address or port。搜索中止。
netgraph cookie
使用指定的cookie把數(shù)據(jù)包轉(zhuǎn)向到netgraph。搜索中止。如果稍后數(shù)據(jù)包眾netgraph返回,則受內(nèi)核變量net.inet.ip.fw.one_pass的影響,或者被接受,或者從下一條規(guī)則繼續(xù)。
ngtee cookie
將數(shù)據(jù)包復(fù)制一份,轉(zhuǎn)發(fā)到netgraph,原始的數(shù)據(jù)包則受net.inet.ip.fw.one_pass的影響,或者被接受,或者從下一條規(guī)則繼續(xù)。查看ng_ipfw(4)可以獲取更多關(guān)于netgraph和ngtee動作的信息。
RULE BODY(規(guī)則體)
規(guī)則體包括零個或多個匹配模式(比如指定源和目的的地址或端口,協(xié)議選項,進(jìn)入和流出的界面等。),這些匹配模式必須按順序?qū)?shù)據(jù)包進(jìn)行識別。
通常,匹配模式之間用一個隱含的“和”操作連接,比如:所有規(guī)則中的模型都必須去和數(shù)據(jù)包進(jìn)行匹配。單個的模型可以使用“not”操作符作為前綴,用來表
示相反的匹配結(jié)果,就象在下例中:
ipfw add 100 allow ip from not 1.2.3.4 to any
特別的,當(dāng)用來表示二選一的“或”模型時,可以使用一對小括號“()”或一對大括號“{}”括起來的“or”操作符,比如:
ipfw add 100 allow ip from { x or not y or z } to any
只允許有一級小括號。特別提示:大多數(shù)shell中,小括號和大括號都有特殊的意義,所以,為了防止被shell誤解,強(qiáng)烈建議在小括號和大括號前加上反斜杠“\”。
規(guī)則體中,至少要包含一個源地址和目的地址的語句!盿ny”關(guān)鍵字可以用在多種地方,用來表明源或目標(biāo)可以是任意的。
規(guī)則體的格式如下:
[proto from src to dst] [options]
第一個部分(proto from src to dst)用來和早期版本的FreeBSD相兼容。在新的FreeBSD版本中,所有的匹配模型(包括MAC頭,IP協(xié)議,地址和端口)都可以在options里指定。
各規(guī)則字段的含義如下:
proto: protocol | { protocol or ... }
protocol:[not] protocol-name | protocol-number