1.Linux-Centos 7 firewalld防火牆設定

資訊文件分類:

系統

CentOS Linux release 7.0.1406 (Core)

firewalld執行指令

啟動
# service firewalld start

停止
# service firewalld stop

重新啟動
# service firewalld restart

重讀設定
# firewall-cmd --reload

查看狀態
# service firewalld status

# firewall-cmd --state

程式設定

目錄 /etc/firewalld
設定檔 /etc/firewalld/firewalld.conf

防火牆基礎操作

畢竟他是一個防火牆,所以他引入了防火牆的zone的觀念,一看到就能瞭,一個zone可以有規則,zone到zone也可以有規則。

預設是一個叫 public的 zone,就是外面進到伺服器的zone,如果伺服器很單純對外服務不當路由器的話,這個zone就夠了。

操作這個防火牆如果有圖形介面直接在選單中點選防火牆就好了,圖形化易學易懂較沒問題,指令的話主要是用firewall-cmd 這個指令。

查看zone
# firewall-cmd --get-default-zone
public

查看運作中的zone和zone裡的介面
# firewall-cmd --get-active-zones
public
  interfaces: ens192

可以看到ens192這個介面是在public 這個zone中。

查看所有的zone
# firewall-cmd --get-zones

新增zone
# firewall-cmd --set-default-zone=home

查看此zone=public所開的服務
# firewall-cmd --zone=public --list-all
public (default, active)
  interfaces: ens192
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

在public zone新增80TCP的服務
# firewall-cmd --zone=public --add-port=80/tcp

移除在public zone上80埠的所有服務 tcp/udp
# firewall-cmd --zone=public --remove-port=80

移除在public zone上5144埠的udp服務 5144/udp
# firewall-cmd --zone=public --remove-port=5144/udp

上面移除新增port(或服務)是整個zone都生效(一個zone可以由很多interfaces組成),我們可以指定來源:

# firewall-cmd --zone=public  --add-source=163.17.40.0/24
# firewall-cmd --zone=public  --remove-source=163.17.40.0/24

複雜的限定

這樣是所有的服務都套用這個來源,如果要限定單一服務的來源,可以使用他的rich rules:

列出所有rich-rules
# firewall-cmd --zone=public --list-rich-rules
<預設是沒有>

新增接受限制40.0可以讀取 28001埠
# firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="163.17.40.0/24" port port="28001" protocol="tcp" accept'

查看設定結果
# firewall-cmd  --zone=public --list-all
public (default, active)
  interfaces: ens192
  sources:
  services: dhcpv6-client ssh
  ports:
  masquerade: no
  forward-ports:
  icmp-blocks:
  rich rules:

        rule family="ipv4" source address="163.17.40.0/24" port port="28001" protocol="tcp" accept

這樣子就開通了40.0/24連往這台機器的規則。

但是這樣子設定只是runtime的環境有用,一設定下去就生效,不需要重啟和重讀;

移除,得要完整的寫才有用,請把 --list-all 顯示出來的 rich rules整行貼上
# firewall-cmd --zone=public --remove-rich-rule='rule family="ipv4" source address="192.168.56.0/24" port port="3306" protocol="tcp" accept'

當 firewalld重啟或重讀時,剛才加的設定就不見了,所以上面的操作要全部加上--permanent,讓它變成永久的設定

防火牆永久的設定

操作要全部加上--permanent,讓它變成永久的設定,runtime和永久的設定的不同,在firewalld重啟或重讀時,firewalld才會把永久的規則寫到runtime來用。

所以,永久的設定一定重啟或重讀才會生效。

查看永久的設定
# firewall-cmd --zone=public --list-all --permanent

查看runtime的設定(少了--permanent)
# firewall-cmd --zone=public --list-all

新增在public zone上53埠的udp服務 53/udp
# firewall-cmd --zone=public --add-port=53/udp --permanent

