netmiko
파이썬에서 SSH를 사용하여 네트워크 자동화를 수행하는 대표적인 모듈 중 paramiko 와 netmiko 가 있는데,
paramiko는 netmiko에 비해 사용법이 복잡하기 때문에, 네트워크 장비에 SSH 접속 후 자동화를 수행하는 작업에는 netmiko가 많이 사용된다.
구성도
실습을 진행할 네트워크 구성도는 다음과 같다.
사전 준비
netmiko 설치
pip install netmiko
netmiko 함수
netmiko에서는 아래 세 가지 함수를 주로 사용한다.
send_command()
sh version
,sh run
등의 Privileged Mode 명령어에 사용됨.
send_config_set()
conf t [명령어]
, Global Mode 명령어에 사용됨.conf t
,exit
는 자동으로 작성해주기 때문에 사용할 명령어만 입력하면 된다.
save_config()
- 스위치 설정 저장(
write memory
)할 때 사용됨.
- 스위치 설정 저장(
net_connect = ConnectHandler(**ios)
net_connect
객체를 netmiko 모듈의ConnectHandler
클래스를 사용해 생성함.
output = net_connect.send_command('show ip int br')
output
변수에show ip int br
명령어에 대한 결과 값을 담음.
스위치 설정
원활한 실습을 위해서는 자동화하려는 스위치 장비에 관리 IP 및 SSH 설정이 되어있어야 한다.
관리 IP 설정
먼저, 스위치의 VLAN 1 인터페이스에 관리 IP를 설정하자
(관리 IP를 꼭 vlan 1에 설정할 필요는 없다.)
Switch> enable
Switch# configure terminal
Switch(config)# interface vlan 1
Switch(config-if)# ip address 192.168.219.155 255.255.255.0
Switch(config-if)# no shutdown
그리고 스위치가 다른 네트워크와 통신할 수 있도록 기본 게이트웨이를 설정하자.
Switch(config)# ip default-gateway 192.168.219.1
마지막으로 인터페이스 구성 모드에서 나와 설정을 완료하자.
Switch(config-if)# exit
SSH 설정
SSH를 사용하려면 도메인 이름을 설정해야 한다.
Switch(config)# ip domain-name example.com
SSH를 위해 RSA 키를 생성하자.
Switch(config)# crypto key generate rsa
키 크기(모듈러스 크기)를 묻는 메시지가 나타나면, 보통 1024 또는 2048 비트를 입력하자.
How many bits in the modulus [512]: 1024
SSH 버전을 설정하자. 일반적으로 SSH 버전 2를 사용하는 것이 안전하다.
Switch(config)# ip ssh version 2
SSH 접속에 사용할 사용자 계정과 권한을 만들어주자.
Switch(config)# username admin privilege 15 secret cisco123
Switch(config)# enable password cisco123
마지막으로 SSH를 허용하기 위해 VTY 라인을 설정하자.
Switch(config)# line vty 0 4
Switch(config-line)# login local
Switch(config-line)# transport input ssh
Switch(config-line)# exit
스위치 접속
스위치에 SSH 접속이 정상적으로 수행되는지 테스트해보자.
$ ssh <사용자계정>@<스위치IP>
$ ssh admin@192.168.219.50
자동화 스크립트 작성
- 여러가지 자동화 스크립트를 작성해보자.
장비별 VLAN 출력
반복문 for
를 사용하여 스위치 3개를 반복하고, 스위치마다 설정되어 있는 vlan을 출력하도록 해보자.
from netmiko import ConnectHandler
def config_ssh(switches: list[tuple[str]]) -> None:
for ip, username, password, enable, port, device_type in switches:
devices = {
'ip': ip,
'username': username,
'password': password,
'secret': enable,
'port': port,
'device_type': device_type,
}
net_connect = ConnectHandler(**devices)
net_connect.enable()
command = ('sh vlan')
output = net_connect.send_command(command)
print(output)
if __name__ == "__main__":
fname = "L2-switch.txt"
with open(file=fname, mode='r', encoding='utf-8') as fp:
switches = [tuple(switch.strip('\n').split()) for switch in fp.readlines()]
config_ssh(switches=switches)
L2-switch.txt 의 파일 내용은 아래와 같다.
192.168.219.180 admin cisco123 cisco123 22 cisco_ios
실행 결과
$ python3 main.py
VLAN Name Status Ports
---- -------------------------------- --------- -------------------------------
1 default active Gi0/0, Gi0/1, Gi0/2, Gi0/3, Gi1/0, Gi1/1, Gi1/2, Gi1/3
1002 fddi-default act/unsup
1003 token-ring-default act/unsup
1004 fddinet-default act/unsup
1005 trnet-default act/unsup
VLAN Type SAID MTU Parent RingNo BridgeNo Stp BrdgMode Trans1 Trans2
---- ----- ---------- ----- ------ ------ -------- ---- -------- ------ ------
1 enet 100001 1500 - - - - - 0 0
1002 fddi 101002 1500 - - - - - 0 0
1003 tr 101003 1500 - - - - - 0 0
1004 fdnet 101004 1500 - - - ieee - 0 0
1005 trnet 101005 1500 - - - ibm - 0 0
Remote SPAN VLANs
------------------------------------------------------------------------------
Primary Secondary Type Ports
------- --------- ----------------- ------------------------------------------
장비별 config 백업
파이썬을 활용한 네트워크 자동화 중 가장 많이 사용되는 config backup 이다.
스위치 config를 백업하기 위해서는 파이썬으로 파일을 생성하여, 명령어 결과를 파일에 저장하는 작업이 필요하다.
from netmiko import ConnectHandler
from datetime import datetime
# 장비 정보 설정
def read_switches_file(file_name: str) -> list[tuple[str]]:
with open(file_name, 'r', encoding='utf-8') as fp:
return [tuple(switch.strip('\n').split()) for switch in fp.readlines()]
def backup_config(switches: list[tuple[str]]) -> None:
for ip, username, password, enable, port, device_type in switches:
device = {
'device_type': device_type,
'ip': ip,
'username': username,
'password': password,
'secret': enable,
'port': port,
}
# 장비 연결
with ConnectHandler(**device) as net_connect:
hostname :str = net_connect.send_command('show run | include hostname').split()[-1]
config :str = net_connect.send_command('show run')
with open(f'{hostname}_backup.txt', 'w', encoding='utf-8') as fp:
fp.write(config)
if __name__ == '__main__':
file_name :str = 'switches.txt'
switches = read_switches_file(file_name=file_name)
backup_config(switches=switches)
switches.txt 의 파일 내용은 아래와 같다.
192.168.219.50 test cisco123 cisco123 22 cisco_ios
실행 결과
$ python main.py
$ ls -lh .
-rw-r--r-- 1 a-user a-user 3.4K 9월 2일 16:18 test-swtich1_backup.txt