网络工程师如何利用Python自动Telnet到N个路由器并执行配置?

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 【10月更文挑战第23天】

传统的网络管理方法通常需要手动配置多个设备,这不仅耗时,而且容易出错。随着网络规模的扩大,手动配置逐渐无法满足需求。因此,网络自动化技术应运而生,通过脚本和工具自动执行配置、监控和管理任务,大大提高了网络管理的效率。

自动化不仅能减少人为错误,还能确保一致性。例如,在多台路由器上进行相同的配置时,使用自动化脚本可以确保每台设备的配置完全一致。此外,自动化还可以显著缩短执行时间,从而更快地响应业务需求和网络变化。

Python是一种广泛应用于网络自动化的编程语言。它语法简单,易于学习,同时拥有丰富的库和模块,能够处理各种网络任务。无论是通过Telnet、SSH还是API与网络设备进行交互,Python都提供了强大的支持。

使用Python,网络工程师可以编写脚本来自动执行复杂的配置任务。例如,可以编写一个脚本批量配置多个路由器的接口、路由和访问控制列表(ACL)。Python的灵活性和强大的第三方库支持,使其成为网络自动化的首选工具之一。

Telnet

Telnet是一种早期的远程登录协议,允许用户通过TCP/IP网络在远程设备上执行命令。它基于客户端-服务器模型,客户端向服务器发送文本命令,服务器执行后将结果返回给客户端。Telnet的工作原理相对简单,但正是由于其简单性,它在很多网络设备上仍然得以保留,特别是在一些不支持SSH的旧设备上。

Telnet使用纯文本进行通信,这意味着传输的数据(包括登录凭证)并未加密,这也是其最大的安全缺陷。尽管如此,在封闭网络或安全性要求不高的场景中,Telnet仍然是一个可用的工具。

在网络管理中,Telnet曾被广泛用于访问和管理网络设备。通过Telnet,网络管理员可以远程登录到路由器、交换机等设备,并执行配置命令。例如,可以使用Telnet登录到一台路由器,查看接口状态、配置静态路由或调整访问控制列表。

然而,随着安全需求的提高,SSH逐渐取代了Telnet,成为更安全的远程管理协议。但在一些遗留设备或特定场景中,Telnet仍然有其应用价值,特别是在网络自动化脚本中,使用Telnet进行批量配置仍然具有实际意义。

尽管Telnet在某些情况下仍然有用,但它存在明显的安全性问题。由于Telnet使用明文传输数据,包括用户名和密码,网络攻击者可以轻松地嗅探到这些敏感信息。因此,在公共网络或对安全性要求较高的场合,建议避免使用Telnet,转而采用SSH等加密协议。

在需要使用Telnet的场景中,可以通过一些方式减小安全风险。例如,在使用Python自动化脚本时,可以通过限制脚本的执行环境、使用专用网络等方式,确保Telnet通信的安全性。此外,还可以考虑对登录凭证进行加密存储,并在脚本执行过程中尽可能地减少敏感信息的暴露。

Python Telnet库的介绍

telnetlib是Python标准库中的一个模块,专门用于实现Telnet协议。通过telnetlib,我们可以方便地与支持Telnet协议的远程设备进行通信。telnetlib提供了基本的Telnet功能,如连接远程主机、发送命令、读取响应等,使得编写Telnet自动化脚本变得非常简单。

  • 文档:
https://docs.python.org/3/library/telnetlib.html

可以选择中文:

源码地址:

https://github.com/python/cpython/blob/3.12/Lib/telnetlib.py

虽然telnetlib的功能相对基础,但对于大多数Telnet操作来说已经足够。通过telnetlib,可以轻松地实现与网络设备的交互,完成自动化配置任务。在接下来的部分中,我们将详细介绍如何使用telnetlib进行Telnet操作。

使用telnetlib建立一个Telnet连接非常简单。首先,需要导入模块并创建一个Telnet对象,连接到指定的主机。然后,可以通过该对象发送命令并读取设备的响应。以下是一个简单的示例,演示如何使用telnetlib连接到一台路由器,并执行一些基本的命令:

import telnetlib

# 连接到路由器
tn = telnetlib.Telnet('192.168.1.1')

# 输入用户名
tn.read_until(b'Username:')
tn.write(b'admin\n')

# 输入密码
tn.read_until(b'Password:')
tn.write(b'password\n')

# 执行命令
tn.write(b'show running-config\n')

# 读取输出
output = tn.read_all().decode('ascii')
print(output)

# 关闭连接
tn.close()

