轉載文章 技術文章: 以 iptables 架設 SME 防火牆
此文章由 pango 發表於1月 7日 (星期三) 上午12:00
由於 Internet 的普及和連接的成本下降, 很多企業都已經把辦公室網絡接上 Internet 去了。 而當各企業正享受著 Internet 所帶來的商機和方便的同時, 亦為企業本身帶來各種的危機。 從一些貪玩小孩的入侵, 到大規模的網蟲 (NetWorm) 爆發。 企業的系統無時無刻面對著各種挑戰。 一但系統被入侵, 所損失的往往多於能從 Internet 中所得到的。 所以我們必需要有一個防禦的機制來保護企業內的資料和財產, 免受外來的種種攻擊。 而當中最為普及的技術便是『防火牆』(Firewall)。
什麼是防火牆
『防火牆』只是一個統稱, 或者可以說是一個概念。 其實, 任何一種能成功防止外來入侵的網絡裝置或軟件, 都可以稱為『防火牆』。
從網絡保安而言, 防火牆通常會用作內部網絡對外連接的唯一通道。 如此一來, 防火牆便成為了一個網絡關卡, 所有進出內部網絡的交通都必先經過防火牆的檢查和過濾, 防止入侵者接近內部的資源。
而防火牆是根據網絡管理員預先定下的規則 (Rules) 來過濾網絡交通。 而這些規則便是整個防火牆的靈魂、內部網絡的守衛。 在制定這些規則時, 大都是圍繞著以下幾個範籌而定:
誰〔不〕能進出網絡
什麼〔不〕可以進出網絡
資料〔不〕可以傳到那裡去
用什麼方法才〔不〕可進出網絡
防火牆的種類
現時所流行的防火牆大致可分為以下兩類:
1 封包過濾 (Packet Filters)
封包過濾是透過檢測網絡封包的標頭 (Header) 資料是否符合管理員所定下的規則, 而決定是否讓其通過。 這些標頭資料包括了:
來源/目的地的位址 (Address)
來源/目的地的通訊埠 (Port)
通訊協定 (Protocol)
使用封包過濾的好處是其系統和應用程式中立性 (Operating Sytem & Application-neutral), 對於在內部網絡的客端程式不須作任可更改便可提供保謢。 而本文將會介紹的 防火牆亦是封包過濾式的。
2 應用層閘道 (Application Gateway)
應用層閘道式的防火牆, 主要是在客端和伺服器之間加上『代理伺服器』(Proxy Server) 而達成。 如此一來, 網絡間的連線得變成兩個部驟: 首先是客端和代理伺服器連線, 然後經過過濾後才由代理伺服器和真實的伺服器連線。
但是使用應用層閘道式的防火牆, 往往須要更改客端程式的設定來佩合。 這對於一般的用家 (End-user) 來說, 並不如封包過濾般方便。
Linux 與 封包過濾
Linux 核心自版本 1.1 開始已提供了封包過濾的功能。 到了現時的 2.4 版本內建的 Netfilter 模組, 功能更臻完善。 這個模組利用了一致被資訊保安界好評的 『狀態性』(Stateful) 機制, 記下各網絡連線的狀態並檢查往後的封包是否屬於同一連線。 狀態性機制能使防火牆能過濾一些以往不能偵測的連線狀態, 加強了內部網絡安全。
iptables
Netfilter 是在 Linux 核心 (Kernel) 的模組, 我們不能和它直接溝通。 它只會依著管理員定下的規則, 對封包進行檢測。 至於把怎樣才能把規則告知 Netfilter, 就得靠一個名為 iptables 的用戶端的程式。
要把 iptables 運用得當, 就先要理解 Netfilter 處理封包的機制。
之前提及過防火牆是透過一系列的規則而建成, 而每個規則都包含了一個對封包的描述 (Match) 和 一個處置動作 (Target)。 每當封包符合規則中的描述時, 核心便會對封包進行相應的處置動作。 而在 Netfilter 的角度中, 這些規則是記錄在不同的鏈 (Chain) 中, 而鏈又會被歸納到不同的規則表 (Table) 中。
封包會根據它在核心中不同的層次和狀態, 被送到一個或多個規則表和鏈中, 並和當中的每個規則作對比並執行相應的動作。 iptables 的功用就是讓管理員管理各個規則表和鏈中的規則。
核心中的規則表
在核心中有三個規則表:
filter
這個規則表是最常用的規則表, 也是 iptables 的預設的規則表。 所有對封包進行過濾的規則都是加進這個規則表的鏈中。 這個規則表中有三個預設的鏈, 分別是: INPUT (給目的地是本機的封包), FORWORD (給途經本機的封包), OUTPUT (給由本機所發出的封包)
nat
這個規則表主要是給予系統 網路位址轉換 (Network Address Translation) 的功能。顧名思義, 網路位址轉換就是把封包標頭的位址和通訊埠的資料更改。 這個功能主要的用處是:
Internet 連線分享。 即使只得一個可用的 Internet 位址, 也可把整個內部網絡的電腦接上 Internet。
隱蔽內部網絡的存在。 縱然有足夠的 Internet 位址可用, 但基於保安的理由我們有時會不希望其他人知到企業內部網絡的存在。 運用網路位址轉換就可把所有內部網絡對外的通訊轉換成看似是同一位址所發出的封包一樣。
服務轉向 (Forwording )。 當有伺服器置於防火牆後, 但又須要對外提供時, 便可以把目的地位址是防火牆的封包轉向到真實的伺服器。這個規則表中有三個預設的鏈, 分別是: PREROUTING (給所有進入本機而未經路由處理 (Routing Decision)的封包), POSTROUTING (給所有經過路由處理而目的地不是本機的封包), OUTPUT (給由本機所發出的封包)
mangle
這個規則表用來更改封包的一些屬性 (Properties), 這個規則表中有四個預設的鏈, 分別是: PREROUTEING, INPUT, FORWARD , OUTPUT 和 POSTROUTING。
Iptables 的基本語法
iptables -t Table -Operation Chain Match -j Target
Table 是所用的是個規則表
Chain 指明是用規則表中的哪一個鏈
Operation 是對鏈中的規則所進行的動作, 例如:增加,移除,清空 等
Match 是一個對封包的描述, 例如:來源地址及通訊埠
Target 是處置動作, 例如:ACCEPT, DROP, LOG等
常用的描述語法
語法 用途
-p [!] protocol 指定所針對的通訊協定, 例如:tcp, udp, icmp
-s [!] address[/mask] 指定所針對的來源位址。 這可以是一個IP位址, 主機名稱, 或加上網絡遮罩以表示一群 IP 位址。
-d [!] address[/mask] 指定所針對的目的地位址。 這可以是一個IP位址, 主機名稱, 或加上網絡遮罩以表示一群IP位址。
-i [!] name 指定從那個網絡介面進入的封包。 例如:eth0, ppp0
-o [!] name 指定從那個網絡介面送出的封包。 例如:eth0, ppp0
--sport [!] port[:port] 指定來源通訊埠。 這可以指明是那一個或那一組埠
--dport [!] port[:port] 指定目的地通訊埠。 這可以指明是那一個或那一組埠
[!] --syn 只限 TCP 協定所用, 這指定封包須為 TCP 連線要求封包
防火牆架設範例
有了基本的認識後, 我們便開始架設防火牆。 我們假設企業A 有一個 Internet 連線和足夠的合法 Internet 位址給所有電腦使用。 而企業A 只希望員工使用 WWW 和 FTP。
我們可以跟著以下的步驟制作一個 Shell Script, 來架設防火牆。
設定網絡參數和載入相關的核心模組
$INTERNAL_NET=X.X.X.X/24 # Local LAN Subnet
$INTERNAL_NIC=eth0 # Local LAN interface
$EXTERNAL_NET=Y.Y.Y.Y/8 # Internet Subnet
$EXTERNAL_NIC=eth1 # Internet interface
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ipt_state
清除現有的規則
-F 動作會清除所指定的鏈中的所有規則, 如果沒有指明鏈則規則表中所有的鏈都會被清空。
/sbin/iptables -t filter -F
/sbin/iptables -t nat -F
/sbin/iptables -t mangle -F
-X 動作會移除指定規則表中所有由用者增加的鏈
/sbin/iptables -t filter -X
/sbin/iptables -t nat -X
/sbin/iptables -t mangle -X
設定預設政策
-P 動作會設定所指定的鏈的預設政策。 當一個封包進入鏈後, 但沒有規則能符合這個封包的資料和狀態時, 核心會以鏈的預設政策去處理該個封包。
每一個良好的防火牆的預設政策都應設為 DROP。 正所謂寧枉無縱, 預設拒絕所有封包, 然後才讓真正有用封包通過。 能使防火牆更為堅固。
/sbin/iptables -t filter -P INPUT DROP
/sbin/iptables -t filter -P OUTPUT DROP
/sbin/iptables -t filter -P FORWARD DROP
不回應 ICMP 封包
如要查看一部主機是否在線, 最簡單的方法是使用 ping 指令。 如果不想被 ping, 可以設定 Netfilter 不回應 ICMP 封包
/sbin/iptables -t filter -A INPUT -p icmp --icmp-type echo-requested -j DROP
/sbin/iptables -t filter -A OUTPUT -p icmp --icmp-type echo-reply -j DROP
/sbin/iptables -t filter -A FORWARD -p icmp --icmp-type echo-requested -j DROP
/sbin/iptables -t filter -A FORWARD -p icmp --icmp-type echo-reply -j DROP
防止 IP Spoofing
IP Spoofing 是把外來的封包假裝成是內部網絡所發出的, 試途讓防火牆誤認而允許其進入內部網絡。 而要防止 IP Spoofing, 我們只須要過濾那些從 Internet 進入而聲稱來源地址是內部網絡的封包便可。
/sbin/iptables -t filter -A INPUT -i $EXTERNAL_NIC -s $INTERNAL_NET -j DROP
/sbin/iptables -t filter -A FORWARD -i $EXTERNAL_NIC -s $INTERNAL_NET -j DROP
防止網絡掃描
網絡掃描是利用一些不正常而又合法的封包去檢測伺服器所提供的服務和取得一些系統資訊。 亦有入侵者用這些封包企途繞過防火牆去入侵內部網絡, 所以必需過濾。
/sbin/iptables -t filter -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
/sbin/iptables -t filter -A FORWARD -p tcp --tcp-flags ALL ALL -j DROP
/sbin/iptables -t filter -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
/sbin/iptables -t filter -A FORWARD -p tcp --tcp-flags ALL NONE -j DROP
/sbin/iptables -t filter -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
/sbin/iptables -t filter -A FORWARD -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
/sbin/iptables -t filter -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
/sbin/iptables -t filter -A FORWARD -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
允許內部網絡使用者瀏覽 Internet 網頁
要允許瀏覽 Internet 網頁, 我們須要允許封包從內部網絡傳送到 Web Server 去, 並同時要允許封包從 Web Server返回內部網絡。
/sbin/iptables -t filter -A FORWARD -p tcp -s $INTERNAL_NET -d 0/0 --dport 80 -j ACCEPT
/sbin/iptables -t filter -A FORWARD -p tcp -s $INTERNAL_NET -d 0/0 --dport 443 -j ACCEPT
要允許封包從 Web Server返回內部網絡, 有兩個方法設定。 其一是利用狀態性機制去自動判斷相關的封包:
/sbin/iptables -t filter -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
其次是加上相應的規則:
/sbin/iptables -t filter -A FORWARD -p tcp -d $INTERNAL_NET -s 0/0 --sport 80 ! --syn -j ACCEPT
/sbin/iptables -t filter -A FORWARD -p tcp -d $INTERNAL_NET -s 0/0 --sport 443 ! --syn -j ACCEPT
利用狀態性機制去自動判斷的好處是, 只須設定一次就能和其他規則分享使用 (象以下的 DNS 和 FTP), 能減少規則的數量,方便管理。
允許內部網絡查詢 DNS
DNS 是主機名稱和 IP 位址互換的服務, 如果過濾了 DNS 查詢, 用戶便不能用主機名稱 (如:http://www.linuxpilot.net ) 來瀏覽網頁, 而是要直接用 IP 位址 (如: http://203.194.196.187)。
/sbin/iptables -t filter -A FORWARD -p udp -s $INTERNAL_NET -d 0/0 --dport 53 -j ACCEPT
如果已有固定的 DNS 伺服器, 可以以下規則去限制只可以查詢指定的 DNS 伺服器:
$DNSSRV=202.181.230.106 # IP Address of the DNS Server
/sbin/iptables -t filter -A FORWARD -p udp -s $INTERNAL_NET -d $DNSSRV --dport 53 -j ACCEPT
允許內部網絡使用者使用 FTP
大部份的 Internet 服務的設定基本上和之前的大同小異, 讀者可以嚐試自行設定。 但可惜的是 FTP 不只用一個通訊埠來進行資料傳送, 而是要用兩個。 更甚的是其中一個通訊埠是次次不同的, 根本不可能預先在防火牆中設定。
有幸的是 Netfilter 所提供的狀態性機制能解決這個問題。 由於 FTP 的第二個通訊埠的連線, 是透過在埠21已建立的連線來建立, 所以可以利用狀態性機制去允許所有由已建立的連線所衍生出來的連線。
/sbin/iptables -t filter -A FORWARD -p tcp -s $INTERNAL_NET -d 0/0 --dport 21 -j ACCEPT
允許管理員以 SSH 連線到防火牆修改設定
最後, 開設一個通道給管理員以 SSH 連線到防火牆修改設定。 不然的話, 每當有設定要修改時, 管理員便要親身登入防火牆修改了。
/sbin/iptables -t filter -A INPUT -i $INTERNAL_NIC -s $INTERNAL_NET --dport 22 -j ACCEPT
最後的步驟
當設計好所有的規則和相應的 Script 後, 把所有的 Script 集合起來製成一個 Shell Script, 然後於 /etc/rc.d/rc.local 中加入執行該 Script 的命令。 這樣每次系統啟動時便會自動啟動防火牆。
Internet 連線分享
雖然以上的防火牆是基於有足夠的合法位址而設計, 但只須多加一規則便可以讓內部網絡以一個合法位址分享Internet 連線。
如果獲得一個固定的合法位址, 可以用:
$FIREWALL_IP=y.y.y.z # IP Address that can connect to Internet
/sbin/iptables -t nat -A POSTROUTING -o $EXTERNAL_NIC -s $INTERNAL_NET -j SNAT –to $FIREWALL_IP
如果位址是動態分佩的話, 則用:
/sbin/iptables -t nat -A POSTROUTING -o $EXTERNAL_NIC -s $INTERNAL_NET -j MASQUERADE
其實以上兩個規則,都是叫核心把由內部網絡所發出的封包內的來源位址, 先轉成防火牆的合法位址再送出 Internet。 只不過用 MASQUERADE 方法時, 因為要顧及動態位址分佩, 所以會比 SNAT 多用一點 CPU 資源。
總結
Linux 加上 Netfilter 的強大功能, 給予中小企一個低成本的防火牆的解決方案。 以保障企業的資源。 以上的範例雖已包含了一般防火牆的功能, 但單靠 Netfilter 是未能杜絕所有的入侵 (例如: 電郵病毒)的。 所以系統管理員仍是要綜合各種網絡保安的工具一起, 發揮最大的效能。
作者Isaac Chau
原文在 LinuxPilot 第 15 期刊登
沒有留言:
張貼留言