隨著網路架構日益複雜,手動管理防火牆和 ACL 變得越來越困難,自動化已成為提升效率和降低錯誤的關鍵。本文提供的 Python 指令碼和範例,結合 Netmiko 和 Nornir 等工具,可自動化執行防火牆服務管理、區域組態、服務與埠號設定等任務。此外,文章也示範瞭如何使用 Jinja2 範本引擎,根據預先定義的規則自動生成 ACL 組態,簡化網路安全管理流程,並確保組態的一致性和可維護性。透過自動化,工程師可以更專注於網路安全策略的制定和最佳化,而非繁瑣的重複性手動操作。

自動化管理防火牆服務與設定

在現代的伺服器管理中,自動化是提升效率和減少錯誤的關鍵。本文將介紹如何使用Python和Netmiko函式庫來自動化管理多台伺服器上的防火牆服務,包括啟動或停止firewalld服務、管理系統啟動時的服務狀態,以及組態防火牆區域。

連線伺服器與管理防火牆服務

首先,我們定義了一個server_connection函式,用於建立與伺服器的連線。這個函式接受一個IP位址作為引數,並傳回一個Netmiko連線物件。

def server_connection(ip):
    device = {"host": ip, "username": "ubuntu", "password": "ubuntu", "device_type": "linux", "secret": "ubuntu"}
    net_connect = Netmiko(**device)
    return net_connect

內容解密:

  • device字典包含了連線伺服器所需的資訊,如主機IP、使用者名稱、密碼、裝置型別和特權密碼。
  • Netmiko(**device)建立了一個到伺服器的連線,並傳回這個連線物件。

啟動或停止firewalld服務

我們定義了兩個函式,start_firewalldstop_firewalld,用於在連線的伺服器上啟動或停止firewalld服務。這些函式使用server_connection函式建立連線,並透過讀取預先準備的文字檔案來傳送組態命令。

def start_firewalld(ip):
    connection = server_connection(ip)
    output = connection.send_config_from_file("start_firewalld.txt", read_timeout=1000)
    print(output)

def stop_firewalld(ip):
    connection = server_connection(ip)
    output = connection.send_config_from_file("stop_firewalld.txt", read_timeout=1000)
    print(output)

內容解密:

  • connection.send_config_from_file方法從指定的文字檔案中讀取命令並在伺服器上執行。
  • read_timeout=1000設定了讀取超時時間,以確保命令執行的可靠性。

管理系統啟動時的服務狀態

我們還定義了兩個函式,enable_service_on_bootdisable_service_on_boot,用於在系統啟動時啟用或停用指定的服務。

def enable_service_on_boot(ip):
    service = "firewalld"
    connection = server_connection(ip)
    connection.send_config_set(f"systemctl enable {service}", read_timeout=1000)
    output = connection.send_command(f"systemctl list-unit-files --type=service | grep {service}")
    print(output)

def disable_service_on_boot(ip):
    service = "firewalld"
    connection = server_connection(ip)
    connection.send_config_set(f"systemctl disable {service}", read_timeout=1000)
    output = connection.send_command(f"systemctl list-unit-files --type=service | grep {service}")
    print(output)

內容解密:

  • connection.send_config_set方法用於執行特定的組態命令,如啟用或停用服務。
  • connection.send_command方法用於執行命令並取得輸出,如列出服務的狀態。

平行執行任務

為了提高效率,我們使用了ThreadPoolExecutor來平行執行任務。這允許我們同時對多台伺服器進行操作。

with ThreadPoolExecutor(max_workers=5) as executor:
    result = executor.map(enable_service_on_boot, host)

內容解密:

  • max_workers=5指定了最大工作執行緒數,即同時對5台伺服器進行操作。
  • executor.map方法將指定的函式應用於主機列表中的每一台伺服器。

組態防火牆區域

firewalld服務提供了多個預定義的區域,如public、trusted和drop等,用於不同的網路環境。我們可以使用firewall-cmd命令來管理和查詢這些區域。

root@Server-1:/home/ubuntu# firewall-cmd --get-zones
block dmz drop external home internal nm-shared public trusted work

firewall-cmd 指令詳解與應使用案例項