要觀察永遠設定的rule時,切記加上 --permanent

 

RHEL 及 CentOS 預設的防火牆會預設限制埠號對外開放, 如果安裝一些伺服器 (例如 Apache, NFS, Samba 等), 在本機測試正常, 但不能在外部連接, 可能是給防火牆封鎖了, 那便需要在防火牆開啟相應的埠號 (如 Apache 要開啟 80 或 443)。

在 RHEL 6 及 CentOS 6, 預設是使用 iptables, 而在 RHEL 7 開始改用了 firewalld 作為防火牆, 以下是兩者開啟埠號的方法。

RHEL 7 / CentOS 7 開啟埠號

例如我想永久開啟 80 埠號, 在 CentOS 7 輸入以下指令:

$ sudo firewall-cmd –zone=public –add-port=80/tcp –permanent
$ sudo firewall-cmd –reload

如果上面指令沒有加上 “–permanent” 參數, 下次重新開機後設定便會失效。

然後檢查設定是否生效:

$ sudo firewall-cmd –list-all

輸出類似這樣:

 

在 “ports” 一行, 可以看到 “80/tcp”, 那便表示埠號 80 的 tcp 連線對外開放。

RHEL 6 / CentOS 6 開啟埠號

在 CentOS 6 是使用 iptables 作為防火牆, 以下同樣是開啟埠號 80 作為例子:

$ sudo iptables -I INPUT -p tcp -m tcp –dport 80 -j ACCEPT
$ sudo service iptables save

上面第一行指令是開啟埠號 80 的連線, 而第二行指令則是將設定儲存, 讓下次開機保留這次的設定。

 

 

說明 指令
 啟動  service firewalld start
 停止  service firewalld stop
 禁用  systemctl disable firewalld
 重新啟動  service firewalld restart
 重讀設定  firewall-cmd --reload
 查看狀態  service firewalld status
 查看永久的設定  firewall-cmd --zone=public --list-all --permanent
 查看 runtime 的設定  firewall-cmd --zone=public --list-all
 查看 zone  firewall-cmd --get-default-zone
 查看此 zone 所開的服務  firewall-cmd --zone=public --list-all
 在 (執行時期) 
 加入 public zone 的 80 TCP 端口
 firewall-cmd --zone=public --add-port=80/tcp
 在 (永久)
 加入 public zone 的 80 TCP 端口
 firewall-cmd --zone=public --permanent --add-port=80/tcp
 在 (執行時期) 
 刪除 public zone 的 80 端口
 firewall-cmd --zone=public --remove-port=80
 在 (永久)
 刪除 public zone 的 80 端口
  firewall-cmd --zone=public --permanent --remove-port=80
 加入可通過的 IP  firewall-cmd --zone=public --add-source=192.168.1.2/24
 移除可通過的 IP  firewall-cmd --zone=public --remove-source=192.168.1.2/24
   
 加入 192.168.1.2/24
 的 IP 可讀取 80 端口
 firewall-cmd --zone=public
 --add-rich-rule='rule family="ipv4" source
 address="192.168.1.2/24" 
 port port="80" protocol="tcp" accept'
   
   

 

 

說明 指令
 啟動  service firewalld start
 停止  service firewalld stop
 禁用  systemctl disable firewalld
 重新啟動  service firewalld restart
 重讀設定  firewall-cmd --reload
 查看狀態  service firewalld status
 查看永久的設定  firewall-cmd --zone=public --list-all --permanent
 查看 runtime 的設定  firewall-cmd --zone=public --list-all
 查看 zone  firewall-cmd --get-default-zone
 查看此 zone 所開的服務  firewall-cmd --zone=public --list-all
 在 (執行時期) 
 加入 public zone 的 80 TCP 端口
 firewall-cmd --zone=public --add-port=80/tcp
 在 (永久)
 加入 public zone 的 80 TCP 端口
 firewall-cmd --zone=public --permanent --add-port=80/tcp
 在 (執行時期) 
 刪除 public zone 的 80 端口
 firewall-cmd --zone=public --remove-port=80
 在 (永久)
 刪除 public zone 的 80 端口
  firewall-cmd --zone=public --permanent --remove-port=80
 加入可通過的 IP  firewall-cmd --zone=public --add-source=192.168.1.2/24
 移除可通過的 IP  firewall-cmd --zone=public --remove-source=192.168.1.2/24
   
 加入 192.168.1.2/24
 的 IP 可讀取 80 端口
 firewall-cmd --zone=public
 --add-rich-rule='rule family="ipv4" source
 address="192.168.1.2/24" 
 port port="80" protocol="tcp" accept'
   
   

 

