現在要開始增加 ipfirewall 的規則以使內部網路獲得安全。在實作時有點複雜,因為有些 ipfirewall 的功能在橋接的封包上無法使用。而且,在被橋接的封包和被本地機器接收的封包之間有些差異。一般而言,接收到被橋接的封包時只被過濾一次,而非一般情況的二次,因此使用規則 'out' 或 'xmit' 永遠不會符合。我通常使用比較舊但閱讀時有意義的語法 'in via'。另一個限制是只能使用 'pass' 或 'drop' 來過濾橋接封包,一些複雜的用法,如 'divert' 、 'forward' 或 'reject' 無法使用。這些語法只有在由機器本身出去或進來的網路傳輸才可以使用。
在 FreeBSD 4.0 中的新概念是 stateful filtering。對傳統要求外流、其後跟隨著相同 IP 位址及埠號的集合(但當然也有來源及目)的 UDP 網路傳輸而言,這是一個很大的吹噓。對於沒有狀態維持的防火牆而言,要處理這一連串的網路傳輸缺乏建立代理權。但防火權可以"記得" 一個向外流的 UDP 封包,而在接下來的幾分鐘內允許回應,處理 UDP 服務十分繁瑣,接下來的範例說明了如何實做。偏執狂也可以像這樣建立 TCP 的規則。這樣可以避免像拒絕服務攻擊或其他令人不愉的惡作劇,但它也將使 state table 的大小急速成長。
我們來看一個設定的範例。請注意在/etc/rc.firewall 的文件頂端中,應該已經處理了 lookback 介面,且關於 ARP 的處理也已經設定好了,這樣等一下才不用再顧慮這些。
us_ip=192.168.1.1 oif=fxp0 iif=fxp1 # Things that we've kept state on before get to go through in a hurry. ${ipfw} add check-state # Throw away RFC 1918 networks ${ipfw} add deny log ip from 10.0.0.0/8 to any in via ${oif} ${ipfw} add deny log ip from 172.16.0.0/12 to any in via ${oif} ${ipfw} add deny log ip from 192.168.0.0/16 to any in via ${oif} # 允許橋接器本身所有想做的連線 (keep state if UDP) ${ipfw} add pass udp from ${us_ip} to any keep-state ${ipfw} add pass ip from ${us_ip} to any # 允許內部網路任何想做的連線 (keep state if UDP) ${ipfw} add pass udp from any to any in via ${iif} keep-state ${ipfw} add pass ip from any to any in via ${iif} # 允許任何型式的 ICMP 連線 ${ipfw} add pass icmp from any to any # TCP section # 任何地方都可以建立 TCP 連線 ${ipfw} add pass tcp from any to any established # Pass the "quarantine" range. ${ipfw} add pass tcp from any to any 49152-65535 in via ${oif} # Pass ident probes. It's better than waiting for them to timeout ${ipfw} add pass tcp from any to any 113 in via ${oif} # Pass SSH. ${ipfw} add pass tcp from any to any 22 in via ${oif} # Pass DNS. 當內部網路有名稱伺服器時才需要 #${ipfw} add pass tcp from any to any 53 in via ${oif} # 只傳遞 SMTP 給郵件伺服器 ${ipfw} add pass tcp from any to mailhost 25 in via ${oif} # UDP section # Pass the "quarantine" range. ${ipfw} add pass udp from any to any 49152-65535 in via ${oif} # Pass DNS. 當內部網路有名稱伺服器時才需要 #${ipfw} add pass udp from any to any 53 in via ${oif} # 其他的都拒絕 ${ipfw} add deny log ip from any to any
以前有設定過防火牆的人也許注意到有些東西遺漏了,即 anti-spoofing。這裡並沒有加入:
${ipfw} add deny ip from ${us_ip}/24 to any in via ${oif}
那是指丟棄任何自稱來自於內部網路、卻從外面來的封包。通常加入這條規則是為了確保別人無法試著以產生惡毒的封包,使它看起來像從內部發出而騙過封包過濾器。但問題是至少有一個在外面的機器你不想要被忽略--你的路由器。以我的情況而言,我有些機器在外面、有些在裡面,但我不希望外部機器對內部有例行性的存取。但同時我也不希望把它們的網路傳輸丟棄,在我的情況裡,我的 ISP 在他們的路由器中有 anti-spoofs,因此我不需要操心。而且一般而言,規則越少越好,因為每條規則都需要消耗時間及 CPU 的處理。
請注意最後一條規則幾乎和內定的規則65536一模一樣,然而以橋接器而言,這二條規則有二個最主要的差異。當然這裡的規則在丟棄封包時會留下記錄,但這裡的規則只適用於 IP 傳輸,除了 UDP 0.0.0.0 外,無法處理非 IP 的網路傳輸,所以內定的規則 65536 會丟棄所有網路傳輸,而非只有非 IP 的傳輸。所以得到的影響是,不符合的 IP 傳輸會被記錄下來,但非 IP 傳輸不會。如果你想要的話,可以在核心設定中增加這一項設定 IPFIREWALL_DEFAULT_TO_ACCEPT ,這樣一來非 IP 的網路傳輸就會通過而不會被丟棄。但在具封包過濾的橋接器的情形下,你應該不會希望這樣做(除非你是一個超級偏執狂)。
如果你有郵件伺服器的話,其中有一條規則是用來傳遞 SMTP 協定的。以上所有規則很明顯的只是個範例,你應該依自己的需求加以修改。特別注意為了使 'mailhost' 正常運作,名稱伺服器的查詢應該在橋接器開始運作之前,這只是一個例子,確保你選擇了正確的介面。
另一個要注意的是只要在提供DNS服務時才需要設定 DNS 的規則,也就是說如果沒有設定 DNS 伺服器,就不需要這條規則。
提供認証封包(TCP port 113)使用的規則中,也可以使用 'reset' 或 'forward' 的規則,不幸的是,這並非橋接器程式碼中提供的選項,因此最少妨礙它的路徑就是乾脆傳遞它,使它到達目的地。只要目的地的機器有在跑認証服務(ident daemon),就相對的沒什麼大礙。另一個選擇是丟棄113埠的連線,如此將使諸如 IRC 等永遠停不了(the ident probe must timeout)。
也許你已經注意到另一個奇怪的地方,就是允許機器本身所有連線及另一個允許內部網路所有連線的規則。記住這是因為二個網路傳輸集合是經由核心及封包過濾器這二個不同的路徑交談,內部網路是經由橋接器程式碼,而機器本身使用一般的 IP 堆疊,也就是說這二條規則分別處理不同的情形。而在 via ${oif} 的規則中,同時處理二個路徑。一般而言,如果在過濾器中使用 via 規則,你必須為本機產生的封包加入一個例外處理,因為它們並不會經由(via)任何地方。
This, and other documents, can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
For questions about FreeBSD, read the
documentation
before contacting <questions@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.