firewall-cmd 是 Linux 系統中用於管理防火牆的強大工具,透過此指令可以對防火牆進行組態和管理。以下將詳細介紹其常用引數和實際應用案例。

檢查與管理防火牆狀態

首先,我們可以使用以下指令檢查 firewall-cmd 的版本和服務狀態:

firewall-cmd --version
firewall-cmd --state

內容解密:

  • --version 引數用於檢查當前 firewall-cmd 的版本,確保我們使用的工具是最新的或是符合需求的版本。
  • --state 引數用於檢查防火牆服務的當前狀態,確認服務是否正在執行。

管理 Zone 與介面

在防火牆組態中,Zone 是用來定義不同網路介面或來源 IP 的信任級別。以下是一些常用的 Zone 管理指令:

firewall-cmd --get-zones
firewall-cmd --list-all-zones
firewall-cmd --get-default-zone
firewall-cmd --set-default-zone=internal

內容解密:

  • --get-zones 列出系統中所有可用的 Zone 名稱。
  • --list-all-zones 顯示所有 Zone 的詳細組態資訊。
  • --get-default-zone 查詢目前預設的 Zone。
  • --set-default-zone=internal 將預設 Zone 設定為 internal。

查詢與設定介面所屬 Zone

若要查詢特定介面所屬的 Zone 或將介面加入特定的 Zone,可以使用以下指令:

firewall-cmd --get-zone-of-interface=ens33
firewall-cmd --zone=home --change-interface=eth0

內容解密:

  • --get-zone-of-interface=ens33 查詢 ens33 介面所屬的 Zone。
  • --change-interface=eth0 將 eth0 介面變更至 home Zone。

開啟與關閉服務及埠號

在特定 Zone 中開啟或關閉服務及埠號是防火牆組態中的常見需求。例如,若要允許 HTTP 服務,可以使用以下指令:

firewall-cmd --zone=public --add-service=http
firewall-cmd --zone=public --add-port=80/tcp

內容解密:

  • --add-service=http 在 public Zone 中新增允許 HTTP 服務。
  • --add-port=80/tcp 在 public Zone 中新增允許 TCP 協定的 80 埠號。

相對地,若要移除已新增的服務或埠號,可以使用 --remove-service--remove-port 引數:

firewall-cmd --zone=public --remove-service=http
firewall-cmd --zone=public --remove-port=80/tcp

內容解密:

  • --remove-service=http 從 public Zone 中移除 HTTP 服務。
  • --remove-port=80/tcp 從 public Zone 中移除 TCP 協定的 80 埠號。

使設定永久生效與重新載入組態

為了確保防火牆的組態在重啟後仍然生效,需要使用 --permanent 引數。同時,使用 --reload 引數可以重新載入防火牆組態,使變更立即生效。

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

內容解密:

  • --permanent 使後續的組態變更永久生效。
  • --reload 重新載入防火牆組態,使變更立即生效。

建立新的 Zone 與組態範例

若需要建立新的 Zone,可以使用 --new-zone 引數,並結合 --permanent 使其在重啟後仍然存在。

firewall-cmd --new-zone=test123 --permanent
firewall-cmd --reload

內容解密:

  • --new-zone=test123 建立一個名為 test123 的新 Zone。
  • 結合 --permanent 確保新建立的 Zone 在重啟後仍然存在。

自動化組態範例

以下是一個使用 Jinja2 範本引擎與 YAML 檔案自動化組態防火牆的範例:

  1. 首先,安裝必要的 Python 模組,包括 netmikojinja2pyyaml
  2. 建立 info.yaml 檔案,定義所需的變數:

new_zone:

  • test interface:
  • lo service:
  • http
3. 建立 `command_list.txt` 檔案,使用 Jinja2 範本語法:

firewall-cmd –new-zone={{ new_zone[0] }} –permanent firewall-cmd –reload firewall-cmd –get-zones