在 CentOS 6 防火牆 iptables 是以 Rules 寫在 Chain 建立規則然後給 kernel 去執行,每次重建規則必須先清除原有規則,這會導致既有連線中斷。到 CentOS 7 之後改用 firewalld 以 zone 的區域分割觀念來建立,並以動態設定方式執行避免中斷的問題。請注意:不能同時執行 iptables 跟 firewalld 這會造成衝突錯誤。

Firewalld 相關路徑
/etc/firewalld:設定檔路徑
/usr/bin/:firewall-cmd 指令所在的位置
/usr/lib/firewalld/:firewalld 預設的設定資料 (xml 格式),例如 nfs.xml 就定義了 <port protocol="tcp" port="2049"/>

--------------------------------------------------------------------------------

所謂的 zone 就表示主機位於何種環境,需要設定哪些規則,在 firewalld 裡共有 7 個zones
> 先決定主機要設定在那個區域 zone >> 再往該 zone 設定規則 >>> 重新讀取設定檔 sudo firewall-cmd --reload

public: 公開的場所,不信任網域內所有連線,只有被允許的連線才能進入,一般只要設定這裡就可以了
For use in public areas. You do not trust the other computers on the network to not harm your computer. Only selected incoming connections are accepted.
external: 公開的場所,應用在IP是NAT的網路 
For use on external networks with masquerading enabled especially for routers. You do not trust the other computers on the network to not harm your computer. Only selected incoming connections are accepted.
dmz: (Demilitarized Zone) 非軍事區,允許對外連線,內部網路只有允許的才可以連線進來 
For computers in your demilitarized zone that are publicly-accessible with limited access to your internal network. Only selected incoming connections are accepted.
work: 公司、工作的環境 
For use in work areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.
home: 家庭環境 
For use in home areas. You mostly trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.
internal: 內部網路,應用在NAT設定時的對內網路 
For use on internal networks. You mostly trust the other computers on the networks to not harm your computer. Only selected incoming connections are accepted.
trusted: 接受所有的連線
All network connections are accepted.
drop: 任何進入的封包全部丟棄,只有往外的連線是允許的 
Any incoming network packets are dropped, there is no reply. Only outgoing network connections are possible.
block: 任何進入的封包全部拒絕,並以 icmp 回覆對方 ,只有往外的連線是允許的
Any incoming network connections are rejected with an icmp-host-prohibited message for IPv4 and icmp6-adm-prohibited for IPv6. Only network connections initiated from within the system are possible.

-------------------------------------------------------------------------------

預設主機是被放在 public zone 區域,並有開啟兩個服務 dhcpv6-client ssh
> 在這樣的設定下,任何來源都可以透過 ssh 服務來連接到本主機,但其他的服務 service-port 都是關閉的。
★★★ 顯示目前的設定 ★★★
firewall-cmd --list-all
public (default, active)
interfaces: ens160
sources:
services: dhcpv6-client ssh
ports:
masquerade: no
forward-ports:
icmp-blocks:
rich rules:

若你的環境沒在用 DHCP ,則可以將他關掉 DHCP 服務 port
★★★ 關掉 DHCP 服務 port ★★★
sudo firewall-cmd --zone=public --remove-service dhcpv6-client

