我最近在建構一個高效能網路自動化實驗室,過程中累積了一些 Python 自動化和 SSH 管理的實戰經驗,想在此分享給大家。
首先,我將示範如何使用 Python 和 Paramiko 函式庫實作網路裝置時間和時區的自動化設定,並分享我如何逐步最佳化程式碼結構和資料組織方式。
import paramiko
import time
import json
# 裝置資訊,使用字典列表儲存,每個字典代表一個裝置
devices = [
{'ip': '192.168.127.3', 'hostname': 'R1'},
{'ip': '192.168.127.4', 'hostname': 'R2'},
{'ip': '192.168.127.101', 'hostname': 'SW1'},
{'ip': '192.168.127.102', 'hostname': 'SW2'},
{'ip': '192.168.127.133', 'hostname': 'R3'}
]
username = 'blackcat'
password = 'cisco123'
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for device in devices:
try:
ssh_client.connect(hostname=device['ip'], username=username, password=password, look_for_keys=False, timeout=5)
print(f"成功連線到 {device['hostname']} ({device['ip']})")
conn = ssh_client.invoke_shell()
conn.send("conf t\n")
conn.send("clock timezone AEST +10\n")
conn.send("clock summer-time AEST recurring 1 0 2 10 2 0 2\n") # 設定夏令時間
conn.send("end\n")
time.sleep(2) # 等待指令執行完成
output = conn.recv(65535).decode('utf-8') # 取得設定結果
print(f"{device['hostname']} 設定結果:\n{output}")
ssh_client.close()
except Exception as e:
print(f"無法連線到 {device['hostname']} ({device['ip']}):{e}")
# 將裝置資訊轉換為 JSON 格式
json_devices = json.dumps(devices, indent=4)
print(f"\nJSON 格式的裝置資訊:\n{json_devices}")
這段程式碼使用迴圈迭代 devices
列表,利用 Paramiko 連線到每個裝置,並設定時間和時區。我加入了錯誤處理機制 try...except
,以及 timeout
引數來避免程式卡住。此外,我使用 conn.recv()
接收並顯示設定結果,方便除錯。最後,程式碼將 devices
列表轉換為 JSON 格式字串並輸出。
graph LR C[C] A[Python Script] --> B(Paramiko); B --> C{SSH Connection}; C -- Success --> D[Configure Time/Timezone]; C -- Fail --> E[Error Handling];
此流程圖描述了 Python 指令碼使用 Paramiko 連線到 SSH 伺服器的過程,包含成功設定時間和時區,以及連線失敗時的錯誤處理。
接下來,我將分享如何使用 NMAP 掃描 SSH 連線埠,並分析潛在的安全風險。
nmap -p 22 --script ssh-auth-methods,ssh2-enum-algos <目標主機>
這個 NMAP 指令結合了 ssh-auth-methods
和 ssh2-enum-algos
兩個指令碼,一次性檢測 SSH 驗證方法和支援的演算法,提升效率。<目標主機>
應該替換成實際的 IP 位址或網域名稱。
最後,我將探討一個常見的 SSH 連線問題:「No matching cipher found」,並提供解決方案。這個錯誤訊息通常表示客戶端和伺服器端支援的加密演算法不比對。我的解決方案是調整伺服器端的 SSH 設定,使其支援更廣泛的加密演算法,或者調整客戶端使用的演算法。
sequenceDiagram participant Client participant Server Client->>Server: Client Hello (Cipher Suites) Server->>Client: Server Hello (Chosen Cipher Suite) alt Cipher Suite Match Client->>Server: Key Exchange Server->>Client: Key Exchange Client->>Server: Encrypted Data Server->>Client: Encrypted Data else Cipher Suite Mismatch Server->>Client: Alert (No Matching Cipher) Client->>Server: Connection Closed end
這個序列圖更詳細地展示了 SSH 連線建立的流程,包含客戶端和伺服器端交換加密演算法的過程,以及當演算法不比對時發生的錯誤情況。
透過以上分享,我希望我的實務經驗能幫助大家更好地運用 Python 網路自動化技術,並提升 SSH 連線的安全性與穩定性。
在現代網路管理中,時間同步扮演著至關重要的角色,舉凡日誌記錄、安全機制、排程任務等,都仰賴精確的時間戳記。當網路裝置的時間不同步時,可能導致系統錯誤、安全漏洞,甚至影響營運效率。因此,有效管理和設定網路時間協定 (NTP) 伺服器,是確保網路穩定執行的關鍵任務。
我經常需要管理大量的網路裝置,手動設定每台裝置的 NTP 伺服器既費時又容易出錯。因此,我開發了一套 Python 自動化指令碼,可以快速與有效地完成這項工作。
確認 SSH 與 NTP 連線埠狀態
在開始之前,我習慣先確認目標裝置的 SSH (TCP 22) 和 NTP (UDP 123) 連線埠是否暢通。我會使用 nmap
進行掃描:
nmap -p 22 192.168.1.10 192.168.1.20 # 確認 SSH 連線埠
nmap -p 123 -sU 192.168.1.10 192.168.1.20 192.168.1.100 # 確認 NTP 連線埠 (-sU 代表 UDP)
若連線埠狀態顯示 closed
,可能是設定有誤或防火牆阻擋。filtered
通常表示防火牆過濾了連線。
除了 nmap
,我也會直接登入裝置,使用以下指令檢查:
show ip interface brief # 顯示介面狀態和 IP 位址
show ntp status # 顯示 NTP 狀態
NTP 伺服器狀態檢查與設定
確保 NTP 伺服器本身運作正常非常重要。以下是我常用的檢查和設定指令:
timedatectl status # 檢查系統時間狀態
timedatectl set-ntp true # 啟用 NTP 同步
firewall-cmd --zone=public --add-port=123/udp --permanent # 開放防火牆 UDP 123 連線埠
firewall-cmd --reload # 重新載入防火牆設定
Python 自動化指令碼:設定 NTP 伺服器
以下 Python 指令碼使用 paramiko
模組,透過 SSH 遠端設定網路裝置的 NTP 伺服器:
import paramiko
import time
import getpass # 安全地取得密碼
username = input("請輸入使用者名稱:")
password = getpass.getpass("請輸入密碼:")
devices = ['192.168.1.10', '192.168.1.20'] # 裝置 IP 位址列表
ntp_server = '192.168.1.100' # NTP 伺服器 IP 位址
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for ip in devices:
try:
client.connect(ip, username=username, password=password, look_for_keys=False, timeout=5) # 設定連線逾時
print(f"已連線至 {ip}")
shell = client.invoke_shell()
shell.send("configure terminal\n")
shell.send(f"ntp server {ntp_server}\n") # 設定 NTP 伺服器
shell.send("end\n")
shell.send("wr mem\n") # 儲存設定
time.sleep(2)
output = shell.recv(65535).decode()
print(output)
print("-" * 80)
client.close()
except paramiko.AuthenticationException:
print(f"驗證失敗:{ip}")
except paramiko.SSHException as e:
print(f"SSH 連線錯誤:{ip} - {e}")
except Exception as e:
print(f"其他錯誤:{ip} - {e}")
此指令碼迭代處理 devices
列表中的每個 IP 位址。它使用 paramiko
建立 SSH 連線,並透過 invoke_shell()
建立互動式 shell,以便依序傳送指令。f-string
格式化字串,將 NTP 伺服器 IP 位址嵌入指令中。wr mem
指令儲存設定。try...except
塊處理各種潛在錯誤,例如驗證失敗、SSH 連線錯誤等,提升程式碼的穩健性。getpass
模組安全地取得密碼,避免在程式碼中直接寫入密碼。
graph LR B[B] C[C] A[開始] --> B{取得使用者名稱和密碼}; B --> C{迴圈處理每個裝置 IP}; C --> D[建立 SSH 連線]; D -- 成功 --> E[設定 NTP 伺服器]; E --> F[儲存設定]; F --> G[關閉連線]; D -- 失敗 --> H[顯示錯誤訊息]; H --> G; G --> I[結束];
**圖表説明:**此流程圖展示了程式碼的執行流程,從取得使用者認證到設定 NTP 伺服器,最後結束迴圈。
sequenceDiagram participant 使用者 participant Python 指令碼 participant 網路裝置 使用者->>Python 指令碼: 提供使用者名稱和密碼 loop 每個裝置 IP Python 指令碼->>網路裝置: 建立 SSH 連線 alt 連線成功 Python 指令碼->>網路裝置: 設定 NTP 伺服器 Python 指令碼->>網路裝置: 儲存設定 網路裝置-->>Python 指令碼: 回傳設定結果 Python 指令碼->>網路裝置: 關閉連線 else 連線失敗 網路裝置-->>Python 指令碼: 回傳錯誤訊息 end end
**圖表説明:**此循序圖詳細描述了使用者、Python 指令碼和網路裝置之間的互動流程,更清晰地呈現了程式碼的執行步驟。
透過這個 Python 自動化指令碼,我可以輕鬆管理多台網路裝置的 NTP 設定,大幅提升了工作效率,同時也降低了人為錯誤的風險。
#!/usr/bin/env python3
import time
import paramiko
from datetime import datetime
from getpass import getpass
t_ref = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
def get_credentials():
"""取得使用者認證資訊"""
username = input("* 輸入網路管理員帳號 : ")
password = None
while not password:
password = getpass("* 輸入網路管理員密碼 : ")
password_verify = getpass("** 確認網路管理員密碼 : ")
if password != password_verify:
print("! 網路管理員密碼不符,請重新輸入。")
password = None
return username, password
def backup_config(device_ip, username, password):
"""備份裝置設定"""
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(device_ip, username=username, password=password)
shell = ssh_client.invoke_shell()
shell.send("enable\n") # 進入特權模式
shell.send("terminal length 0\n") # 設定終端輸出長度為 0,避免分頁顯示
time.sleep(1)
shell.send("show running-config\n")
time.sleep(5) # 等待指令執行完成
output = shell.recv(65535).decode() # 接收設定檔內容
ssh_client.close()
# 將設定檔儲存到檔案
filename = f"backup_{device_ip}_{t_ref}.cfg"
with open(filename, "w") as f:
f.write(output)
print(f"{device_ip} 設定已備份至 {filename}。")
except Exception as e:
print(f"無法備份 {device_ip} 設定:{e}")
if __name__ == "__main__":
username, password = get_credentials()
device_ips = []
while True:
device_ip = input("輸入裝置 IP 地址 (或輸入 'done' 完成輸入): ")
if device_ip.lower() == 'done':
break
device_ips.append(device_ip)
for device_ip in device_ips:
backup_config(device_ip, username, password)
print("備份程式完成。")
這個程式碼整合了先前的使用者認證和計時工具,並新增了備份設定的功能。get_credentials()
函式用於取得使用者認證資訊。backup_config()
函式使用 paramiko
連線到裝置,執行 show running-config
指令,並將輸出儲存到檔案。主程式會先取得使用者認證,然後提示使用者輸入多個裝置 IP,最後逐一備份每個裝置的設定。加入了 enable
指令進入特權模式,以及terminal length 0
指令避免分頁顯示,確保完整備份設定檔。
graph LR D[D] A[使用者輸入認證] --> B{驗證認證}; B -- 成功 --> C[輸入裝置 IP]; C --> D{SSH 連線到裝置}; D -- 成功 --> E[執行 show running-config]; E --> F[儲存設定檔]; F --> G[備份完成];
**圖表説明:**此流程圖描述了互動式備份指令碼的執行流程,從使用者輸入認證資訊開始,到成功備份設定檔結束。
sequenceDiagram participant User participant Script participant Device User->>Script: 輸入帳號密碼 activate Script Script->>Script: 驗證帳號密碼 Script->>User: 輸入裝置 IP User->>Script: 裝置 IP Script->>Device: SSH 連線 activate Device Device-->>Script: 連線成功 Script->>Device: 執行 show running-config Device-->>Script: 設定檔內容 deactivate Device Script->>Script: 儲存設定檔 deactivate Script Script-->>User: 備份完成
**圖表説明:**此序列圖詳細展示了使用者、指令碼和裝置之間的互動過程,更清晰地呈現了備份流程的每一步驟。
在現今複雜的網路環境中,維護大量網路裝置的設定檔至關重要。手動備份不僅耗時費力,還容易出錯。因此,自動化網路裝置備份成為提升效率和可靠性的關鍵。本文將以 Python 的 Paramiko 函式庫為例,示範如何開發一個自動化備份方案,簡化網路管理流程。
import time
import paramiko
from datetime import datetime
import getpass
# 取得目前時間戳記,用於備份檔案命名
t_ref = datetime.now().strftime("%Y%m%d%H%M%S")
# 裝置 IP 列表
device_list = ["192.168.1.1", "192.168.1.2", "192.168.1.3"]
# 使用者名稱和密碼
username = input("請輸入使用者名稱:")
password = getpass.getpass("請輸入密碼:")
def get_credentials():
global username, password
start_timer = time.mktime(time.localtime())
get_credentials()
for ip in device_list:
print(t_ref)
print(f"正在登入 {ip}")
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh_client.connect(hostname=ip, username=username, password=password, look_for_keys=False)
print(f"成功連線至 {ip}\n")
print(f"正在備份 {ip} 的執行組態\n")
remote_connection = ssh_client.invoke_shell()
time.sleep(3)
remote_connection.send("copy running-config tftp\n")
remote_connection.send("192.168.127.10\n") # TFTP 伺服器 IP
remote_connection.send(ip + ".bak@" + t_ref + "\n")
time.sleep(3)
output = remote_connection.recv(65535)
print(output.decode('ascii'))
print(f"成功備份執行組態至 TFTP,並斷開與 {ip} 的連線\n")
print("-" * 80)
except paramiko.AuthenticationException:
print(f"登入 {ip} 失敗:使用者名稱或密碼錯誤。")
except paramiko.SSHException as sshException:
print(f"SSH 連線至 {ip} 發生錯誤:{sshException}")
except Exception as e:
print(f"發生錯誤:{e}")
finally:
if ssh_client:
ssh_client.close()
time.sleep(1)
total_time = time.mktime(time.localtime()) - start_timer
print(f"總執行時間: {total_time} 秒")
這段程式碼的核心功能是利用 Paramiko 模組實作網路裝置的自動化備份。首先,程式碼取得當前時間戳記,用於建立獨一無二的備份檔名,避免覆寫先前的備份。接著,程式碼迭代裝置 IP 列表,針對每個 IP 地址建立 SSH 連線。連線成功後,程式碼會執行備份指令,將裝置的執行組態(running-config)複製到指定的 TFTP 伺服器。
我特別加入了 try...except...finally
區塊來處理潛在的錯誤,例如驗證失敗、SSH 連線錯誤等,提升程式碼的穩健性。此外,程式碼在備份完成後會關閉 SSH 連線,釋放資源。最後,程式碼計算並顯示整個備份過程的總執行時間,方便追蹤效能。
這個程式碼片段不僅展示瞭如何使用 Paramiko 進行 SSH 連線和執行指令,更體現了我在網路自動化方面的實務經驗,例如錯誤處理、時間戳記的使用以及程式碼結構的設計。透過這些技巧,可以有效提升網路管理效率,並確保備份流程的可靠性。
我認為,自動化備份是現代網路管理的根本。透過這個 Python 指令碼,我們可以輕鬆地將備份工作自動化,減少人工介入,降低錯誤風險,並提高整體網路的穩定性。更重要的是,這個指令碼可以根據實際需求進行調整,例如修改裝置 IP 列表、TFTP 伺服器地址等,使其更具彈性。