# Firewalld 防火牆
###### tags: `主機管理`
> [基於國家 IP 段的資料](https://github.com/herrbischoff/country-ip-blocks)
* 透過 state 可以查看目前運行狀態,如果顯示 running 就表示正常運行
```bash
firewall-cmd --state
```
* 查詢指令用法
```bash
firewall-cmd --help
```
* 查看目前防火牆名單
```bash
firewall-cmd --list-all
```
* 永久設定參數 `--permanent`
* 設定內容
* 針對port
```bash=
firewall-cmd --permanent --add-port=22/TCP
firewall-cmd --permanent --remove-port=22/TCP
```
* 針對連線協定
```bash=
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --remove-service=ssh
```
* 針對特定ip
```bash=
firewall-cmd --permanent --add-source=192.168.1.100
firewall-cmd --permanent --add-source=192.168.1.0/24
firewall-cmd --permanent --remove-source=192.168.1.100
```
* 利用rich rule來進行細節設定
```bash=
#單一IP
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.100' reject"
#除了針對特定單一IP外,再針對特別連線port進行設定
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.100" port protocol="tcp" port="3306" accept'
#針對IP範圍
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' reject"
```
* 規則整合作法
* ipset (IP清單整合)
* 簡易指令介紹
```bash
# 新增一個自己定義的ip清單,例如ssh_ip_set
# 如果hash:ip改成hash:net,則可以允許設定網段,例如:192.168.0.0/24
firewall-cmd --permanent --new-ipset=ssh_ip_set --type=hash:ip
# 新增一個ssh_ip_set白名單可以登入ssh的
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source ipset='ssh_ip_set' port protocol='tcp' port='22' accept"
# 查詢目前的IP清單
firewall-cmd --ipset=ssh_ip_set --get-entries
# 新增白名單
firewall-cmd --permanent --ipset=ssh_ip_set --add-entry=192.168.0.1
# 移除白名單
firewall-cmd --permanent --ipset=ssh_ip_set --remove-entry=192.168.0.1
```
* 開放SSH管理腳本
```bash
#!/bin/bash
# 檢查 root 權限
if [[ $EUID -ne 0 ]]; then
echo "請以 root 權限執行此腳本"
exit 1
fi
IPSET_NAME="ssh_whitelist"
# 初始化:如果 ipset 不存在則建立
init_ipset() {
if ! firewall-cmd --get-ipsets | grep -q "$IPSET_NAME"; then
echo "正在初始化 $IPSET_NAME..."
firewall-cmd --permanent --new-ipset=$IPSET_NAME --type=hash:ip
# 建立規則關聯(只針對此 ipset 開放 port 22)
firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source ipset='$IPSET_NAME' port protocol='tcp' port='22' accept"
firewall-cmd --reload
echo "初始化完成。"
fi
}
# 執行初始化
init_ipset
while true; do
echo "========================================"
echo " Firewalld SSH 白名單管理 (IPSet)"
echo "========================================"
echo "1) 查看目前白名單"
echo "2) 新增 IP 到白名單"
echo "3) 移除 IP 從白名單"
echo "4) 重新載入防火牆 (Reload)"
echo "q) 離開"
read -p "請選擇操作 [1-4/q]: " choice
case $choice in
1)
echo "--- 目前授權的 IP 清單 ---"
firewall-cmd --ipset=$IPSET_NAME --get-entries
echo "--------------------------"
;;
2)
read -p "請輸入要新增的 IP: " target_ip
if [[ $target_ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
firewall-cmd --permanent --ipset=$IPSET_NAME --add-entry=$target_ip
firewall-cmd --reload
echo "✅ 已新增 $target_ip 並重新載入。"
else
echo "❌ IP 格式不正確。"
fi
;;
3)
read -p "請輸入要移除的 IP: " target_ip
firewall-cmd --permanent --ipset=$IPSET_NAME --remove-entry=$target_ip
firewall-cmd --reload
echo "⚠️ 已移除 $target_ip 並重新載入。"
;;
4)
firewall-cmd --reload
echo "🔄 防火牆已重新載入。"
;;
q)
echo "結束管理。"
exit 0
;;
*)
echo "無效選項,請重新輸入。"
;;
esac
echo ""
done
```
* self-defined services (Port服務整合)
```bash
# 創建 ports 清單
firewall-cmd --permanent --new-service=guardium-ports
# 增加 ports 清單的內容
firewall-cmd --permanent --service=guardium-ports --add-port=16016-16021/tcp
firewall-cmd --permanent --service=guardium-ports --add-port=8081/tcp
firewall-cmd --permanent --service=guardium-ports --add-port=9800-9801/tcp
# 查看 ports 清單的內容
firewall-cmd --permanent --info-service=guardium-ports
# 新增guardium-ports的防火牆規則
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="140.130.2.141" service name="guardium-ports" accept'
```
* 重新載入防火牆規則
> 每次重新設定防火牆後,firewalld 並不會自動生效,需要透過 reload 重新載入規則讓設定生效
```bash
firewall-cmd --reload
```