IPFIREWALL (IPFW) 是一個由 FreeBSD 發(fā)起的防火墻應用軟件, 它由 FreeBSD 的志愿者成員編寫和維護。 它使用了傳統(tǒng)的無狀態(tài)規(guī)則和規(guī)則編寫方式, 以期達到簡單狀態(tài)邏輯所期望的目標。
目前創(chuàng)新互聯已為近1000家的企業(yè)提供了網站建設、域名、網絡空間、成都網站托管、企業(yè)網站設計、雨花網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發(fā)展。標準的 FreeBSD 安裝中, IPFW 所給出的規(guī)則集樣例 (可以在 /etc/rc.firewall
和 /etc/rc.firewall6
中找到) 非常簡單, 建議不要不加修改地直接使用。 該樣例中沒有使用狀態(tài)過濾, 而該功能在大部分的配置中都是非常有用的, 因此這一節(jié)并不以系統(tǒng)自帶的樣例作為基礎。
IPFW 的無狀態(tài)規(guī)則語法, 是由一種提供復雜的選擇能力的技術支持的, 這種技術遠遠超出了一般的防火墻安裝人員的知識水平。 IPFW 是為滿足專業(yè)用戶, 以及掌握先進技術的電腦愛好者們對于高級的包選擇需求而設計的。 要完全釋放 IPFW 的規(guī)則所擁有的強大能力, 需要對不同的協議的細節(jié)有深入的了解, 并根據它們獨特的包頭信息來編寫規(guī)則。 這一級別的詳細闡述超出了這本手冊的范圍。
IPFW 由七個部分組成, 其主要組件是內核的防火墻過濾規(guī)則處理器, 及其集成的數據包記帳工具、 日志工具、 用以觸發(fā) NAT 工具的 divert
(轉發(fā)) 規(guī)則、 高級特殊用途工具、 dummynet 流量×××機制, fwd rule
轉發(fā)工具, 橋接工具, 以及 ipstealth 工具。 IPFW 支持 IPv4 和 IPv6。
IPFW 是基本的 FreeBSD 安裝的一部分, 以單獨的可加載內核模塊的形式提供。 如果在 rc.conf
中加入 firewall_enable="YES"
語句, 就會自動地加載對應的內核模塊。 除非您打算使用由它提供的 NAT 功能, 一般情況下并不需要把 IPFW 編進 FreeBSD 的內核。
如果將 firewall_enable="YES"
加入到 rc.conf
中并重新啟動系統(tǒng), 則下列信息將在啟動過程中, 以高亮的白色顯示出來:
ipfw2 initialized, divert disabled, rule-based forwarding disabled, default to deny, logging disabled
可加載內核模塊在編譯時加入了記錄日志的能力。 要啟用日志功能, 并配置詳細日志記錄的限制, 需要在 /etc/sysctl.conf
中加入一些配置。 這些設置將在重新啟動之后生效:
net.inet.ip.fw.verbose=1 net.inet.ip.fw.verbose_limit=5
把下列選項在編譯 FreeBSD 內核時就加入, 并不是啟用 IPFW 所必需的, 除非您需要使用 NAT 功能。 這里只是將這些選項作為背景知識來介紹。
options IPFIREWALL
這個選項將 IPFW 作為內核的一部分來啟用。
options IPFIREWALL_VERBOSE
這個選項將啟用記錄通過 IPFW 的匹配了包含 log
關鍵字規(guī)則的每一個包的功能。
options IPFIREWALL_VERBOSE_LIMIT=5
以每項的方式, 限制通過 syslogd(8) 記錄的包的個數。 如果在比較惡劣的環(huán)境下記錄防火墻的活動可能會需要這個選項。 它能夠避免潛在的針對 syslog 的洪水式拒絕服務***。
options IPFIREWALL_DEFAULT_TO_ACCEPT
這個選項默認地允許所有的包通過防火墻, 如果您是第一次配置防火墻, 使用這個選項將是一個不錯的主意。
options IPDIVERT
這一選項啟用 NAT 功能。
如果內核選項中沒有加入 IPFIREWALL_DEFAULT_TO_ACCEPT
, 而配置使用的規(guī)則集中也沒有明確地指定允許連接進入的規(guī)則, 默認情況下, 發(fā)到本機和從本機發(fā)出的所有包都會被阻止。
/etc/rc.conf
Options啟用防火墻:
firewall_enable="YES"
要選擇由 FreeBSD 提供的幾種防火墻類型中的一種來作為默認配置, 您需要閱讀 /etc/rc.firewall
文件并選出合適的類型, 然后在 /etc/rc.conf
中加入類似下面的配置:
firewall_type="open"
您還可以指定下列配置規(guī)則之一:
open
── 允許所有流量通過。
client
── 只保護本機。
simple
── 保護整個網絡。
closed
── 完全禁止除回環(huán)設備之外的全部 IP 流量。
UNKNOWN
── 禁止加載防火墻規(guī)則。
filename
── 到防火墻規(guī)則文件的絕對路徑。
有兩種加載自定義 ipfw 防火墻規(guī)則的方法。 其一是將變量 firewall_type
設為包含不帶 ipfw(8) 命令行選項的 防火墻規(guī)則 文件的完整路徑。 下面是一個簡單的規(guī)則集例子:
add deny in add deny out
除此之外, 也可以將 firewall_script
變量設為包含 ipfw
命令的可執(zhí)行腳本, 這樣這個腳本會在啟動時自動執(zhí)行。 與前面規(guī)則集文件等價的規(guī)則腳本如下:
ipfw
命令是在防火墻運行時, 用于在其內部規(guī)則表中手工逐條添加或刪除防火墻規(guī)則的標準工具。 這一方法的問題在于, 一旦您的關閉計算機或停機, 則所有增加或刪除或修改的規(guī)則也就丟掉了。 把所有的規(guī)則都寫到一個文件中, 并在啟動時使用這個文件來加載規(guī)則, 或一次大批量地替換防火墻規(guī)則, 那么推薦使用這里介紹的方法。
ipfw
的另一個非常實用的功能是將所有正在運行的防火墻規(guī)則顯示出來。 IPFW 的記賬機制會為每一個規(guī)則動態(tài)地創(chuàng)建計數器, 用以記錄與它們匹配的包的數量。 在測試規(guī)則的過程中, 列出規(guī)則及其計數器是了解它們是否工作正常的重要手段。
按順序列出所有的規(guī)則:
# ipfw list
列出所有的規(guī)則, 同時給出最后一次匹配的時間戳:
# ipfw -t list
列出所有的記賬信息、 匹配規(guī)則的包的數量, 以及規(guī)則本身。 第一列是規(guī)則的編號, 隨后是發(fā)出包匹配的數量, 進入包的匹配數量, 最后是規(guī)則本身。
# ipfw -a list
列出所有的動態(tài)規(guī)則和靜態(tài)規(guī)則:
# ipfw -d list
同時顯示已過期的動態(tài)規(guī)則:
# ipfw -d -e list
將計數器清零:
# ipfw zero
只把規(guī)則號為 NUM
的計數器清零:
# ipfw zero NUM
規(guī)則集是指一組編寫好的依據包的值決策允許通過或阻止 IPFW 規(guī)則。 包的雙向交換組成了一個會話交互。 防火墻規(guī)則集會作用于來自于 Internet 公網的包以及由系統(tǒng)發(fā)出來回應這些包的數據包。 每一個 TCP/IP 服務 (例如 telnet, www, 郵件等等) 都由協議預先定義了其特權 (監(jiān)聽) 端口。 發(fā)到特定服務的包會從源地址使用非特權 (高編號) 端口發(fā)出, 并發(fā)到特定服務在目的地址的對應端口。 所有這些參數 (例如: 端口和地址) 都是可以為防火墻規(guī)則所利用的, 判別是否允許服務通過的標準。
當有數據包進入防火墻時, 會從規(guī)則集里的第一個規(guī)則開始進行比較, 并自頂向下地進行匹配。 當包與某個選擇規(guī)則參數相匹配時, 將會執(zhí)行規(guī)則所定義的動作, 并停止規(guī)則集搜索。 這種策略, 通常也被稱作 “最先匹配者獲勝” 的搜索方法。 如果沒有任何與包相匹配的規(guī)則, 那么它就會根據強制的 IPFW 默認規(guī)則, 也就是 65535 號規(guī)則截獲。 一般情況下這個規(guī)則是阻止包, 而且不給出任何回應。
如果規(guī)則定義的動作是 count
、 skipto
或 tee
規(guī)則的話, 搜索會繼續(xù)。
這里所介紹的規(guī)則, 都是使用了那些包含狀態(tài)功能的, 也就是 keep state
、 limit
、 in
、 out
以及 via
選項的規(guī)則。 這是編寫明示允許防火墻規(guī)則集所需的基本框架。
在操作防火墻規(guī)則時應謹慎行事, 如果操作不當, 很容易將自己反鎖在外面。
這里所介紹的規(guī)則語法已經經過了簡化, 只包括了建立標準的明示允許防火墻規(guī)則集所必需的那些。 要了解完整的規(guī)則語法說明, 請參見 ipfw(8) 聯機手冊。
規(guī)則是由關鍵字組成的: 這些關鍵字必須以特定的順序從左到右書寫。 下面的介紹中, 關鍵字使用粗體表示。 某些關鍵字還包括了子選項, 這些子選項本身可能也是關鍵字, 有些還可以包含更多的子選項。
#
用于表示開始一段注釋。 它可以出現在一個規(guī)則的后面, 也可以獨占一行。 空行會被忽略。
CMD RULE_NUMBER ACTION LOGGING SELECTION STATEFUL
每一個新的規(guī)則都應以 add
作為前綴, 它表示將規(guī)則加入內部表。
每一條規(guī)則都與一個范圍在 1 到 65535 之間的規(guī)則編號相關聯。
每一個規(guī)則可以與下列的動作之一相關聯, 所指定的動作將在進入的數據包與規(guī)則所指定的選擇標準相匹配時執(zhí)行。
allow | accept | pass | permit
這些關鍵字都表示允許匹配規(guī)則的包通過防火墻, 并停止繼續(xù)搜索規(guī)則。
check-state
根據動態(tài)規(guī)則表檢查數據包。 如果匹配, 則執(zhí)行規(guī)則所指定的動作, 亦即生成動態(tài)規(guī)則; 否則, 轉移到下一個規(guī)則。 check-state 規(guī)則沒有選擇標準。 如果規(guī)則集中沒有 check-state 規(guī)則, 則會在第一個 keep-state 或 limit 規(guī)則處, 對動態(tài)規(guī)則表實施檢查。
deny | drop
這兩個關鍵字都表示丟棄匹配規(guī)則的包。 同時, 停止繼續(xù)搜索規(guī)則。
log
or logamount
當數據包與帶 log
關鍵字的規(guī)則匹配時, 將通過名為 SECURITY 的 facility 來把消息記錄到 syslogd(8)。 只有在記錄的次數沒有超過 logamount 參數所指定的次數時, 才會記錄日志。 如果沒有指定 logamount
, 則會以 sysctl 變量 net.inet.ip.fw.verbose_limit
所指定的限制為準。 如果將這兩種限制值之一指定為零, 則表示不作限制。 如果達到了限制數, 可以通過將規(guī)則的日志計數或包計數清零來重新啟用日志, 請參見 ipfw reset log
命令來了解細節(jié)。
日志是在所有其他匹配條件都驗證成功之后, 在針對包實施最終動作 (accept, deny) 之前進行的。 您可以自行決定哪些規(guī)則應啟用日志。
這一節(jié)所介紹的關鍵字主要用來描述檢查包的哪些屬性, 用以判斷包是否與規(guī)則相匹配。 下面是一些通用的用于匹配包特征的屬性, 它們必須按順序使用:
udp | tcp | icmp
也可以指定在 /etc/protocols
中所定義的協議。 這個值定義的是匹配的協議, 在規(guī)則中必須指定它。
from src to dst
from
和 to
關鍵字用于匹配 IP 地址。 規(guī)則中必須 同時 指定源和目的兩個參數。 如果需要匹配任意 IP 地址, 可以使用特殊關鍵字 any
。 還有一個特殊關鍵字, 即 me
, 用于匹配您的 FreeBSD 系統(tǒng)上所有網絡接口上所配置的 IP 地址, 它可以用于表達網絡上的其他計算機到防火墻 (也就是本機), 例如 from me to any
或 from any to me
或 from 0.0.0.0/0 to any
或 from any to 0.0.0.0/0
或 from 0.0.0.0 to any
或 from any to 0.0.0.0
以及 from me to 0.0.0.0
。 IP 地址可以通過 帶點的 IP 地址/掩碼長度 (CIDR 記法), 或者一個帶點的 IP 地址的形式來指定。 這是編寫規(guī)則時所必需的。 使用 net-mgmt/ipcalc port 可以用來簡化計算。 關于這個工具的更多信息, 也可參考它的主頁: http://jodies.de/ipcalc
。
port number
這個參數主要用于那些支持端口號的協議 (例如 TCP 和 UDP)。 如果要通過端口號匹配某個協議, 就必須指定這個參數。 此外, 也可以通過服務的名字 (根據 /etc/services
) 來指定服務, 這樣會比使用數字指定端口號直觀一些。
in | out
相應地, 匹配進入和發(fā)出的包。 這里的 in
和 out
都是關鍵字, 在編寫匹配規(guī)則時, 必需作為其他條件的一部分來使用。
via IF
根據指定的網絡接口的名稱精確地匹配進出的包。 這里的 via
關鍵字將使得接口名稱成為匹配過程的一部分。
setup
要匹配 TCP 會話的發(fā)起請求, 就必須使用它。
keep-state
這是一個必須使用的關鍵字。 在發(fā)生匹配時, 防火墻將創(chuàng)建一個動態(tài)規(guī)則, 其默認行為是, 匹配使用同一協議的、從源到目的 IP/端口 的雙向網絡流量。
limit {src-addr | src-port | dst-addr | dst-port}
防火墻只允許匹配規(guī)則時, 與指定的參數相同的 N
個連接。 可以指定至少一個源或目的地址及端口。 limit
和 keep-state
不能在同一規(guī)則中同時使用。 limit
提供了與 keep-state
相同的功能, 并增加了一些獨有的能力。
有狀態(tài)過濾將網絡流量當作一種雙向的包交換來處理。 它提供了一種額外的檢查能力, 用以檢測會話中的包是否來自最初的發(fā)送者, 并在遵循雙向包交換的規(guī)則進行會話。 如果包與這些規(guī)則不符, 則將自動地拒絕它們。
check-state
用來識別在 IPFW 規(guī)則集中的包是否符合動態(tài)規(guī)則機制的規(guī)則。 如果匹配, 則允許包通過, 此時防火墻將創(chuàng)建一個新的動態(tài)規(guī)則來匹配雙向交換中的下一個包。 如果不匹配, 則將繼續(xù)嘗試規(guī)則集中的下一個規(guī)則。
動態(tài)規(guī)則機制在 SYN-flood ***下是脆弱的, 因為這種情況會產生大量的動態(tài)規(guī)則, 從而耗盡資源。 為了抵抗這種***, 從 FreeBSD 中加入了一個叫做 limit
的新選項。 這個選項可以用來限制符合規(guī)則的會話允許的并發(fā)連接數。 如果動態(tài)規(guī)則表中的規(guī)則數超過 limit
的限制數量, 則包將被丟棄。
記錄日志的好處是顯而易見的: 它提供了在事后檢查所發(fā)生的狀況的方法, 例如哪些包被丟棄了, 這些包的來源和目的地, 從而為您提供找到***者所需的證據。
即使啟用了日志機制, IPFW 也不會自行生成任何規(guī)則的日志。 防火墻管理員需要指定規(guī)則集中的哪些規(guī)則應該記錄日志, 并在這些規(guī)則上增加 log
動作。 一般來說, 只有 deny 規(guī)則應記錄日志, 例如對于進入的 ICMP ping 的 deny 規(guī)則。 另外, 復制 “默認的 ipfw 終極 deny 規(guī)則”, 并加入 log
動作來作為您的規(guī)則集的最后一條規(guī)則也是很常見的用法。 這樣, 您就能看到沒有匹配任何一條規(guī)則的那些數據包。
日志是一把雙刃劍, 如果不謹慎地加以利用, 則可能會陷入過多的日志數據中, 并導致磁盤被日志塞滿。 將磁盤填滿是 DoS ***最為老套的手法之一。 由于 syslogd 除了會將日志寫入磁盤之外, 還會輸出到 root 的控制臺屏幕上, 因此有過多的日志信息是很讓人惱火的事情。
IPFIREWALL_VERBOSE_LIMIT=5
內核選項將限制同一個規(guī)則發(fā)到系統(tǒng)日志程序 syslogd(8) 的連續(xù)消息的數量。 當內核啟用了這個選項時, 某一特定規(guī)則所產生的連續(xù)消息的數量將封頂為這個數字。 一般來說, 沒有辦法從連續(xù) 200 條一模一樣的日志信息中獲取更多有用的信息。 舉例來說, 如果同一個規(guī)則產生了 5 次消息并被記錄到 syslogd, 余下的相同的消息將被計數, 并像下面這樣發(fā)給 syslogd:
last message repeated 45 times
所有記錄的數據包包消息, 默認情況下會最終寫到 /var/log/security
文件中, 后者在 /etc/syslog.conf
文件里進行了定義。
絕大多數有經驗的 IPFW 用戶會創(chuàng)建一個包含規(guī)則的文件, 并且, 按能夠以腳本形式運行的方式來書寫。 這樣做大的一個好處是, 可以大批量地刷新防火墻規(guī)則, 而無須重新啟動系統(tǒng)就能夠激活它們。 這種方法在測試新規(guī)則時會非常方便, 因為同一過程在需要時可以多次執(zhí)行。 作為腳本, 您可以使用符號替換來撰寫那些經常需要使用的值, 并用同一個符號在多個規(guī)則中反復地表達它。 下面將給出一個例子。
這個腳本使用的語法同 sh(1)、 csh(1) 以及 tcsh(1) 腳本兼容。 符號替換字段使用美元符號 $ 作為前綴。 符號字段本身并不使用 $ 前綴。 符號替換字段的值必須使用 "雙引號" 括起來。
可以使用類似下面的規(guī)則文件:
############### start of example ipfw rules script ############# # ipfw -q -f flush # Delete all rules # Set defaults oif="tun0" # out interface odns="192.0.2.11" # ISP's DNS server IP address cmd="ipfw -q add " # build rule prefix ks="keep-state" # just too lazy to key this each time $cmd 00500 check-state $cmd 00502 deny all from any to any frag $cmd 00501 deny tcp from any to any established $cmd 00600 allow tcp from any to any 80 out via $oif setup $ks $cmd 00610 allow tcp from any to $odns 53 out via $oif setup $ks $cmd 00611 allow udp from any to $odns 53 out via $oif $ks ################### End of example ipfw rules script ############
這就是所要做的全部事情了。 例子中的規(guī)則并不重要, 它們主要是用來表示如何使用符號替換。
如果把上面的例子保存到 /etc/ipfw.rules
文件中。 下面的命令來會重新加載規(guī)則。
# sh /etc/ipfw.rules
/etc/ipfw.rules
這個文件可以放到任何位置, 也可以命名為隨便什么別的名字。
也可以手工執(zhí)行下面的命令來達到類似的目的:
# ipfw -q -f flush# ipfw -q add check-state# ipfw -q add deny all from any to any frag# ipfw -q add deny tcp from any to any established# ipfw -q add allow tcp from any to any 80 out via tun0 setup keep-state# ipfw -q add allow tcp from any to 192.0.2.11 53 out via tun0 setup keep-state# ipfw -q add 00611 allow udp from any to 192.0.2.11 53 out via tun0 keep-state
以下的這組非-NAT 規(guī)則集, 是如何編寫非常安全的 '明示允許' 防火墻的一個例子。 明示允許防火墻只允許匹配了 pass 規(guī)則的包通過, 而默認阻止所有的其他數據包。 用來保護整個網段的防火墻, 至少需要有兩個網絡接口, 并且其上必須配置規(guī)則, 以便讓防火墻正常工作。
所有類 UNIX 操作系統(tǒng), 也包括 FreeBSD, 都設計為允許使用網絡接口 lo0
和 IP 地址 127.0.0.1
來完成操作系統(tǒng)內部的通訊。 防火墻必須包含一組規(guī)則, 使這些數據包能夠無障礙地收發(fā)。
接入 Internet 公網的那個網絡接口上, 應該配置授權和訪問控制, 來限制對外的訪問, 以及來自 Internet 公網的訪問。 這個接口很可能是您的用戶態(tài) PPP 接口, 例如 tun0
, 或者您接在 DSL 或電纜 modem 上的網卡。
如果有至少一個網卡接入了防火墻后的內網 LAN, 則必須為這些接口配置規(guī)則, 以便讓這些接口之間的包能夠順暢地通過。
所有的規(guī)則應被組織為三個部分, 所有應無阻礙地通過的規(guī)則, 公網的發(fā)出規(guī)則, 以及公網的接收規(guī)則。
公網接口相關的規(guī)則的順序, 應該是最經常用到的放在盡可能靠前的位置, 而最后一個規(guī)則, 則應該是阻止那個接口在那一方向上的包。
發(fā)出部分的規(guī)則只包含一些 allow
規(guī)則, 允許選定的那些唯一區(qū)分協議的端口號所指定的協議通過, 以允許訪問 Internet 公網上的這些服務。 所有的規(guī)則中都指定了 proto
、port
、 in/out
、 via
以及 keep state
這些選項。 proto tcp
規(guī)則同時指定 setup
選項, 來區(qū)分開始協議會話的包, 以觸發(fā)將包放入 keep state 規(guī)則表中的動作。
接收部分則首先阻止所有不希望的包, 這樣做有兩個不同的原因。 其一是惡意的包可能和某些允許的流量規(guī)則存在部分匹配, 而我們希望阻止, 而不是讓這些包僅僅與 allow
規(guī)則部分匹配就允許它們進入。 其二是, 已經確信要阻止的包被拒絕這件事, 往往并不是我們需要關注的, 因此只要簡單地予以阻止即可。 防火墻規(guī)則集中的每個部分的最后一條規(guī)則都是阻止并記錄包, 這有助于為逮捕***者留下法律所要求的證據。
另外一個需要注意的事情是確保系統(tǒng)對不希望的數據包不做回應。 無效的包應被丟棄和消失。 這樣, ***者便無法知道包是否到達了您的系統(tǒng)。 ***者對系統(tǒng)了解的越少, 其***的難度也就越大。 如果不知道端口號, 可以查閱 /etc/services/
或到 http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
并查找一下端口號, 以了解其用途。 另外, 您也可以在這個網頁上了解常見***所使用的端口: http://www.sans.org/security-resources/idfaq/oddports.php
。
下面是一個非-NAT 的規(guī)則集, 它是一個完整的明示允許規(guī)則集。 使用它作為您的規(guī)則集不會有什么問題。 只需把那些不需要的服務對應的 pass 規(guī)則注釋掉就可以了。 如果您在日志中看到消息, 而且不想再看到它們, 只需在接收部分增加一個一個 deny
規(guī)則。 您可能需要把 dc0
改為接入公網的接口的名字。 對于使用用戶態(tài) PPP 的用戶而言, 應該是tun0
。
這些規(guī)則遵循一定的模式。
所有請求 Internet 公網上服務的會話開始包, 都使用了 keep-state
。
所有來自 Internet 的授權服務請求, 都采用了 limit
選項來防止洪水式***。
所有的規(guī)則都使用了 in
或者 out
來說明方向。
所有的規(guī)則都使用了 via
接口名
來指定應該匹配通過哪一個接口的包。
這些規(guī)則都應放到 /etc/ipfw.rules
。
另外有需要云服務器可以了解下創(chuàng)新互聯scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。