暫時允許外部連接本機 DNS 服務
★★★ 暫時開啟 DNS port 53 ★★★
sudo systemctl start named
sudo systemctl enable named
sudo firewall-cmd --add-service=dns
sudo firewall-cmd --reload
firewall-cmd --list-all
public (default, active)
interfaces: ens160
sources:
services: dhcpv6-client dns ssh
ports: (略)

★★★ 永久開啟 DNS port 53 ★★★
sudo firewall-cmd --add-service=dns --permanent
sudo firewall-cmd --reload

 

QQ:為何可以直接指定加入的服務名稱為 dns 呢?那他怎麼知道要開啟哪些連接埠?
Ans:他會參考 /usr/lib/firewalld/services/ 下的服務,例如 dns.xml ,啟用本服務就會連帶的開啟 TCP 跟 UDP 的 port 53
<?xml version="1.0" encoding="utf-8"?>
<service>
<short>DNS</short>
<description>The Domain Name System (DNS) is used to provide and request host and domain names. Enable this option, if you plan
to provide a domain name service (e.g. with bind).</description>
<port protocol="tcp" port="53"/>
<port protocol="udp" port="53"/>
</service>
 

總共有這些服務,可以直接叫用
amanda-client.xml high-availability.xml kpasswd.xml mysql.xml pop3s.xml smtp.xml
bacula-client.xml https.xml ldaps.xml nfs.xml postgresql.xml ssh.xml
bacula.xml http.xml ldap.xml ntp.xml proxy-dhcp.xml telnet.xml
dhcpv6-client.xml imaps.xml libvirt-tls.xml openvpn.xml radius.xml tftp-client.xml
dhcpv6.xml ipp-client.xml libvirt.xml pmcd.xml RH-Satellite-6.xml tftp.xml
dhcp.xml ipp.xml mdns.xml pmproxy.xml rpc-bind.xml transmission-client.xml
dns.xml ipsec.xml mountd.xml pmwebapis.xml samba-client.xml vnc-server.xml
ftp.xml kerberos.xml ms-wbt.xml pmwebapi.xml samba.xml wbem-https.xml

 

★★★ 如何修改主機的預設 zone ★★★
前面說過預設為 public zone ,但有些主機服務是要建立在 DMZ 下,我們可以透過修改 /etc/firewalld/firewalld.conf 來將預設的區域改為 dmz
sudo vi /etc/firewalld/firewalld.conf
> 修改 DefaultZone=public
> 變成 DefaultZone=dmz
然後重新載入
sudo firewall-cmd --reload

 

★★★ 加入自行指定的連接埠 ★★★
sudo firewall-cmd --add-port=8080/tcp --permanent
success
sudo firewall-cmd --reload
success
sudo firewall-cmd --list-all
public (default, active)
interfaces: ens160
sources:
services: dhcpv6-client dns ssh
ports: 8080/tcp
masquerade: no

 

QQ:為何我設定暫時的 rules 都無效呢?
ANS:假設你臨時要開放 port 8888,於是你執行了
sudo firewall-cmd --add-port=8888/tcp 
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

卻發現 --list-all 的結果都沒將 port:8888 這 rule 給加入,這是因為你在第二步驟時做了 reload ,不是設定沒用而是被你的 reload 給清除了,所以臨時性的只要
sudo firewall-cmd --add-port=8888/tcp 
sudo firewall-cmd --list-all

查看永久的設定 
firewall-cmd  --list-all --permanent 

 

★★★ 修改服務的預設連接埠 ★★★
假設你的主機為 web /www ,預設是走 port 80 但有時候某些網站就不是使用 80 port ,這時候該怎麼修改呢?
Step 1:先複製對應的 xml 檔到 /etc/firewalld/services
sudo cp /usr/lib/firewalld/services/http.xml  /etc/firewalld/services
Step 2:修改 http.xml
sudo vi /etc/firewalld/services/http.xml
Step 3:修改對應連接埠
<port protocol="tcp" port="80"/>
改為
<port protocol="tcp" port="8080"/>
Step 4:重新載入 
sudo firewall-cmd --reload

 

