RFC 4742 - NETCONF over SSH

RFC 网络协议文档 > RFC 4742 - NETCONF over SSH

RFC 4742 - NETCONF over SSH

通过安全 Shell(SSH)使用 NETCONF 配置协议

摘要

The NETCONF protocol [RFC4721] is an XML-based protocol used to manage the configuration of networking equipment. NETCONF is defined to be session-layer and transport independent, allowing mappings to be defined for multiple session-layer or transport protocols. This document defines how NETCONF can be used within a Secure Shell (SSH) session, using the SSH connection protocol [RFC4254] over the SSH transport protocol [RFC4253]. This mapping will allow NETCONF to be executed from a secure shell session by a user or application.

NETCONF协议[RFC4721]是一种基于XML的协议,用于管理网络设备的配置。NETCONF被定义为会话层和传输独立,允许为多个会话层或传输协议定义映射。本文档定义了如何在安全Shell(SSH)会话中使用NETCONF,通过SSH传输协议[RFC4253]使用SSH连接协议[RFC4254]。此映射将允许用户或应用程序从安全shell会话执行NETCONF。

1. 介绍

Throughout this document, the terms “client” and “server” are used to refer to the two ends of the SSH transport connection. The client actively opens the SSH connection, and the server passively listens for the incoming SSH connection. The terms “manager” and “agent” are used to refer to the two ends of the NETCONF protocol session. The manager issues NETCONF remote procedure call (RPC) commands, and the agent replies to those commands. When NETCONF is run over SSH using the mapping defined in this document, the client is always the manager, and the server is always the agent.

在本文档中,术语”客户机”和”服务器”用于表示SSH传输连接的两端。客户端主动打开SSH连接,服务器被动侦听传入的SSH连接。术语”管理器”和”代理”用于表示NETCONF协议会话的两端。管理器发出NETCONF远程过程调用(RPC)命令,代理对这些命令进行响应。当使用本文档中定义的映射在SSH上运行NETCONF时,客户机始终是管理器,服务器始终是代理。

2. 需求术语

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 [RFC2119].

本文件中的关键词”必须”、”不得”、”要求”、”应”、”不应”、”应”、”不应”、”建议”、”可”和”可选”应按照RFC 2119[RFC2119]中所述进行解释。

3. 通过SSH启动NETCONF

To run NETCONF over SSH, the client will first establish an SSH transport connection using the SSH transport protocol, and the client and server will exchange keys for message integrity and encryption. The client will then invoke the “ssh-userauth” service to authenticate the user, as described in the SSH authentication protocol [RFC4252]. Once the user has been successfully authenticated, the client will invoke the “ssh-connection” service, also known as the SSH connection protocol.

要通过SSH运行NETCONF,客户端将首先使用SSH传输协议建立SSH传输连接,客户端和服务器将交换消息完整性和加密的密钥。然后,客户端将调用”ssh userauth”服务对用户进行身份验证,如ssh身份验证协议[RFC4252]中所述。一旦用户成功通过身份验证,客户端将调用”ssh连接”服务,也称为ssh连接协议。

3.1 SSH 连接建立

The SSH connection is established as follows:

SSH连接建立如下:

  1. 传输层连接: 客户端建立到服务器的TCP连接
  2. 密钥交换: 客户端和服务器交换密钥
  3. 用户认证: 客户端使用SSH认证协议进行身份验证
  4. 服务请求: 客户端请求NETCONF服务

3.2 NETCONF 服务启动

Once the SSH connection is established and the user has been authenticated, the client opens a channel of type “session” within the SSH connection. The client will then invoke the “netconf” subsystem over the SSH session.

一旦SSH连接建立且用户已通过身份验证,客户端在SSH连接内打开类型为”session”的通道。然后客户端将通过SSH会话调用”netconf”子系统。

4. SSH 端口和子系统的使用

4.1 默认端口

NETCONF over SSH uses the IANA-assigned port 830 for the NETCONF over SSH service.

通过SSH的NETCONF使用IANA分配的端口830用于通过SSH的NETCONF服务。

4.2 子系统名称

The subsystem name is “netconf”. The subsystem is invoked using the SSH “subsystem” request.

子系统名称是”netconf”。使用SSH”subsystem”请求调用子系统。

5. 消息格式

5.1 帧格式

NETCONF over SSH uses a simple framing mechanism. Each NETCONF message is sent as a complete XML document. The message is prefixed with a length header.

通过SSH的NETCONF使用简单的帧机制。每个NETCONF消息作为完整的XML文档发送。消息前面有一个长度头。

+----------+----------+----------+----------+----------+
|  Length  |  Length  |  Length  |  Length  |  XML     |
|  (MSB)   |          |          |  (LSB)   |  Document|
+----------+----------+----------+----------+----------+

5.2 长度头格式