这个脚本展示了如何使用telnetlib连接到一个IP地址为192.168.1.1的路由器,输入用户名和密码后,执行show running-config命令并输出结果。read_until()方法用于等待设备的提示符,而write()方法则用于发送命令。

构建基础的Telnet脚本

在开始编写Telnet自动化脚本之前,需要先设置Python开发环境。Python的安装过程非常简单,可以从Python官网直接下载适合的版本并安装。安装完成后,建议使用虚拟环境(virtual environment)来管理项目的依赖,这样可以避免不同项目之间的依赖冲突。

可以通过以下命令创建和激活虚拟环境:

python3 -m venv myenv
source myenv/bin/activate  # 在Windows上使用 myenv\Scripts\activate

一旦激活虚拟环境,就可以使用pip安装必要的库。如果需要安装额外的库,可以通过pip命令轻松实现:

pip install some-library

在本例中,我们主要使用Python的标准库telnetlib,因此不需要额外安装第三方库。

构建基础的Telnet脚本首先需要建立与目标路由器的连接。我们可以通过telnetlib.Telnet()方法创建一个Telnet连接对象,并指定目标设备的IP地址或主机名。连接成功后,就可以通过该对象与设备进行交互。

例如,以下代码展示了如何连接到一台路由器并等待其响应:

import telnetlib

tn = telnetlib.Telnet('192.168.1.1')

# 等待登录提示符
tn.read_until(b'Username:')

在成功建立连接后,下一步是登录到路由器。这通常涉及输入用户名和密码。我们可以使用read_until()方法等待路由器的提示符,然后使用write()方法发送用户名和密码。

# 输入用户名
tn.write(b'admin\n')

# 等待密码提示符并输入密码
tn.read_until(b'Password:')
tn.write(b'password\n')

这种方式可以处理大多数情况下的登录过程。当然,根据不同设备的配置,可能需要调整等待提示符的时间或者处理不同的提示符。

登录成功后,就可以开始发送配置命令。通过write()方法,可以向路由器发送任何支持的命令,例如查看当前配置、调整接口设置等。发送命令后,可以使用read_all()read_until()方法读取设备返回的响应。

# 执行命令
tn.write(b'show ip interface brief\n')

# 读取命令输出
output = tn.read_until(b'#').decode('ascii')
print(output)

在完成所有操作后,记得正确关闭连接。通过tn.close()方法,可以安全地断开与设备的Telnet连接。这不仅有助于释放资源,还能避免设备上出现未关闭的会话。

# 关闭Telnet连接
tn.close()

通过这些基本步骤,已经可以构建一个简单的Telnet脚本,自动化地连接到路由器、执行命令并读取结果。接下来,我们将探讨如何扩展这个脚本,以便处理多个设备。

批量操作:Telnet到多个路由器

在实际的网络管理中,往往需要对多个设备进行相同或类似的配置。例如,在多个路由器上统一配置接口或路由,或者执行批量更新。在这种情况下,手

动逐一操作显然效率低下,并且容易出现遗漏或配置不一致的问题。

通过Python脚本,可以轻松实现批量操作。利用循环结构,可以将相同的操作应用到多个设备上,大幅提高工作效率。

为了实现对多台设备的批量操作,可以将设备的IP地址、用户名和密码等信息存储在一个列表中,然后通过循环依次连接到每台设备并执行配置命令。以下是一个示例代码,展示了如何使用循环来批量处理多个路由器:

devices = [
    {
   'ip': '192.168.1.1', 'username': 'admin', 'password': 'password1'},
    {
   'ip': '192.168.1.2', 'username': 'admin', 'password': 'password2'},
    {
   'ip': '192.168.1.3', 'username': 'admin', 'password': 'password3'},
]

for device in devices:
    tn = telnetlib.Telnet(device['ip'])

    tn.read_until(b'Username:')
    tn.write(device['username'].encode('ascii') + b'\n')
    tn.read_until(b'Password:')
    tn.write(device['password'].encode('ascii') + b'\n')

    # 执行配置命令
    tn.write(b'show running-config\n')
    output = tn.read_all().decode('ascii')
    print(f"Configuration for {device['ip']}:\n{output}")

    tn.close()

这个脚本展示了如何遍历设备列表,逐一连接到每个路由器,执行命令并输出结果。通过这种方式,可以轻松实现对多台设备的统一配置。

当设备数量较多时,直接在脚本中硬编码设备信息会显得非常不方便。此时,可以考虑将设备信息存储在配置文件中,例如使用JSON或YAML格式,然后在脚本中读取配置文件以获取设备信息。这样不仅提高了脚本的可维护性,还可以方便地添加或修改设备信息。

