(轉)在 CentOS 設置 iptables

1. 引言

CentOS 內置了一個非常強勁的防火牆,統稱爲 iptables,但更正確的名稱是 iptables/netfilter。iptables 是一個用戶空間的模塊。作爲用戶,你在命令行就是通過它將防火牆規則放進缺省的表裡。netfilter 是一個核心模塊,它內置於內核中,進行實際的過濾。iptables 有很多前綴圖像界面可以讓用戶新增或定義規則,但它們很多時不及使用命令行般有靈活性,而且限制用戶瞭解實際發生的事情。我們將會學習 iptables 的命令行界面。

在我們正式應付 iptables 前,我們必須對它的運作有一個基本的理解。iptables 利用到 IP 地址、協議(tcp、udp、icmp)及端口這些概念。我們不需要成爲這些方面的專家(因爲我們可以找到所需的信息),但對它們有一般的理解會有幫助。

iptables 將規則放進缺省的規則鏈(INPUT、OUTPUT 及 FORWARD),而所有流量(IP 壓縮)都會被相關的規則鏈檢查,根據當中的規則判斷如何處理每個壓縮,例如:接納或丟棄它。這些動作稱爲目標,而最常見的兩個缺省目標就是 DROP 來丟棄壓縮;或 ACCEPT 來接納壓縮。

規則鏈

我們可以在過濾表的 3 條缺省規則鏈內加入規則,來處理通過這些規則鏈的壓縮。它們分別是:

* INPUT - 所有以主機爲目的地的壓縮。
* OUTPUT - 所有源自主機的壓縮。
* FORWARD - 這些壓縮的目的地或來源地都不是主機,但路經主機(由它選路)。假若你的主機是一個路由器,這條規則鏈將會被應用。

我們將會花費最多時間處理 INPUT 規則鏈,藉以過濾進入我們的機器的壓縮 —— 亦即是將壞蛋拒諸門外。

規則是以列表的方式被加進每條規則鏈。每個壓縮會被頭一條規則開始檢查,才至最後一條。假若壓縮與其中一條規則吻合,相應的動作便會被執行,例如接納(ACCEPT)或丟棄(DROP)壓縮。一但有吻合的規則,這個壓縮便會按照規則來處理,而不再被規則鏈內的其它規則所檢查。假如壓縮通過所有檢查而不符合任何規則鏈內的任何一條規則,那應這條規則鏈的缺省動作將會被執行。這就是所謂的缺省政策,可以設置爲接納(ACCEPT)或丟棄(DROP)壓縮。

規則鏈擁有缺省政策這個概念帶來兩個基本的可能性,而我們必須考慮它們才能決定如何組織我們的防火牆。

1. 我們可以缺省一個政策來丟棄(DROP)所有壓縮,然後刻意加入規則來接納(ACCEPT)源自被信任的 IP 地址的壓縮,或者打開那些提供服務的端口,如:bittorrent、FTP 服務器、網頁服務器、Samba 文件服務器等。

又或者,

2. 我們可以缺省一個政策來接納(ACCEPT)所有壓縮,然後刻意加入規則來攔截(DROP)來自有問題的 IP 地址或系列的壓縮,也或者阻止壓縮進出只作私人用途或未提供服務的端口。

普遍來說,第一個方法多數用在 INPUT 規則鏈,因爲我們會希望控制哪些東西可以訪問我們的機器;而第二個方法多數用在 OUTPUT 規則鏈,因爲我們多數信賴那些離開(源自)我們機器的壓縮。

2. 準備開始

在命令行上使用 iptables 需要 root 的權限,因此你必須化身爲 root 用戶來做下面的事情。

[attachment:ArtWork/WikiDesign/icon-admonition-attention.png]


注意: 我們將會停用 iptables 及復位你的防火牆規則,因此假若你依賴你的 Linux 防火牆作爲第一道防線,請特別留意這點。

iptables 應該缺省被安裝在所有 CentOS 3.x、4.x 及 5.x 上。你可以這樣來檢查 iptables 是否已安裝在你的系統上:

$ rpm -q iptables
iptables-1.3.5-1.2.1

要知道 iptables 是否正在運作中,我們可以檢查 iptables 這個模塊是否已被裝入,並利用 -L 這個選項來查看活動的規則:

# lsmod | grep ip_tables
ip_tables 29288 1 iptable_filter
x_tables 29192 6 ip6t_REJECT,ip6_tables,ipt_REJECT,xt_state,xt_tcpudp,ip_tables

# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
RH-Firewall-1-INPUT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
RH-Firewall-1-INPUT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain RH-Firewall-1-INPUT (2 references)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT icmp -- anywhere anywhere icmp any
ACCEPT esp -- anywhere anywhere
ACCEPT ah -- anywhere anywhere
ACCEPT udp -- anywhere 224.0.0.251 udp dpt:mdns
ACCEPT udp -- anywhere anywhere udp dpt:ipp
ACCEPT tcp -- anywhere anywhere tcp dpt:ipp
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited

從上面我們可看見缺省的規則,與及訪問 SSH 服務用的規則。

如果 iptables 並未被執行,你可以這樣啟用它:

# system-config-securitylevel

3. 創建一組簡單的規則

[attachment:ArtWork/WikiDesign/icon-admonition-attention.png]


注意: 此刻我們將會清除缺省的規則集。如果你是通過 SSH 遠程連接到一臺服務器來進行學習,你有可能會將自己拒諸這臺機器之外。你必須將缺省的輸入(input)政策改爲接納(accept),然後才清除現有規則,接著你要預先加入一條容許你自己訪問機器的規則,避免你將自己封鎖在外。

我們會採用一個以樣例爲本的方法來查看 iptables 的不同指令。在首個樣例中,我們會創建一組簡單的規則來設置一個「狀態壓縮檢驗」(SPI)防火牆,容許對外的連接但攔截一切無用的對內連接:

# iptables -P INPUT ACCEPT
# iptables -F
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
# iptables -L -v

你應該得到這樣的輸出:

Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
0 0 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

現在讓我們逐一看看以上的 8 個指令,並理解我們實際做了甚麼:

1.

iptables -P INPUT ACCEPT 假如利用遠程連接,我們必須臨時將 INPUT 鏈的缺省政策改爲 ACCEPT,否則當我們清除現有的規則集時,便會將自己封鎖在服務器之外。
2.

iptables -F 我們利用 -F 選項來清除一切現存的規則,好讓我們能夠在嶄新的狀態下加入的規則。
3.

iptables -A INPUT -i lo -j ACCEPT 現在是時候加入一些規則了。我們利用 -A 選項來附加(新增)規則到某條鏈,而這裡所指的是 INPUT 鏈。接著我們利用 -i 選項(interface「界面」之意)來指定那些符合或來自 lo(localhost、127.0.0.1)界面的壓縮。最後我們 -j(jump「跳至」)符合這條規則的目標動作:在這裡是 ACCEPT。所以這條規則會導致所有轉至 localhost 界面的對內壓縮獲得接納。一般來說這是必須的,因爲很多軟件預期能夠與 localhost 適配器溝通。
4.

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 這是擔負起大部份工作的規則,而我們再一次將它加進(-A)INPUT 鏈內。這裡我們利用 -m 選項來裝入一個模塊(state)。state 模塊能夠查看一個壓縮並判斷它的狀態是 NEW、ESTABLISHED 抑或 RELATED。NEW 指內進的壓縮屬於不是由主機啟主導的新增連接。ESTABLISHED 及 RELATED 指內進的壓縮隸屬於一條現存的連接,或者與現存的連接有關係。
5.

iptables -A INPUT -p tcp --dport 22 -j ACCEPT 現在我們加入一條規則來容許 SSH 通過 tcp 端口 22 來連接。這樣做是要防止我們連接到遠程系統的 SSH 連接意外地被封銷。我們稍後會更詳細解釋這條規則。
6.

iptables -P INPUT DROP 這個 -P 選項設置某條規則鏈上的缺省政策。我們現在可以將 INPUT 鏈的缺省政策改爲 DROP。意思就是,不符合任何一條規則的對內壓縮將會被丟棄。要是我們通過 SSH 遠程連接而沒有加入上一條規則,此刻我們便會被封鎖於系統之外。
7.

iptables -P FORWARD DROP 同樣地,在這裡我們將 FORWARD 鏈的缺省政策設爲 DROP,因爲我們並不是用計算機作爲路由器,所以理應沒有任何壓縮路經它。
8.

iptables -P OUTPUT ACCEPT 而最後,我們將 OUTPUT 鏈的缺省政策設爲 ACCEPT,因爲我們想容許所有對外的流量(由於我們信任我們的用戶)。
9.