The length header is a 4-byte integer in network byte order (big-endian) that specifies the length of the XML document in bytes.

长度头是一个4字节的整数,按网络字节顺序(大端序)排列,指定XML文档的字节长度。

6. 能力协商

6.1 Hello 消息

The NETCONF session begins with the exchange of hello messages between the client and server. The hello message is used to exchange capabilities and session identifiers.

NETCONF会话以客户端和服务器之间交换hello消息开始。hello消息用于交换功能和会话标识符。

<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
    <capability>urn:ietf:params:netconf:base:1.1</capability>
  </capabilities>
  <session-id>4</session-id>
</hello>

6.2 能力交换

The client and server exchange their capabilities in the hello message. Each capability is identified by a URI.

客户端和服务器在hello消息中交换其功能。每个功能由URI标识。

7. 安全考虑

7.1 身份验证

SSH provides strong authentication mechanisms. The client MUST authenticate to the server using one of the supported SSH authentication methods.

SSH提供强身份验证机制。客户端必须使用支持的SSH身份验证方法之一向服务器进行身份验证。

7.2 数据完整性

SSH provides data integrity protection through message authentication codes (MACs).

SSH通过消息认证码(MAC)提供数据完整性保护。

7.3 数据机密性

SSH provides data confidentiality through encryption.

SSH通过加密提供数据机密性。

8. 实现示例

8.1 Python 实现

import paramiko
import xml.etree.ElementTree as ET

class NETCONFClient:
    def __init__(self, host, port=830, username=None, password=None):
        self.host = host
        self.port = port
        self.username = username
        self.password = password
        self.ssh = None
        self.channel = None
    
    def connect(self):
        """建立SSH连接并启动NETCONF会话"""
        self.ssh = paramiko.SSHClient()
        self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        self.ssh.connect(self.host, self.port, self.username, self.password)
        
        # 打开会话通道
        self.channel = self.ssh.invoke_subsystem('netconf')
        
        # 交换hello消息
        self._exchange_hello()
    
    def _exchange_hello(self):
        """交换hello消息"""
        hello = '''<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
            <capabilities>
                <capability>urn:ietf:params:netconf:base:1.0</capability>
            </capabilities>
        </hello>]]>]]>'''
        
        self.channel.send(hello)
        response = self._receive_message()
        return response
    
    def get_config(self, source='running'):
        """获取配置"""
        rpc = f'''<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
            <get-config>
                <source>
                    <{source}/>
                </source>
            </get-config>
        </rpc>]]>]]>'''
        
        self.channel.send(rpc)
        return self._receive_message()
    
    def _receive_message(self):
        """接收消息"""
        data = ""
        while True:
            chunk = self.channel.recv(1024).decode('utf-8')
            data += chunk
            if ']]>]]>' in data:
                break
        return data.replace(']]>]]>', '')
    
    def close(self):
        """关闭连接"""
        if self.channel:
            self.channel.close()
        if self.ssh:
            self.ssh.close()

# 使用示例
client = NETCONFClient('192.168.1.1', username='admin', password='password')
client.connect()
config = client.get_config()
print(config)
client.close()

8.2 命令行工具

# 使用 ssh 直接连接
ssh -s admin@192.168.1.1 netconf

# 使用 netconf 客户端工具
netconf-console --host 192.168.1.1 --port 830 --user admin

# 使用 Python ncclient 库
python -c "
from ncclient import manager
with manager.connect(host='192.168.1.1', port=830, username='admin', 
                    password='password', hostkey_verify=False) as m:
    print(m.get_config(source='running'))
"

9. 故障排除

9.1 常见问题

  1. 连接被拒绝: 检查SSH服务是否运行在端口830
  2. 认证失败: 检查用户名和密码是否正确
  3. 子系统不可用: 检查NETCONF子系统是否已安装
  4. 消息格式错误: 检查XML格式是否正确

9.2 调试技巧

  1. 启用SSH调试: 使用 -v 参数启用详细输出
  2. 检查日志: 查看服务器端的NETCONF日志
  3. 验证XML: 使用XML验证工具检查消息格式
  4. 网络抓包: 使用Wireshark等工具分析网络流量

10. 最佳实践

10.1 安全配置

  1. 使用密钥认证: 避免使用密码认证
  2. 限制访问: 使用防火墙限制SSH访问
  3. 定期更新: 保持SSH和NETCONF软件更新
  4. 监控日志: 定期检查访问日志

10.2 性能优化

  1. 连接复用: 复用SSH连接进行多个操作
  2. 批量操作: 使用批量操作减少网络开销
  3. 超时设置: 设置合理的超时时间
  4. 错误处理: 实现适当的错误处理和重试机制

11. 参考资料


本文档基于 RFC 4742 标准,如有问题请提交 Issue 或 Pull Request。