以下是一个使用JSON配置文件的示例:

{
   
    "devices": [
        {
   "ip": "192.168.1.1", "username": "admin", "password": "password1"},
        {
   "ip": "192.168.1.2", "username": "admin", "password": "password2"},
        {
   "ip": "192.168.1.3", "username": "admin", "password": "password3"}
    ]
}

在Python脚本中,可以使用json模块读取配置文件,并循环处理每个设备:

import json
import telnetlib

with open('devices.json') as f:
    config = json.load(f)

for device in config['devices']:
    tn = telnetlib.Telnet(device['ip'])

    tn.read_until(b'Username:')
    tn.write(device['username'].encode('ascii') + b'\n')
    tn.read_until(b'Password:')
    tn.write(device['password'].encode('ascii') + b'\n')

    # 执行配置命令
    tn.write(b'show running-config\n')
    output = tn.read_all().decode('ascii')
    print(f"Configuration for {device['ip']}:\n{output}")

    tn.close()

这种方法使得设备信息与脚本逻辑分离,更易于管理和维护。

高级脚本功能

错误处理与日志记录

在实际应用中,脚本执行过程中可能会遇到各种错误,例如设备连接失败、认证失败或命令执行出错。为了提高脚本的稳定性和可靠性,需要加入适当的错误处理机制,并记录脚本的执行日志,以便后续分析和排查问题。

通过Python的try-except结构,可以捕获和处理运行时错误。例如,在连接设备时,可以检测是否成功连接,如果失败则跳过该设备并记录错误信息:

import telnetlib
import logging

logging.basicConfig(filename='telnet_script.log', level=logging.INFO)

devices = [
    {
   'ip': '192.168.1.1', 'username': 'admin', 'password': 'password1'},
    {
   'ip': '192.168.1.2', 'username': 'admin', 'password': 'password2'},
    {
   'ip': '192.168.1.3', 'username': 'admin', 'password': 'password3'},
]

for device in devices:
    try:
        tn = telnetlib.Telnet(device['ip'])
    except Exception as e:
        logging.error(f"Failed to connect to {device['ip']}: {str(e)}")
        continue

    try:
        tn.read_until(b'Username:')
        tn.write(device['username'].encode('ascii') + b'\n')
        tn.read_until(b'Password:')
        tn.write(device['password'].encode('ascii') + b'\n')

        tn.write(b'show running-config\n')
        output = tn.read_all().decode('ascii')
        logging.info(f"Configuration for {device['ip']}:\n{output}")
    except Exception as e:
        logging.error(f"Error during operation on {device['ip']}: {str(e)}")
    finally:
        tn.close()

这个脚本在每个操作步骤中都加入了错误处理,并将错误和执行结果记录到日志文件中。这有助于在出现问题时快速定位和解决问题。

多线程处理

当设备数量较多时,逐一连接和配置设备的效率可能较低。为提高效率,可以使用多线程技术同时处理多个设备。Python的threading模块提供了简单易用的多线程支持,使得在多个设备上并行执行操作成为可能。

以下是一个使用多线程的示例代码:

import threading
import telnetlib

devices = [
    {
   'ip': '192.168.1.1', 'username': 'admin', 'password': 'password1'},
    {
   'ip': '192.168.1.2', 'username': 'admin', 'password': 'password2'},
    {
   'ip': '192.168.1.3', 'username': 'admin', 'password': 'password3'},
]

def configure_device(device):
    try:
        tn = telnetlib.Telnet(device['ip'])
        tn.read_until(b'Username:')
        tn.write(device['username'].encode('ascii') + b'\n')
        tn.read_until(b'Password:')
        tn.write(device['password'].encode('ascii') + b'\n')

        tn.write(b'show running-config\n')
        output = tn.read_all().decode('ascii')
        print(f"Configuration for {device['ip']}:\n{output}")
    finally:
        tn.close()

threads = []

for device in devices:
    t = threading.Thread(target=configure_device, args=(device,))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

通过threading.Thread()创建线程,并通过target参数指定每个线程的执行函数,这样可以同时处理多个设备,提高脚本的执行效率。

命令输出的解析

在执行配置命令后,路由器会返回命令输出。对于复杂的命令,输出通常包含大量信息。为了进一步处理这些信息,可能需要对输出进行解析,例如提取特定配置项或统计某些信息。

Python的正则表达式模块re可以帮助解析和提取命令输出中的特定内容。以下是一个示例,展示如何提取接口的IP地址信息:

import re

