网络拓扑搭建
telnet的使用只有在确保网络是安全纯净的,没有人进行嗅探等行为,或者只是传递一些公开的数据,并且这些数据不会包含密码等敏感和重要的数据,否则不建议在使用telnet,如果处于可能被嗅探的风险中,那就应该使用ssh进行管理了。
实验过程分为四个步骤:
- 配置设备Telnet服务
- 手动验证和查看Telnet登录步骤
- 编写和运行Python代码
- 验证结果
配置云:要先安装网卡,然后添加地址。
配置R1设备接口地址
[R1]int g0/0/0
[R1-GigabitEthernet0/0/0]ip add 192.168.250.1 24
配置R1设备Telnet服务
[Huawei]sys R1
[R1]un in en
Info: Information center is disabled.
[R1]user-interface vty 0 4
[R1-ui-vty0-4]au
[R1-ui-vty0-4]authentication-mode password
Please configure the login password (maximum length 16):Huawei@123
[R1-ui-vty0-4]protocol inbound telnet
[R1-ui-vty0-4]user privilege level 15
[R1-ui-vty0-4]q
[R1]q
<R1>
telnetlib介绍
telnetlib是Python标准库中的模块。它提供了实现Telnet功能的类telnetlib.Telnet。
import telnetlib
tn = telnetlib.Telnet(host=None[,port=0[,timeout])
方法 | 功能 |
---|---|
Telnet.read_until(expected,timeout=None) | 读取直到给定的字符串expected或超时秒数。 |
Telnet.read_all() | 读取所有数据直到EOF(End Of File)。阻塞直到连接关闭。 |
Telnet.read_very_eager() | 读取从上次IO阻断到现在所有的内容,返回字符串。连接关闭或者没有数据时触发EOFError异常 |
Telnet.write(buffer) | 写入数据。在套接字(Socket)上写一个字符串,加倍任何IAC(Interpret As Command)字符。 |
Telnet.close() | 关闭连接。 |
源代码和思路
代码基本思路:导入模块——》定义登录设备IP——》定义登录设备密码——》Telnet登录到主机——》读取直到回显信息为“Password”,输入编码为ASCII的密码并换行,输出读取直到看到""信息——》关闭Telnet连接
# 使用telnetlib登录设备
import telnetlib
import time
host ='192.168.250.1'
password='Huawei@123'
# 命令结束提示符
# 正常模式如<R1> 来提示用户输入命令,所以取>为作为标志符
_UserTag = '>'
# system-view模式如[R1] 来提示用户输入命令,所以取]为作为标志符
_SysTag = ']'
# telnet登录
tn = telnetlib.Telnet(host)
# ❤read_until()来判断缓冲区中的数据是否有想要的内容,如果没有就等待
tn.read_until(b'Password:')
tn.write(password.encode('ascii') + b"\n")
# 读取用户模式
UserTag = tn.read_until(_UserTag.encode('ascii'))
response = UserTag
print(response.decode('ascii')) # print(tn.read_until(b'<R1>').decode('ascii'))
time.sleep(2)
# 执行一个dir命令
tn.write(b"dir\n")
response = UserTag
if b'>' in response:
print(response.decode('ascii'))
time.sleep(2)
# 进入系统视图
tn.write(b"system-view\n")
SysTag = tn.read_until(_SysTag.encode('ascii'))
response = SysTag
print(response.decode('ascii'))
time.sleep(2)
tn.close()
print("close")
结果:
<R1>
dir
Directory of flash:/
Idx Attr Size(Byte) Date Time(LMT) FileName
0 drw- - May 22 2020 08:24:04 dhcp
1 -rw- 121,802 May 26 2014 09:20:58 portalpage.zip
2 -rw- 2,263 May 22 2020 08:23:58 statemach.efs
3 -rw- 828,482 May 26 2014 09:20:58 sslvpn.zip
1,090,732 KB total (784,464 KB free)
<R1>system-view
Enter system view, return user view with Ctrl+Z.
[R1]
close
接口IP地址配置
tn.write(b"int g0/0/1\n")
tn.write(b"ip add 192.168.60.1 255.255.255.0\n")
SysTag = tn.read_until(_SysTag.encode('ascii'))
response = SysTag
print(response.decode('ascii'))
time.sleep(2)
封装函数
登录操作就使用ConnHwTelnet函数
如果执行用户模式命令就使用UsermodeRunCommand函数
如果执行sys模式命令就使用SysmodeRunCommand函数
import telnetlib
import time
host ='192.168.250.1'
password='Huawei@123'
# 命令结束提示符
# 正常模式如<R1> 来提示用户输入命令,所以取>为作为标志符
_UserTag = '>'
# system-view模式如[R1] 来提示用户输入命令,所以取]为作为标志符
_SysTag = ']'
# 封装到一个登陆函数里面
def ConnHwTelnet(host,password,_UserTag = '>',_SysTag = ']'):
# telnet登录
tn = telnetlib.Telnet(host)
# 开启调试,按需开启,方便判断
password_promt = 'Password'
response = tn.read_until(password_promt.encode('ascii'))
if password_promt.encode('ascii') in response:
print('[*] Password: ', password)
time.sleep(2)
tn.write(password.encode('ascii') + b"\n")
# 如果登陆成功,则出现类似<R1>,使用_UserTag来进行捕获
response = tn.read_until(_UserTag.encode('ascii'))
if _UserTag.encode('ascii') in response:
print(response.decode('ascii')) # print(tn.read_until(b'<R1>').decode('ascii'))
time.sleep(2)
# 成功后,返回一个成功连接实例
return tn
# 执行用户模式命令
def UsermodeRunCommand(tn, command,_UserTag='>'):
command = "%s\n" % command
tn.write(command.encode('ascii'))
response = tn.read_until(_UserTag.encode('ascii'))
if _UserTag.encode('ascii') in response:
print(response.decode('ascii'))
# 执行system模式命令
def SysmodeRunCommand(tn,command,_SysTag=']'):
command = "%s\n" % command
tn.write(command.encode('ascii'))
response = tn.read_until(_SysTag.encode('ascii'))
if _SysTag.encode('ascii') in response:
print(response.decode('ascii'))
if __name__ == '__main__':
tn = ConnHwTelnet(host,password,_UserTag,_SysTag)
# 如果执行用户模式命令就使用UsermodeRunCommand函数,如果执行sys模式命令就使用SysmodeRunCommand函数
UsermodeRunCommand(tn, "dir")
SysmodeRunCommand(tn, "system-view")
SysmodeRunCommand(tn, "int g0/0/1")
SysmodeRunCommand(tn, "ip add 192.168.60.1 255.255.255.0")
tn.close()
print("测试完毕")
结果:
[*] Password: Huawei@123
:
<R1>
dir
Directory of flash:/
Idx Attr Size(Byte) Date Time(LMT) FileName
0 drw- - May 23 2020 12:20:24 dhcp
1 -rw- 121,802 May 26 2014 09:20:58 portalpage.zip
2 -rw- 2,263 May 23 2020 12:20:19 statemach.efs
3 -rw- 828,482 May 26 2014 09:20:58 sslvpn.zip
4 -rw- 249 May 23 2020 12:20:57 private-data.txt
5 -rw- 660 May 23 2020 12:22:01 vrpcfg.zip
1,090,732 KB total (784,456 KB free)
<R1>
system-view
Enter system view, return user view with Ctrl+Z.
[R1]
int g0/0/1
[R1-GigabitEthernet0/0/1]
ip add 192.168.60.1 255.255.255.0
Error: The address already exists.
[R1-GigabitEthernet0/0/1]
测试完毕
补充 dis cu
像dis cu这种一个屏幕显示不了的,需要按回车才能显示全的操作
# 定义一个集合,每一屏的信息都追加到集合中
result_list = []
# 判断是否有--More--
command = "dis cu\n"
tn.write(command.encode('ascii'))
time.sleep(2)
while (True):
# 获取返回的结果
command_result = tn.read_very_eager().decode("ascii")
# 追加到集合中
result_list.append(command_result)
# 判断当前这一页是否 --More-- 结束
if ' ---- More ----' in command_result.strip():
tn.write(b"\n")
time.sleep(0.5)
else:
break
# 拼接集合
result_str = "\n".join(result_list)
print(result_str)
tn.close()
print("测试完毕")