跳到主要内容

3. TACACS+ 数据模型的设计

本模块用于在设备上配置 TACACS+ 客户端 (TACACS+ client), 以支持使用集中式 AAA 服务器的部署场景. 认证 (authentication) 用于验证用户的用户名和密码, 授权 (authorization) 允许用户访问并执行分配给该用户的各种特权级别的命令, 计费 (accounting) 则跟踪已访问设备的用户活动.

ietf-system-tacacs-plus 模块使用 tacacs-plus 分组的内容来扩充 ietf-system 模块中定义的 /sys:system 路径. 因此, 设备可以使用本地, RADIUS 或 TACACS+ 认证, 通过多种机制验证尝试访问设备的用户, 例如命令行接口或基于 Web 的用户接口.

直接位于 tacacs-plus 容器下的 server 列表保存 TACACS+ 服务器列表, 并使用 server-type 区分不同的 AAA 服务. 该服务器列表用于冗余.

当多个接口连接到 TACACS+ 客户端或服务器时, 可以指定传出 TACACS+ 数据包的源地址, 也可以通过接口 IP 地址设置来指定源地址, 或根据本地转发信息库 (Forwarding Information Base, FIB) 中的出站接口推导源地址. 对于位于虚拟专用网络 (Virtual Private Network, VPN) 中的 TACACS+ 服务器, 需要指定 VRF 实例.

server 列表下的 statistics 容器是一组只读计数器, 用于统计与已配置服务器之间发送和接收的消息.

TACACS+ 客户端的 YANG 模块具有图 1 所示的结构.

augment /sys:system:
  +--rw tacacs-plus
     +--rw client-credentials* [id] {credential-reference}?
     |  +--rw id                       string
     |  +--rw (auth-type)?
     |     +--:(certificate)
     |     |  ...
     |     +--:(raw-public-key) {tlsc:client-ident-raw-public-key}?
     |     |  ...
     |     +--:(tls13-epsk) {tlsc:client-ident-tls13-epsk}?
     |        ...
     +--rw server-credentials* [id] {credential-reference}?
     |  +--rw id                 string
     |  +--rw ca-certs!
     |  |  ...
     |  +--rw ee-certs!
     |  |  ...
     |  +--rw raw-public-keys! {tlsc:server-auth-raw-public-key}?
     |  |  ...
     |  +--rw tls13-epsks?       empty
     |          {tlsc:server-auth-tls13-epsk}?
     +--rw server* [name]
        +--rw name                           string
        +--rw server-type
        |       tacacs-plus-server-type
        +--rw domain-name?                   inet:domain-name
        +--rw sni-enabled?                   boolean
        +--rw address                        inet:host
        +--rw port                           inet:port-number
        +--rw (security)
        |  +--:(tls)
        |  |  +--rw client-identity!
        |  |  |  +--rw (ref-or-explicit)?
        |  |  |     +--:(ref)
        |  |  |     |  +--rw credentials-reference?
        |  |  |     |          sys-tcs-plus:client-credentials-ref
        |  |  |     |          {credential-reference}?
        |  |  |     +--:(explicit)
        |  |  |        +--rw (auth-type)?
        |  |  |           +--:(certificate)
        |  |  |           |  ...
        |  |  |           +--:(raw-public-key)
        |  |  |           |     {tlsc:client-ident-raw-public-key}?
        |  |  |           |  ...
        |  |  |           +--:(tls13-epsk)
        |  |  |                 {tlsc:client-ident-tls13-epsk}?
        |  |  |              ...
        |  |  +--rw server-authentication
        |  |  |  +--rw (ref-or-explicit)?
        |  |  |     +--:(ref)
        |  |  |     |  +--rw credentials-reference?
        |  |  |     |          sys-tcs-plus:server-credentials-ref
        |  |  |     |          {credential-reference}?
        |  |  |     +--:(explicit)
        |  |  |        +--rw ca-certs!
        |  |  |        |  ...
        |  |  |        +--rw ee-certs!
        |  |  |        |  ...
        |  |  |        +--rw raw-public-keys!
        |  |  |        |       {tlsc:server-auth-raw-public-key}?
        |  |  |        |  ...
        |  |  |        +--rw tls13-epsks?             empty
        |  |  |                {tlsc:server-auth-tls13-epsk}
        |  |  +--rw hello-params {tlscmn:hello-params}?
        |  |     +--rw tls-versions
        |  |     |  +--rw min?   identityref
        |  |     |  +--rw max?   identityref
        |  |     +--rw cipher-suites
        |  |        +--rw cipher-suite*
        |  |                tlscsa:tls-cipher-suite-algorithm
        |  +--:(obfuscation)
        |     +--rw shared-secret?           string
        +--rw (source-type)?
        |  +--:(source-ip)
        |  |  +--rw source-ip?               inet:ip-address
        |  +--:(source-interface)
        |     +--rw source-interface?        if:interface-ref
        +--rw vrf-instance?
        |       -> /ni:network-instances/network-instance/name
        +--rw single-connection?             boolean
        +--rw timeout?                       uint16
        +--ro statistics
           +--ro discontinuity-time?    yang:date-and-time
           +--ro connection-opens?      yang:counter64
           +--ro connection-closes?     yang:counter64
           +--ro connection-aborts?     yang:counter64
           +--ro connection-failures?   yang:counter64
           +--ro connection-timeouts?   yang:counter64
           +--ro messages-sent?         yang:counter64
           +--ro messages-received?     yang:counter64
           +--ro errors-received?       yang:counter64
           +--ro sessions?              yang:counter64
           +--ro cert-errors?           yang:counter64
           +--ro rpk-errors?            yang:counter64
                   {tlsc:server-auth-raw-public-key}?

图 1: 树结构概览

具体而言, 该模块旨在覆盖 [RFC 9887] 中规定的以下关键要求:

  • 传输必须使用最低 TLS 1.3 [RFC 8446].

  • 不得使用更早的 TLS 版本.

  • 所提供或接受的密码套件 (cipher suites) 应当可配置.

  • 实现可以支持原始公钥 (raw public keys) 和预共享密钥 (Pre-Shared Keys, PSKs).

  • 实现必须支持配置服务器域名的能力, 以便可以将该域名包含在 TLS 服务器名称指示 (Server Name Indication, SNI) 扩展中.

与 [RFC 9105] 相比, 支持以下新的数据节点:

client-credentials 和 server-credentials: 定义一组可以全局预配并随后在特定服务器下引用的凭据.

domain-name: 根据 [RFC 9887] 第 3.4.2 节提供服务器的域名. 这是包含在 SNI 扩展中的 TLS TACACS+ 服务器域名. 该域名不同于底层传输连接所使用的 IP 地址或主机名.

sni-enabled: 控制 SNI 的激活 ([RFC 6066] 第 3 节). 只有在提供域名时, 才能使用此参数.

client-identity: 指定客户端在与服务器建立连接时可以出示的身份凭据. 客户端身份可以在顶层配置, 然后由特定服务器实例引用. 也可以在每个服务器实例下显式配置客户端身份.

server-authentication: 指定客户端如何认证服务器. 服务器凭据可以在顶层配置, 然后由特定服务器实例引用. 也可以在每个服务器实例下显式配置客户端身份.

hello-params: 控制建立 TLS 会话时使用的 TLS 版本和密码套件.

discontinuity-time: 客户端最近一次发生不连续性的时间, 例如用于重置所有计数器的配置操作, 重新初始化等.

cert-errors: 因证书问题导致的连接失败次数.

rpk-errors: 与原始公钥相关的连接失败次数.