4. 編寫 Python 指令碼讀取 YAML 檔案並結合 Jinja2 範本生成最終的命令:
   ```python
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load

def from_jinja():
    env = Environment(loader=FileSystemLoader("."))
    template = env.get_template("command_list.txt")
    with open("info.yaml") as r:
        data = safe_load(r)
    command = template.render(data).split('\n')
    return command

commands = from_jinja()
for cmd in commands:
    print(cmd)

內容解密:

此範例展示如何利用 Jinja2 範本引擎和 YAML 組態檔案自動生成 firewall-cmd 指令,用於建立新的 Zone、重新載入組態以及查詢現有的 Zones。透過這種方式,可以輕鬆地實作防火牆組態的自動化管理。

網路裝置防火牆組態與ACL管理

在現代網路架構中,防火牆組態和存取控制列表(ACL)管理是確保網路安全的重要環節。本文將介紹如何使用Python和相關模組(如Netmiko和Nornir)來自動化防火牆組態和ACL管理。

防火牆區域組態

首先,我們來看看如何使用Python指令碼組態防火牆區域。以下是一個範例程式碼,展示瞭如何使用Netmiko模組連線到Linux伺服器並組態防火牆區域。

程式碼範例

from netmiko import Netmiko
from jinja2 import Environment, FileSystemLoader
from yaml import safe_load

def from_jinja():
    env = Environment(loader=FileSystemLoader("."))
    template = env.get_template("command_list.txt")
    with open("info.yml") as r:
        data = safe_load(r)
    command = template.render(data).split("\n")
    return [command, data]

def add_zone(ip):
    device = {"host": ip, "username": "ubuntu", "password": "ubuntu", "device_type": "linux", "secret": "ubuntu"}
    net_connect = Netmiko(**device)
    commands = from_jinja()[0]
    net_connect.send_config_set(commands, read_timeout=1000)
    return net_connect

def zone_configuration(ip):
    interface = "lo"
    data = from_jinja()[1]
    new_zone = data["new_zone"]
    commands = [
        f"firewall-cmd --permanent --zone={new_zone} --change-interface={interface}",
        "firewall-cmd --reload",
        "firewall-cmd --get-active-zones",
        f"sudo firewall-cmd --zone={new_zone} --add-service=http",
        f"sudo firewall-cmd --zone={new_zone} --add-port=80/tcp",
        f"firewall-cmd --zone={new_zone} --add-forward-port=port=80:proto=udp:toport=8080:toaddr=10.10.10.1"
    ]
    connect = add_zone(ip)
    connect.send_config_set(commands)
    out = connect.send_config_set(f"sudo firewall-cmd --list-all --zone={new_zone}")
    print(out)

zone_configuration("192.168.163.135")

內容解密:

  1. from_jinja() 函式使用 Jinja2 範本引擎渲染命令,並從 YAML 檔案中讀取資料。
  2. add_zone(ip) 函式建立到 Linux 伺服器的連線,並傳送組態命令以建立新的防火牆區域。
  3. zone_configuration(ip) 函式組態新的防火牆區域,包括更改介面、新增服務和埠轉發規則。
  4. 最後,呼叫 zone_configuration("192.168.163.135") 函式執行防火牆區域組態。

網路裝置ACL組態

接下來,我們來看看如何使用Nornir框架和Jinja2範本引擎組態網路裝置的ACL。

ACL規則範例

序列號允許/拒絕協定源IP目標IP引數
10denyip10.11.0.0/16192.32.0.0/16--
20denyip15.12.0.0/16192.12.0.0/16--
30permitip120.1.0.0/16192.168.0.0/16--
40permittcp10.1.1.0/24172.16.1.0/24eqtelnet
50permitip140.1.0.0/16192.168.0.0/16--
90denypimanyanydscpcs1
100denyipanyany--

程式碼範例(部分)

from nornir import InitNornir
from nornir.plugins.tasks.networking import netmiko_send_config
from jinja2 import Environment, FileSystemLoader

def configure_acl(task):
    env = Environment(loader=FileSystemLoader("."))
    template = env.get_template("acl_commands.txt")
    acl_commands = template.render(data=task.host.data)
    task.run(netmiko_send_config, config_commands=acl_commands.split("\n"))

nr = InitNornir(config_file="config.yaml")
nr.run(task=configure_acl)

內容解密:

  1. 使用 Nornir 初始化網路裝置連線。
  2. 定義 configure_acl 任務,使用 Jinja2 範本引擎渲染 ACL 組態命令。
  3. 使用 netmiko_send_config 外掛傳送 ACL 組態命令到網路裝置。