iptables -L -v 最後,我們可以列出(-L)剛加入的規則,並檢查它們是否被正確地裝入。

我們需要做的最後一件事情,就是存儲我們的規則,好讓它們在下次開機時會自動被重新裝入:

# /sbin/service iptables save

這 樣做會執行 iptables 的 init 腳本,它會執行 /sbin/iptables-ave 並將現有的 iptables 設置寫進 /etc/sysconfig/iptables。開機時,iptables 的 init 腳本會通過 /sbin/iptables-restore 這個指令重新施用存儲在 /etc/sysconfig/iptables 內的規則。

很明顯的,在指令殼內輸入這堆指令會頗乏味,因此運用 iptables 的最簡易方法就是創建一個代你做以上一切的腳本。你可以將上面的指令輸入到你喜歡的文字編輯器內並存儲爲 myfirewall,例如:

#!/bin/bash
#
# iptables 樣例設置腳本
#
# 清除 iptables 內一切現存的規則
#
iptables -F
#
# 容讓 SSH 連接到 tcp 端口 22
# 當通過 SSH 遠程連接到服務器,你必須這樣做才能羣免被封鎖於系統外
#
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#
# 設置 INPUT、FORWARD、及 OUTPUT 鏈的缺省政策
#
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
#
# 設置 localhost 的訪問權
#
iptables -A INPUT -i lo -j ACCEPT
#
# 接納屬於現存及相關連接的壓縮
#
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#
# 存儲設置
#
/sbin/service iptables save
#
# 列出規則
#
iptables -L -v

註: 我們可以在腳本內加入註釋來提醒自己正在做甚麼。

現在令腳本可以被執行:

# chmod +x myfirewall

我們現在可以編輯這個腳本,並在指令殼內用以下指令來執行它:

# ./myfirewall

4. 界面

在上一個範本中,我們看見如何能接納所有來自某個界面的壓縮,也就是 localhost 界面:

iptables -A INPUT -i lo -j ACCEPT

假設我們現在有兩個獨立的界面,分別是將我們連接到內聯網的 eth0 及連接到外部互聯網的 ppp0 撥號調制解調器(或者 eth1 適配器)。我們或許會想接納所有來自內聯網的對內壓縮,但依然過濾那些來自互聯網的壓縮。我們可以這樣做:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT

讓特別留意 —— 假如你接納來自互聯網界面(例如 ppp0 撥號調制解調器)的所有壓縮:

iptables -A INPUT -i ppp0 -j ACCEPT

你便等同於停用了我們的防火牆!

5. IP 地址

將整個界面開放給對內的壓縮也許不夠嚴謹,而你想擁有更多控制權來決定接納甚麼及拒絕甚麼。現在假設我們擁有一羣採用 192.168.0.x 私人網絡的計算機。我們可以打開防火牆給來自某個被信任 IP 地址(例如 192.168.0.4)的對內壓縮:

# 接納來自被信任 IP 地址的壓縮
iptables -A INPUT -s 192.168.0.4 -j ACCEPT # change the IP address as appropriate

