2017-09-25

firewalld - CentOS 7 的動態防火牆

如同先前在 [完全用 GNU/Linux 工作] 07. 簡易的防火牆一文提到,Ubuntu 從 8.04 LTS 開始多了 ufw 這個簡單的防火牆,CentOS 也在 7.0 導入可以動態管理防火牆的 firewalld。Weithenn 前輩的 CentOS 7.3 基礎設定 (10) - 調整 Firewalld 防火牆規則一文很好的解說了 firewalld 與 iptables 的差異,想深入了解的伙伴不妨參考一下。

firewalld 還有個跟 Windows 7 類似的網路共用設定機制,在官方文件中是使用界域 1 (zone) 來敘述這項依據不同環境所設計的網路區域功能。我們可以藉由在各種不同的 zone 進行設置,來達到公開網域 (public network zone) 不開 ssh 埠口,而內部網域 (internal network zone) 則允許等較複雜的信任等級配置。這部份凍仁還未深入研究,在此就不多加說明。

1. 安裝與初始化

1.1. 若系統未預載,請手動安裝 firewalld
[ jonny@CentOS ~ ]
$ sudo yum install firewalld [Enter]

1.2. 檢查 firewalld 服務運行狀態。
[ jonny@CentOS ~ ]
$ systemctl status firewalld [Enter]
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: active (running) since Sun 2017-09-24 09:03:55 UTC; 14min ago
     Docs: man:firewalld(1)
 Main PID: 4376 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─4376 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid 

1.3. 若狀態不為 active,則啟動 (start) 它。firewalld 預設會開 ssh 服務,不用再擔心啟動防火牆時,會被 iptables 擋在牆外了!
[ jonny@CentOS ~ ]
$ sudo systemctl start firewalld [Enter]

1.4. 若需開機自動啟動,則還需啟用 (enable) 它。
[ jonny@CentOS ~ ]
$ sudo systemctl enable firewalld [Enter]
Created symlink from /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service to /usr/lib/systemd/system/firewalld.service.
Created symlink from /etc/systemd/system/basic.target.wants/firewalld.service to /usr/lib/systemd/system/firewalld.service.

2. 基礎操作

2.1. 狀態 (state) 查詢,running 表示正常運行中。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --state [Enter]
running

2.2. 新增允許 HTTP 服務連線規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-service=http --permanent [Enter]
success

2.3. 新增允許 10050 埠口 TCP 連線規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-port=10050/tcp --permanent [Enter]
success

2.4. 刪除允許 dhcpv6-client 服務連線規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --remove-service=dhcpv6-client \
    --permanent [Enter]
success

2.5. 刪除允許 10050 埠口的 TCP 連線規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --remove-port=10050/tcp --permanent [Enter]
success

2.6. 重新讀取防火牆規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --reload [Enter]
success

2.7. 列出當前的防火牆規則:眼尖的客官可以發現,以下範例為 public 這個 network zone 的配置。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --list-all [Enter]
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s3
  sources:
  services: http ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

3. 進階使用

3.1. 允許 (accept) 特定 IP 連線

3.1.1. 允許來自 192.168.1.2 的所有連線。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-rich-rule 'rule family="ipv4" \
    source address="192.168.1.2/32" accept' --permanent [Enter]

3.1.2. 允許來自 192.168.2.1 ~ 192.168.2.254 的所有 ssh 連線。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-rich-rule 'rule family="ipv4" \
    source address="192.168.2.0/24" service name="ssh" accept' \
   --permanent [Enter]

3.2. 拒絕 (reject) 或阻擋 (drop) 特定 IP 連線

3.2.1. 拒絕來自 110.88.4.5 的連線。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-rich-rule 'rule \
    family="ipv4" source address="110.88.4.5/32" reject' \
    --permanent [Enter]

3.2.2. 阻擋來自 27.16.3.1 ~ 27.16.3.254 的 22 埠口連線。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-rich-rule 'rule \
    family="ipv4" source address="27.16.3.0/24" port port="22" \
    drop' --permanent [Enter]

3.3. 允許特定埠口連線

3.3.1. 允許 32700 到 33000 埠口的 TCP 連線規則。
[ jonny@CentOS ~ ]
$ sudo firewall-cmd --add-port=32700-33000/tcp --permanent [Enter]

3.4. 圖形化介面

大家可另外安裝 firewall-config 套件進行操作。
[ jonny@CentOS ~ ]
$ sudo yum install firewall-config [Enter]

近來凍仁總覺得 CentOS 7 的 firewalld 有些用不慣,索性參照之前 ufw 的筆記,把常用的 firewalld 防火牆指令整理了一下,將來有遇上比較特殊的用法再補上了。

