這裡介紹如何在 CentOS Linux 7 中使用 firewalld 的指令設定防火牆規則。
在舊版的 CentOS Linux 中,防火牆都是以傳統的 iptables 來設定,而從 CentOS 7 開始,則改用 firewalld 來管理防火牆。
傳統的 iptables 在每次修改防火牆時都要清除舊規則,重新套用一次新規則,使用上不是很方便,而新的 firewalld 以區域(zone)的方式管理規則,並使用動態的方式執行,修改規則後可立即生效,也不需要重新啟動系統的服務(service 或 daemon),所以後來的 RHEL、CentOS 與 Fedora 都改用 firewalld 了。
iptables 與 firewalld 兩個防火牆管理系統只能選用其中一種,不可以同時開啟,否則會有問題。
以下是我在 CentOS Linux 7 的測試環境中所整理出來的 firewalld 使用教學。
安裝 firewalld
安裝 firewalld 之前,請先確認 iptables 是否有被啟用,若系統上原本就有運行 iptables 的防火牆,一定要先將其關閉後,才能啟用 firewalld,否則會有問題:
# 檢查 iptables 服務是否正在運行
systemctl status iptables
# 停止正在執行的 iptables 服務
systemctl stop iptables
# 將 iptables 服務永久關閉
systemctl mask iptables
firewalld 在 RHEL/CentOS 7 與 Fedora 21 之中應該是預設就會安裝好的,若您的系統上沒有安裝,可用 yum
安裝:
sudo yum install firewalld
當 firewalld 安裝好之後,檢查 firewalld 服務是否有啟動:
# 檢查 firewalld 服務狀態
systemctl status firewalld
若 firewalld 沒有啟動,則手動啟動它:
# 啟動 firewalld 服務
systemctl start firewalld
# 停止 firewalld 服務
systemctl stop firewalld
# 重新啟動 firewalld 服務
service firewalld restart
若要設定讓 firewalld 在開機時自動啟動,可執行:
# 設定開機自動啟動 firewalld 服務
systemctl enable firewalld
區域簡介
firewalld 的區域(zone)可用來設定網路連線、介面等所處的運作環境,對內使用的區域其防火牆規則會較為寬鬆,反之若是對外的區域其規則會較為嚴謹。
一條網路連線或介面只能隸屬於一個區域,我們可以自訂區域的設定,也可以直接從 firewalld 預設的幾個區域中選擇:
區域 | 描述 |
---|
drop | 任何往內的封包都會被丟棄,只允許往外傳送的封包。 |
block | 任何來自於外部的連線都會被阻擋,只允許自己系統主動建立的連線。 |
public | 公開區域,預設不信任其他電腦與網路,只有被允許的連線才能進入。通常大部分的連線設定都會放在這裡。 |
external | 公開區域,適用於 NAT 網路環境。 |
dmz | 非軍事區域(demilitarized zone,有點像是放在外頭的危險區域),允許外部的連線進入,但其對內的連線則有限制,只有被允許的連線才能連進內部網路。 |
work | 公司內部等工作區域,在此區域中不應該會有惡意的攻擊者。只有被允許的連線可以進入。 |
home | 家裡頭的網路區域,在此區域中不應該會有惡意的攻擊者。只有被允許的連線可以進入。 |
internal | 內部網路區域,在此區域中不應該會有惡意的攻擊者。只有被允許的連線可以進入。 |
trusted | 完全信任的區域,接受所有連線。 |
查詢區域設定
firewalld 都是透過 firewall-cmd
指令來操作的,若要列出 firewalld 中已經定義好的區域,可執行:
# 列出所有的區域
firewall-cmd --get-zones
block dmz drop external home internal public trusted work
列出所有的區域與其詳細的設定內容:
# 列出所有的區域與內容
sudo firewall-cmd --list-all-zones
block
target: %%REJECT%%
icmp-block-inversion: no
interfaces:
sources:
services:
ports:
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[略]
若要查詢特定區域的內部設定,可執行:
# 列出指定的區域與內容
sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp7s0d1 ib0
sources:
services: ssh dhcpv6-client rpc-bind https http tftp dhcp
ports: 944/tcp 944/udp 945/tcp 945/udp 946/udp 8649/udp 8649/tcp 8651/tcp 8652/tcp 15001/tcp 15002/tcp 15003/tcp 15004/tcp 15007/tcp 17001/tcp 8080/tcp
protocols:
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
上面這個查詢方式所得到的結果是目前系統上執行的設定(runtime),若要查詢寫在硬碟中的永久設定,可以使用:
# 查詢永久設定值
sudo firewall-cmd --permanent
預設區域
當網路介面或是連線沒有指定區域時,就會直接納入預設區域中。若要查詢目前預設的區域,可執行:
# 列出預設區域
firewall-cmd --get-default-zone
public
若要更改 firewalld 預設的區域,可以執行:
# 設定預設區域
firewall-cmd --set-default-zone=home
更改後,可再確認一次預設區域:
# 列出預設區域
firewall-cmd --get-default-zone
home
介面所屬區域
列出目前所有運作中的區域,以及各個網路介面所屬的區域:
# 查詢運作中的區域
firewall-cmd --get-active-zones
public
interfaces: enp7s0d1 ib0
trusted
interfaces: eno2
若要查詢指定網路介面所屬區域,可執行:
# 查詢網路介面所屬區域
firewall-cmd --get-zone-of-interface=enp7s0d1
public
若要更改指定網路介面的所屬區域,可以使用:
# 將 enp7s0d1 網路介面設定至 home 區域
sudo firewall-cmd --change-interface=enp7s0d1
上面這種修改網路介面所屬區域的方式只是暫時的,若要讓系統重新開機後還可以維持這樣的設定,就要直接更改 /etc/sysconfig/network-scripts/
底下的設定檔,以 enp7s0d1
這個網路介面來說,就修改 ifcfg-enp7s0d1
這個檔案中的 ZONE
設定值:
區域的服務
若要在防火牆上開啟一些連接埠,讓對外的服務使用,可以再區域設定中新增一些服務設定。firewalld 中有預先定義一些常用的服務名稱,這用這個指令查詢:
# 列出預先定義的服務名稱
firewall-cmd --get-services
RH-Satellite-6 amanda-client amanda-k5-client bacula bacula-client bitcoin
bitcoin-rpc bitcoin-testnet bitcoin-testnet-rpc ceph ceph-mon cfengine condor-collector
ctdb dhcp dhcpv6 dhcpv6-client dns docker-registry dropbox-lansync elasticsearch
freeipa-ldap freeipa-ldaps freeipa-replication freeipa-trust ftp ganglia-client
ganglia-master high-availability http https imap imaps ipp ipp-client ipsec iscsi-target
kadmin kerberos kibana klogin kpasswd kshell ldap ldaps libvirt libvirt-tls managesieve
mdns mosh mountd ms-wbt mssql mysql nfs nrpe ntp openvpn ovirt-imageio ovirt-storageconsole
ovirt-vmconsole pmcd pmproxy pmwebapi pmwebapis pop3 pop3s postgresql privoxy proxy-dhcp
ptp pulseaudio puppetmaster quassel radius rpc-bind rsh rsyncd samba samba-client
sane sip sips smtp smtp-submission smtps snmp snmptrap spideroak-lansync squid ssh
synergy syslog syslog-tls telnet tftp tftp-client tinc tor-socks transmission-client
vdsm vnc-server wbem-https xmpp-bosh xmpp-client xmpp-local xmpp-server
大部分常見的網路服務都有在這個列表中,若要將指定的服務新增至指定的區域中,可執行:
# 將 http 服務新增至 public 區域中
sudo firewall-cmd --add-service=http
上面這行指令只是暫時將 http
服務新增至 public
區域中,重新開機後這個設定就不見了,通常在比較重要的伺服器上,我們都會先使用暫時的設定先進行測試,若測試沒問題,再將設定寫入設定檔,永久保存:
# 永久將 http 服務新增至 public 區域中
sudo firewall-cmd --add-service=http
執行永久的設定之後,可再重新查詢一次永久設定值,確認設定值是否正確:
# 列出 public 區域永久的服務設定值
sudo firewall-cmd --list-services
這樣設定之後,在 public
這個區域就會開啟網頁的 80
連接埠,讓外面可以連進來我們的網站,而現在的網站都會提供安全加密的網頁,所以最好連 HTTPS 的 443
連接埠也一並開啟,開啟的方式大同小異:
# 將 https 服務新增至 public 區域中
sudo firewall-cmd --add-service=https
# 永久將 https 服務新增至 public 區域中
sudo firewall-cmd --add-service=https
自訂開啟連接埠
基本上 firewalld 有內定的服務都可以使用上面這種方式開啟,如果我們想要開啟的連接埠不在 firewalld 內建的服務名單中,也可以直接指定通訊協定( tcp
或 udp
)與埠號:
# 開啟 tcp 的 8080 連接埠
sudo firewall-cmd --add-port=8080/tcp
# 永久開啟 tcp 的 8080 連接埠
sudo firewall-cmd --add-port=8080/tcp
埠號的部分也可以用範圍的方式指定,一次開通多個連接埠:
# 開啟 udp 的 4990 至 4999 連接埠
sudo firewall-cmd --add-port=4990-4999/udp
# 永久開啟 udp 的 4990 至 4999 連接埠
sudo firewall-cmd --add-port=4990-4999/udp
移除服務
若要將指定的服務從某個區域中移除,可以執行:
# 將 http 服務從 public 區域中移除
sudo firewall-cmd --remove-service=http
# 永久將 http 服務從 public 區域中移除
sudo firewall-cmd --remove-service=http
如果是要移除自訂的通訊協定與埠號,則執行:
# 關閉 tcp 的 8080 連接埠
sudo firewall-cmd --remove-port=8080/tcp
# 永久關閉 tcp 的 8080 連接埠
sudo firewall-cmd --remove-port=8080/tcp
新增服務名稱
除了直接指定通訊協定與埠號之外,我們也可以自訂新的服務名稱,加入 firewalld 的服務名稱清單中,這樣就可以使用服務名稱的方式來設定開啟的服務,這樣做的好處是可以讓防火牆的設定看起來更容易理解,不會搞不清楚某些奇怪埠號的用途。
若要新增服務名稱,可以在 /etc/firewalld/services
新增服務的 XML 設定檔,XML 設定檔的語法可參考 /usr/lib/firewalld/services/
中的範例,例如 http.xml
就是定義 http 服務的設定檔:
?>
>
/>
參考這些範例後,撰寫自己的服務設定檔(若需要開啟多個連接埠,可以自己新增,或是參考其他的範例檔),然後另外儲存成一個新的檔案,放在 /etc/firewalld/services
目錄下,檔名要設定為服務的名稱加上 XML 的附檔名,例如 my_service.xml
,接著讓 firewalld 重新載入設定:
# 重新載入設定
sudo firewall-cmd --reload
重新查詢一次支援的服務名稱,應該就可以看到新加入的 my_service
服務了:
# 列出預先定義的服務名稱
firewall-cmd --get-services
常用範例
這裡蒐集一些常用的 firewalld 防火牆設定指令。
只允許特定來源 IP 位址使用服務
如果我們的服務只想讓某些特定來源 IP 位址的電腦使用,可以這樣設定:
# 允許 192.168.0.0/24 使用 http 服務
firewall-cmd \
'
# 永久允許 192.168.0.0/24 使用 http 服務
firewall-cmd \
\
--permanent
白名單 IP 位址
若要將特定的 IP 位址設定為白名單,讓它可以連接任何的連接埠,可以這樣做:
# 將 192.168.0.123 列為 public 區域的白名單
firewall-cmd \
'
# 永久將 192.168.0.123 列為 public 區域的白名單
firewall-cmd \
\
--permanent
參考資料: Red Hat、 Fedora、 Tecmint、 DigitalOcean、 黃昏的甘蔗
原文出處:CentOS Linux 7 以 firewalld 指令設定防火牆規則教學 - G. T. Wang