將這個指令分解,我們首先附加(-A)一條規則到 INPUT 鏈,指明來源(-s)IP 地址是 192.168.0.4 的壓縮都應該被接納(ACCEPT)(請亦留意我們如何利用 # 符號來解釋我們的腳本,因爲 # 之後的所有文字都會被視爲註釋)。

當 然,如果我們想接納來自一系列 IP 地址的壓縮,我們可以爲每個被位任的 IP 地址加入一條規則,而這樣做的確是可行的。但是假如它們的數量很多,一次過加入一系列 IP 地址會比較簡單。要這樣做,我們可以利用一個子網掩碼或標準的斜線記法來指定 IP 地址的範圍。舉個例說,如果我們想將防火牆開放給來自整個 192.168.0.x(當中 x=1 到 254)範圍的壓縮,我們可以用下面其中一個方法來達致目的:

# 接納來自被信任 IP 地址的壓縮
iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT # using standard slash notation
iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT # using a subnet mask

最 後,除了過濾單一的 IP 地址外,我們亦可以配對該設備的 MAC 地址。要這應做,我們需要裝入一個容許過濾 MAC 地址的模塊(mac 模塊)。較早前當我們用 state 模塊來配對 ESTABLISHED 及 RELATED 壓縮時,我們看見模塊擴展 iptables 功能的例子。在這裡我們除了檢查壓縮的 IP 地址外,更利用 mac 模塊來檢查來源地的 MAC 地址:

# 接納來自被信任 IP 地址的壓縮
iptables -A INPUT -s 192.168.0.4 -m mac --mac-source 00:50:8D:FD:E6:32 -j ACCEPT

首先我們用 -m mac 來裝入 mac 模塊,然後我們用 --mac-source 來指定來源 IP 地址(192.168.0.4)的 MAC 地址。你要爲每個需要過濾的乙太網設備找出 mac 地址。以 root 的身份執行 ifconfig(無線設備用 iwconfig)可以將 mac 地址告訢你。

這 樣可防止來源地的 IP 地址被偽裝,因爲只有真正源於 192.168.0.4(MAC 地址是 00:50:8D:5D:E6:32)的壓縮纔會被接納,而所有假扮源於該地址的壓縮都會被攔截。請注意,過濾 MAC 地址在互聯網上不能使用,卻絕對能正確地在內聯網裡運作。

6. 端口及協議

由上面我們看見如何將新增規則在防火牆內,用來過濾符合某個界面或來源 IP 地址的壓縮。 這樣做讓我們能經過防火牆訪問某些被信任的來源(主機)。現在我們看看如何過濾協議及端口,好叫我們能進一步區別要接納及攔截那些對內的壓縮。

在 我們開始之先,我們須要知道個別服務所使用的協議及端口編號。讓我們以 bittorrent 作爲一個簡單的樣例。bittorrent 在 6881 端口上採用 tcp 協議,因此我們需要容許所有以 6881 爲目標端口(它們抵步時所用的端口)的 tcp 壓縮。

# 接納目標端口是 6881 號(bittorrent)的 tcp 壓縮
iptables -A INPUT -p tcp --dport 6881 -j ACCEPT

在這裡我們附加(-A)一條規則到 INPUT 鏈,配對 tcp 協議(-p tcp)及從 6881 目標端口進入我們的機器(--dport 6881)。

註: 要配對目標或來源端口(--dport 或 --sport),你必須先指定協議(tcp、udp、icmp、all)。

我們亦可以擴展以上的樣例來包含一系列的端口,例如,接納 6881 至 6890 端口上的所有 tcp 壓縮:

# 接納目標端口是 6881-6890 號的 tcp 壓縮
iptables -A INPUT -p tcp --dport 6881:6890 -j ACCEPT

7. 融會貫通

既然我們已經有基本認識,現在便可以合併這些規則。

UNIX/Linux 上一個受歡迎的服務就是容許遠程登錄的 SSH 服務。SSH 缺省使用 22 號端口及採用 tcp 協議。因此假若我們想允許遠程登錄,我們需要容許 tcp 連接到 22 號端口:

# 接納目標端口是 22 號(SSH)的 tcp 壓縮
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

這 樣做會開放 22 號端口(SSH)給所有對內的 tcp 連接,卻會構成潛在的安全性威脅,因爲駭客可以強行破入使用易猜測口令的戶口。然而,假若我們知道那些通過 SSH 作遠程登錄的可信任機器的 IP 地址,我們便可以將訪問權限制到那些來源 IP 地址。舉個例說,如果我們只想將 SSH 的訪問權開放給我們的私人內聯網(192.168.0.x),我們可以將來源 IP 地址限制在這個範圍:

# 接納來自私人內聯網,目標端口是 22 號(SSH)的 tcp 壓縮
iptables -A INPUT -p tcp -s 192.168.0.0/24 --dport 22 -j ACCEPT

利 用來源 IP 進行過濾容讓我們能安全地開放 22 號端口上的 SSH 給可信任的 IP 地址來訪問。舉個例說,我們可以用這個方法允許工作與家用機器之間的登錄。對於其它 IP 地址來說,這個端口(與及服務)就好像了關閉了一樣,而服務亦依被停用,因此掃描端口的駭客多數會略過我們。

8. 總結

這裡只是很初步地介紹 iptables 可以做的事情,但我希望這份教學文檔提供了一個良好的基礎,幫助各位創建更復雜的規則集。

9. 連結

http://www.centos.org/docs/5/html/Deployment_Guide-en-US/ch-fw.html
http://www.centos.org/docs/5/html/Deployment_Guide-en-US/ch-iptables.html
發佈了27 篇原創文章 · 獲贊 1 · 訪問量 4176
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章