Paramiko实验——(思科)网络搭建
小白网工的python之路
【Python-自动化】paramiko模块
paramiko介绍
paramiko是基于Python实现的SSH2远程安全连接,支持认证及密钥方式。可以实现远程命令执行、文件传输、中间SSH代理等功能,相对于Pexpect,封装的层次更高,更贴近SSH协议的功能
实验6中,各个交换机记得改名,不然都是一样的默认命名,配置文件通过ftp保存在/home/python,默认为交换机名-cfg,会一次一次的覆盖,最终结果就是一个SW5的配置文件,前4个文件全被覆盖了
实验环境
我的实验环境是GNS3搭建拓扑图,用云桥接到在VMware Workstation 16运行的CentOS 7,
CentOS 7上搭建好了python3.8,
所有交换机已经预配好了SSH服务,ssh登录账号为python,密码为123
拓扑
IP规划
CentOS 7 跑python代码 | 192.168.10.46 |
---|---|
vIOS-L2-1 | 192.168.10.111 |
vIOS-L2-2 | 192.168.10.112 |
vIOS-L2-3 | 192.168.10.113 |
vIOS-L2-4 | 192.168.10.114 |
vIOS-L2-5 | 192.168.10.115 |
实验一 -lab1
实验目的
用python代码实现SSH登录交换机(192.168.10.111),为其loop0接口配置IP(1.1.1.1/32)
先确定SW1上loop0没有IP:
在CentOS 7上创建paramiko-lab1.py文件:
python代码
import paramiko
import time
ip = "192.168.10.111"
username = "python"
password = "123"
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password,look_for_keys=False)
print ("Sucessfully login to ", ip)
command = ssh_client.invoke_shell()
command.send("configure terminal\n")
command.send("int loop 0\n")
command.send("ip address 1.1.1.1 255.255.255.255\n")
command.send("end\n")
time.sleep(1)
output = command.recv(65535)
print (output.decode('ascii'))
ssh_client.close()
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- ssh_client = paramiko.SSHClient()
- ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- ssh_client.connect(hostname=ip,username=username,password=password,look_for_keys=False)
- 上面三条语句我称之为paramiko的ssh三件套,也就是说,使用paramiko模块进行ssh登陆网元都会要使用的命令
- command.send(),这里面填的就是我们要执行的命令了
- output = command.recv(65535),python截屏本次运行的输出记录,将其赋值给output这个变量
- print (output.decode('ascii')), 将output打印出来
- ssh_client.close(),退出SSH
执行代码
实验结果
验证结果
实验成功
由此,我们实验1成功!
实验二 -lab2
实验目的
- 实现交互式的SSH用户名和密码输入
- 配合for loop同时给5台交换机配置VLAN 111至VLAN 115
实验准备
执行我们的代码前,先确定我们的5台交换机没有相应的vlan配置:
SW1配置
SW2配置
SW3配置
SW4配置
SW5配置
在CentOS 7上创建paramiko-lab2.py文件:
python代码
import paramiko
import time
import getpass
username = input("Username: ")
password = getpass.getpass("Password: ")
for i in range(111,116):
ip = '192.168.10.' + str(i)
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password,look_for_keys=False)
command = ssh_client.invoke_shell()
print('=-=-=-=-=-=-=-=-=-=-=-=-=-=')
print('已经成功登陆交换机 Layer3Switch-' + str(i-10) + ' ' + ip)
command.send("configure terminal\n")
for n in range(111, 116):
print("Creating VLAN " + str(n))
command.send("vlan " + str(n) + "\n")
command.send("name Python_VLAN " + str(n) + "\n")
time.sleep(0.5)
command.send("end\n")
command.send("wr mem\n")
time.sleep(2)
output = command.recv(65535)
print(output.decode('ascii'))
ssh_client.close()
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- import getpass,用来提示用户输入密码;getpass输入密码时,则是不可见的,安全性很高
- 因为SW1-SW5五个交换机的ip是连续的,192.168.10.111 - 115, 我们配合for i in range(111,116)做一个简单的循环,配合ip = "192.168.10." + str(i)来批量登录交换机S1至S5
- 注意:这里的i是整数,整数不能和字符串相“+”,所以要用str(i)先将i转化成字符串
- for n in range (111,116): 我们创建VLAN 111 至 VLAN 116,VLAN id是连续的,所以这里又可以配合一个简单的for loop达到循环配置VLAN111-116
执行代码
在这里这截取登陆SW1的部分,可以看出,交互式填写用户名和密码,密码不可见,提高安全性!
SW1部分
验证结果
其他4台交换机,大家可以自己show一下,得出结果。
由此,我们实验2成功!
实验三 -lab3
实验目的
- 在生产环境中,当交换机的管理ip在不同的网段,我们便不能简单的循环,我们要额外写一个文本文件,把我们需要登录的交换机ip全部写进去,然后用for loop配合open()函数来批量登录所有交换机。
- 登陆后,开启ospf.
实验准备
- 假设SW2的IP为192.168.10.22,SW5的IP为192.168.10.55,在交换机上把IP修改
- 创建一个名为ip_list_lab3.txt的文件,把S1,S2,S3,S4,S5交换机的管理IP地址放进去
SW2修改IP
SW5修改IP
ip_list_lab3.txt
在CentOS 7上创建paramiko-lab3.py文件:
python代码
import paramiko
import time
import getpass
username = input('Username: ')
password = getpass.getpass('password: ')
f = open("ip_list_lab3.txt","r")
for line in f.readlines():
ip = line.strip()
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password,look_for_keys=False)
print ("Successfully connect to ", ip)
remote_connection = ssh_client.invoke_shell()
remote_connection.send("conf t\n")
remote_connection.send("router ospf 1\n")
remote_connection.send("end\n")
# remote_connection.send("wr mem\n")
time.sleep(1)
output = remote_connection.recv(65535)
print (output)
f.close()
ssh_client.close()
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- 用open("ip_list_lab3.txt", "r")来打开我们实验前创建好了的ip_list_lab3.txt这个保存所有交换机管理地址的文档,后面的"r"表示只读,可写可不写,因为默认就是它。
- for line in f.readlines(): readlines()方法返回的是一个列表,正好可以用for loop读取ip_list.txt文档里的每一行内容,每一行都是交换机的管理IP地址。
- ip = line.strip(),用strip()去掉多于的空格然后把结果assign给ip这个变量。
- f.close(), 关闭文件
执行代码
验证结果
接下来在交换机上查看:
SW1
SW2
SW3
SW4
SW5
由此,我们实验3成功!
实验四 -lab4
实验背景
- 在有成千上万台网络设备需要管理的生产环境中,在python脚本中利用command.send()提交配置命令,这种方法显得很笨拙,缺乏灵活性,故怎么解决呢?
- 比如:思科的3750和3850交换机,前者跑的是IOS,后者跑的是IOS-XE,你要分别给它们批量修改配置,因为两者的命令格式差异巨大,你必须反复修改command.send()这个部分的代码,一旦遇到大规模的配置,那这种方法的效率会很低下。
- 解决这个问题的思路是分别创建两个文本文件,一个用来存3750命令集·,另一个用来存3850命令集,然后在Python脚本里通过for循环加open()来读取两个文件里的内容,以达到分别给所有3750和3850交换机做配置的目的,这样做的好处是无须修改command.send()这个部分的代码,因为所有的命令行已经在文本文件里预先设置好了。
- 假设你现在手边有3台的3750交换机以及2台3850交换机,它们的hostname和管理ip地址如下:
3750_1: 192.168.10.111 | 3850_1: 172.16.10.114 |
3750_2: 192.168.10.112 | 3850_2: 172.16.10.115 |
3750_3: 192.168.10.113 |
实验目的
- 你需要同时修改所有3750和3850的配置,
- 增加3750交换机vlan1的端口描述 ,-->python_to_3750
- 增加3850交换机的g0/0口的端口描述,-->python_to_3850
实验准备
首先创建两个名为command_3750.txt和ip_3750.txt的文本文件,分别用来保存我们将要配置3750的命令,以及所有3750交换机的IP地址
再创建两个名为command_3850.txt和ip_3850.txt的文本文件,分别用来保存我们将要配置3850的命令,以及所有3850交换机的IP地址
在CentOS 7上创建paramiko-lab4.py文件:
python代码
import paramiko
import time
import getpass
import sys
username = input('Username: ')
password = getpass.getpass('password: ')
ip_file = sys.argv[1]
cmd_file = sys.argv[2]
iplist = open(ip_file, 'r')
for line in iplist.readlines():
ip = line.strip()
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password, look_for_keys=False)
print ("You have successfully connect to ", ip)
command = ssh_client.invoke_shell()
cmdlist = open(cmd_file, 'r')
cmdlist.seek(0)
for line in cmdlist.readlines():
command.send(line + "\n")
time.sleep(1)
cmdlist.close()
output = command.recv(65535).decode('ascii')
print(output)
iplist.close()
ssh_client.close()
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- 因为要用到sys.argv,所以这里import了sys模块
- 「argv」是「argument variable」参数变量的简写形式,这个变量返回的是一个列表,argv[0] 一般是被调用的脚本的文件名或全路径,从argv[1]开始就是传入的数据了
- 配合sys.argv,我们可以很灵活地选用我们脚本需要调用的文本文件,而无需反反复复地修改脚本代码
执行代码
3750
3850
验证结果
至此,我们的实验4成功!
实验五 -lab5
实验背景
大型企业网络设备规模庞大,数量可达成千上万的级别,实际运维中常会发生个别网元因设备故障、链路断开、防火墙策略拦劫、用户名密码配置不对等造成 SSH 连接失败的情况,即网元脱管。前面的几个实验,我们均没有考虑到这个场景,都是假设要操作的设备都是正常可控的。童鞋们不烦试一下,之前的实验拓扑中,任一删掉一条链路,或者关掉一台 交换机,或者改个登录密码,都会发现 python 脚本会卡主后报错,脚本停止不在执行。本实验我们用 Python 中的 try, except 异常处理语句,来解决这个问题
实验目的
- 将交换机S3的密码从123改为456, 将S4的g0/0端口断掉
- 创建一个带有try,except异常处理语句的python脚本来批量在交换机S1-S5上执行show clock命令,让python脚本在S3,S4分别因为用户名密码不匹配,以及连通性出现故障的情况下,依然可以不受干扰,接着配置S5
实验准备
1.首先将S3的密码从123改为456
2.再将S4的端口g0/0断掉
3.在CentOS 7上创建一个名为cmd-lab5.txt的文本文件,写入我们要在S1-S5上执行的命令:show clock
继续创建ip_list_lab5.txt,写了5台交换机的ip地址
4.在CentOS 7上创建paramiko-lab5.py文件:
python代码
import paramiko
import time
import getpass
import sys
import socket
username = input('Username: ')
password = getpass.getpass('password: ')
ip_file = sys.argv[1]
cmd_file = sys.argv[2]
switch_with_authentication_issue = []
switch_not_reachable = []
iplist = open(ip_file, 'r')
for line in iplist.readlines():
try:
ip = line.strip()
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip,username=username,password=password,look_for_keys=False)
print ("已经成功登陆交换机", ip)
command = ssh_client.invoke_shell()
cmdlist = open(cmd_file, 'r')
cmdlist.seek(0)
for line in cmdlist.readlines():
command.send(line + "\n")
time.sleep(2)
cmdlist.close()
output = command.recv(65535).decode('ascii')
print (output)
except paramiko.ssh_exception.AuthenticationException:
print (ip + "用户验证失败!")
switch_with_authentication_issue.append(ip)
except socket.error:
print (ip + "目标不可达!")
switch_not_reachable.append(ip)
iplist.close()
ssh_client.close
print ('\n下列交换机用户验证失败:')
for i in switch_with_authentication_issue:
print (i)
print ('\n下列交换机不可达:')
for i in switch_not_reachable:
print (i)
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- 为了使用try-except来应对网络设备不可达引起的socket.error,这里我们必须import socket。
- 创建两个空列表,取名为switch_with_authentication_issue和switch_not_reachable, 分别在脚本最后配合for循环来统计有哪些设备是因为认证问题无法登录,有哪些是因为设备本身不可达而无法登录。
- 在for循环下使用try-except, 用excpet paramiko.ssh_exception.AuthenticationException:来应对用户名/密码不匹配时返回的错误代码,将出现该错误的交换机的管理IP地址用.append(ip)方法放入switch_with_authentication_issue这个列表中,同理用except socket.error:来应对交换机不可达时返回的错误代码,将出现该错误的交换机的管理IP地址用append(ip)方法放入switch_not_reachable这个列表中。
执行代码
验证结果
- 本应出现的paramiko.ssh_exception.AuthenticationException 错误已经被用户验证失败 192.168.10.113取代,并且python脚本并未就此停止运行,而是继续尝试登录下一个交换机S4,也就是192.168.10.114。
- 本应出现的paramiko.ssh_exception.AuthenticationException:Authentication failed错误已经被192.168.10.114不可达取代,并且python脚本并未就此停止运行,而是继续尝试登录下一个交换机S5,也就是192.168.10.115。
- 在脚本的最后标注出了有哪些交换机出现了用户认证失败的情况,有哪些交换机出现了不可达的情况
至此,我们的实验5成功!
实验六 -lab6
实验背景
将网络设备的配置做备份是网络运维中必不可少的一项工作,根据公司的规模和要求的不同,管理层可能会要求对网络设备的配置做月备、周备甚至日备。传统的备份思科交换机配置的办法是手动 SSH 远程登录设备,然后输入命令 term len 0 和 show run,将回显内容手动复制/粘贴到一个 TXT 或者 Word 文本文件中,效率十分低下,在有成百上千台备需要备份的网络中尤为明显
实验目的
在 CentOS 7 主机上开启 FTP Server 服务,创建 Python 脚本,将 SW1~SW5 的 running configuration 备份保存到 FTP 服务器上
实验准备
我们日常给网络设备做配置备份,通常是在网络设备处开启FTP服务,把它当做FTP服务器,我们的电脑登陆服务器进行get获取备份,少量设备还好说,但设备一多,便显得有些繁琐
现在,我们反其道而行之,在本地电脑开启FTP服务,充当FTP服务器,使用python脚本循环各个网元登陆我们的电脑,进行put上传 配置文件的操作,这样不就显得简单多了么?
1.先在CentOS 7主机中输入下面的命令,下载 vsftpd 服务:
yum install vsftpd -y
2.安装完成后,启动服务:
systemctl start vsftpd
systemctl enable vsftpd
3.验证服务是否被启动:
systemctl status vsftpd
4.(重要)输入下列命令关闭 CentOS 7的防火墙:
systemctl stop firewalld
systemctl status firewalld
在 CentOS 7上输入下列命令,分别创建新的用户名 python 并根据提示设置密码python,这个用户名 python 将稍后作为 FTP 用户使用名,而交换机的 running configuration也将被保存在/home/python 文件夹下,如下所示
useradd –create-home python
passwd python
在CentOS 7上创建paramiko-lab6.py文件:
python代码
import paramiko
import time
import getpass
username = input('Username: ')
password = getpass.getpass('password: ')
f = open("ip_list_lab6.txt")
for line in f.readlines():
ip_address = line.strip()
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip_address,username=username,password=password)
print ("Successfully connect to ", ip_address)
command = ssh_client.invoke_shell()
command.send("configure terminal\n")
command.send("ip ftp username python\n")
command.send("ip ftp password python\n")
command.send("file prompt quiet\n")
command.send("end\n")
command.send("copy running-config ftp://192.168.10.46\n")
time.sleep(5)
output = command.recv(65535)
print (output.decode('ascii'))
f.close()
ssh_client.close ()
- 重点代码解析:
- 先假定读这篇文章的朋友都有一定的基础,故简单的代码就不赘述了
- 感觉都还简单,注意 command.send("copy running-config ftp://192.168.10.46\n") 这里的IP填的是我们CentOS 7主机的IP就行了,其他的没什么了
·
执行代码
验证结果
查看到的配置文件
至此,我们的实验6成功!