1 經友人 Cheng-Chia Tseng 回饋,GNU/Linux 官方是使用「界域」一詞來形容此項功能。然而很棒的一點是在 20.1.4 防火牆簡易設定 | 鳥哥的 Linux 私房菜一文也有很完整的解說呢!

站內連結:
[完全用 GNU/Linux 工作] 07. 簡易的防火牆 - ufw

相關連結:
4.5. 使用防火墙 - Red Hat Customer Portal
CentOS 7.3 基礎設定 (10) - 調整 Firewalld 防火牆規則 | 不自量力 の Weithenn
20.1.4 防火牆簡易設定 | 鳥哥的 Linux 私房菜
gnome - Can I install a GUI for firewalld? | Ask Ubuntu

資料來源:
Firewalld | FedoraProject
Chapter 5. Using Firewalls | Red Hat Customer Portal
Blocking IP addresses using Firewalld rhel 7.0 | Red Hat Customer Portal
CentOS 7 Firewalld 防火牆說明介紹 @ 黃昏的甘蔗

3 則留言 :

  1. 近來常常用到 `sudo firewall-cmd --add-interface --zone=internal` 的部份,再找機會補上了。

    回覆刪除
  2. # Drop all 10050 port, and allow this port on specific ip address

    Thanks someone feedback, if we want to use drop by default, and allow specific port on specific ip address, we can do something like this.

    ## User Story

    As the firewalld user, we want use rich rules to setting firewall, so than we can drop all 10050 port and only allow this port on specific ip address

    ## Workflow:

    1. List the drop zone.

     ```
     [root@ansible-node ~]# firewall-cmd --list-all --zone=drop
     drop (active)
      target: DROP
      icmp-block-inversion: no
      interfaces:
      sources:
      services:
      ports:
      protocols:
      masquerade: no
      forward-ports:
      sourceports:
      icmp-blocks:
      rich rules:
     ```

    2. Add ssh service into drop zone.

     ```
     [root@ansible-node ~]# firewall-cmd --add-service=ssh --zone=drop --permanent
     success
     
     [root@ansible-node ~]# firewall-cmd --reload
     success
     
     [root@ansible-node ~]# firewall-cmd --list-all --zone=drop
     drop (active)
      target: DROP
      icmp-block-inversion: no
      interfaces:
      sources:
      services: ssh
      ports:
      protocols:
      masquerade: no
      forward-ports:
      sourceports:
      icmp-blocks:
      rich rules:
     ```

    3. Add the `eth0` into `drop` zone.

     ```
     [root@ansible-node ~]# firewall-cmd --add-interface=eth0 --zone=drop --permanent
     success
     
     [root@ansible-node ~]# firewall-cmd --list-all --zone=drop
     drop (active)
      target: DROP
      icmp-block-inversion: no
      interfaces: eth0
      sources:
      services: ssh
      ports:
      protocols:
      masquerade: no
      forward-ports:
      sourceports:
      icmp-blocks:
      rich rules:
     ```

    4. Allow specific ip address and port.

     ```
     [root@ansible-node ~]# firewall-cmd --add-rich-rule 'rule family="ipv4" source address="x.x.x.x/32" port port="10050" protocol="tcp" accept' --zone=drop --permanent
     success
     
     [root@ansible-node ~]# firewall-cmd --reload
     success
     
     [root@ansible-node ~]# firewall-cmd --list-all --zone=drop
     drop (active)
      target: DROP
      icmp-block-inversion: no
      interfaces: eth0
      sources:
      services: ssh
      ports:
      protocols:
      masquerade: no
      forward-ports:
      sourceports:
      icmp-blocks:
      rich rules:
         rule family="ipv4" source address="x.x.x.x/32" port port="10050" protocol="tcp" accept
     ```

    5. Done.

    回覆刪除
  3. 除了使用 `--add-interface` 參數將網卡加到特定的 zone 外,也可使用 `--change-interface` 來切換 zone。

    Example:

    ```
    $ sudo firewall-cmd --change-interface eth0 --zone=internal --permanent
    ```

    ----

    補充說明:

    http://note.drx.tw/2017/09/the-firewalld-on-centos-7.html?showComment=1526356041259#c461577478493613334 提到的 `--add-interface` 漏掉了 interface 的部份。

    ```
    $ sudo firewall-cmd --add-interface eth0 --zone=internal --permanent
    ```

    回覆刪除

喜歡這篇文章嗎?歡迎在底下留言讓凍仁知道。😉