★★★ 限制某服務只能從哪IP連入 ★★★
通常我們會限制 ssh 只能從某些IP來進來,我們可以使用 rich-rule 來加入
sudo firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.1.88" service name="ssh" accept"
或 ip subnet
sudo firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept"

 

★★★ 限制某 port 只能從哪IP連入 ★★★
sudo firewall-cmd --add-rich-rule="rule family="ipv4" source address="192.168.12.9" port port="8080" protocol="tcp" accept"
注意:port port="8080" 不是寫錯唷!這是他的格式

 

★★★ 直接指定 rule 到 INPUT  chain★★★
sudo firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp -s "192.168.12.9" --dport 22 -j ACCEPT
這樣的寫法使用 # firewall-cmd --list-all 是看不到的,要用 iptables -L -n

 

★★★ 查看預設載入的 rule ★★★
所有的 zone 設定檔會放在 /etc/firewalld/zones 跟 /usr/lib/firewalld/zones/ ,你所執行的 --permanent 參數會寫在 /etc/firewalld/zones 對應的 zone 檔案裡(例:public.xml),所以當你下了
sudo firewall-cmd --add-service=dns --permanent
就會在 /etc/firewalld/zones/public.xml 變成 多了 <service name="dns"/>
<?xml version="1.0" encoding="utf-8"?>
  <zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="dhcpv6-client"/>
  <service name="ssh"/>
  <service name="dns"/>
  <port protocol="tcp" port="8080"/>
</zone>

 

★★★ 從 /etc/sysconfig/iptables 轉為 firewalld 的 direct  ★★★

假設你原有的 /etc/sysconfig/iptables 有規則
-A INPUT -s 140.113.12.9 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp -s 140.113.0.0/16 --dport 123 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -s 140.114.88.0/24 --dport 161 -j ACCEPT
要轉換到 firewalld 的 direct 規則
新增 /etc/firewalld/direct.xml  ,如果你之前有執行過 #sudo firewall-cmd --permanent --direct .... 則這個檔案會自動的產生

新增/修改 direct.xml 增加對應上面的 rules
sudo vi /etc/firewalld/direct.xml
<?xml version="1.0" encoding="utf-8"?>
<direct>
   <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-p tcp -s 192.168.12.9 --dport 22 -j ACCEPT</rule>
   <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-s 140.113.12.9 -j ACCEPT</rule>
   <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-p udp -s 140.113.0.0/16 --dport 123 -j ACCEPT</rule>
   <rule priority="0" table="filter" ipv="ipv4" chain="INPUT">-p tcp -s 140.114.88.0/24 --dport 161 -j ACCEPT</rule>
</direct>

★★★ 從 zone 移除某項服務 ★★★
sudo firewall-cmd --zone=public --add-service=http --permanent 
sudo firewall-cmd --zone=public --remove-service=http --permanent

sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent 
sudo firewall-cmd --zone=public --remove-port=8080/tcp --permanent

 

★★★ port forward 將從某 port number 的封包轉送另外的 port 或其他主機 ★★★
# 將 80 port 收到的訊息轉往 port 8080
sudo firewall-cmd --zone="public" --add-forward-port=port=80:proto=tcp:toport=8080

# 將 80 port 收到的訊息轉往其他台主機的 port 8080
sudo firewall-cmd --zone="public" --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=140.113.1.1

 

Reference:
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Security_Guide/sec-Using_Firewalls.html 
https://www.youtube.com/watch?v=7_XwTdZlqes 
https://www.linode.com/docs/security/firewalls/introduction-to-firewalld-on-centos