output = """
Interface              IP-Address      OK? Method Status                Protocol
FastEthernet0/0        192.168.1.1     YES manual up                    up
FastEthernet0/1        unassigned      YES unset  administratively down down
"""

# 提取接口和对应的IP地址
interfaces = re.findall(r'(\S+)\s+(\d+\.\d+\.\d+\.\d+|\S+)', output)
for interface, ip in interfaces:
    print(f"Interface: {interface}, IP: {ip}")

这种方式可以根据需要定制输出解析逻辑,从而更好地利用设备返回的数据。

实际案例:使用Python自动化配置网络

假设我们负责管理一个企业网络,网络中包含多台路由器和交换机。为了满足业务需求,需要在所有路由器上配置相同的静态路由和访问控制列表(ACL)。手动逐一配置这些设备不仅效率低下,而且容易出错。因此,我们决定使用Python编写一个自动化脚本,来批量配置这些设备。

首先,我们需要明确配置需求。假设我们需要在每台路由器上添加以下静态路由:

  • 网络 10.0.0.0/24 的下一跳为 192.168.1.254
  • 网络 172.16.0.0/16 的下一跳为 192.168.1.254

此外,还需要配置一个访问控制列表(ACL),阻止特定IP地址段的访问:

  • 阻止 192.168.100.0/24 的所有访问我们可以将这些命令集成到一个Python脚本中,通过Telnet连接到每台路由器并执行配置。

基于上述需求,我们设计以下脚本:

import telnetlib
import json

# 读取设备信息
with open('devices.json') as f:
    devices = json.load(f)['devices']

commands = [
    'ip route 10.0.0.0 255.255.255.0 192.168.1.254',
    'ip route 172.16.0.0 255.255.0.0 192.168.1.254',
    'access-list 101 deny ip 192.168.100.0 0.0.0.255 any',
    'access-list 101 permit ip any any'
]

def configure_device(device):
    try:
        tn = telnetlib.Telnet(device['ip'])
        tn.read_until(b'Username:')
        tn.write(device['username'].encode('ascii') + b'\n')
        tn.read_until(b'Password:')
        tn.write(device['password'].encode('ascii') + b'\n')

        # 进入配置模式
        tn.write(b'configure terminal\n')

        for command in commands:
            tn.write(command.encode('ascii') + b'\n')

        tn.write(b'end\n')
        tn.write(b'write memory\n')

        output = tn.read_all().decode('ascii')
        print(f"Configuration for {device['ip']} completed.")
    finally:
        tn.close()

# 对每台设备进行配置
for device in devices:
    configure_device(device)
目录
相关文章
|
12天前
|
负载均衡 网络协议 算法
|
7天前
|
网络协议 Linux
图形界面配置网络
本文介绍了在Linux上配置网络服务的步骤。首先打开RHEL-01服务器,找到桌面网络配置选项,进入网络配置面板。点击面板右下角的小齿轮,进入有线配置面板,选择IPv4选项,将地址设置为手动。接下来配置IP地址、子网掩码、网关和DNS服务器。配置完成后,使用新的IP地址进行访问。
20 4
图形界面配置网络
|
11天前
|
负载均衡 网络协议 算法
|
15天前
|
域名解析 网络协议 安全
|
4天前
|
JSON Shell Linux
配置Python的环境变量可
配置Python的环境变量
16 4
|
3天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
13 2
|
6天前
|
网络虚拟化 数据安全/隐私保护 数据中心
对比了思科和华为网络设备的基本配置、接口配置、VLAN配置、路由配置、访问控制列表配置及其他重要命令
本文对比了思科和华为网络设备的基本配置、接口配置、VLAN配置、路由配置、访问控制列表配置及其他重要命令,帮助网络工程师更好地理解和使用这两个品牌的产品。通过详细对比,展示了两者的相似之处和差异,强调了持续学习的重要性。
18 2
|
7天前
|
网络协议 Linux
通用网卡配置文件配置网络
本文介绍了在RHEL 7系统中配置网络的方法。首先,通过编辑位于`/etc/sysconfig/network-scripts`目录下的网卡配置文件(例如`ifcfg-ens33`),设置静态IP地址、子网掩码、网关和DNS等参数。接着,使用`systemctl`命令重启网络服务,确保配置生效。此外,还介绍了使用`nmtui`图形界面工具进行网络配置的步骤,包括修改IP地址、保存配置和重启网络。最后,通过`ip addr`或`ifconfig`命令验证配置是否成功。
28 2
|
18天前
|
运维 负载均衡 安全
|
Linux 网络安全
linux端口连通性测试telnet、wget、ssh、curl
linux端口连通性测试telnet、wget、ssh、curl
135 0