1. 程式人生 > >CentOs 防火牆iptables 詳解

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 可以做的事情,但我希望這份教學文件提供了一個良好的基礎,幫助各位建立更復雜的規則集。