napalm の 6 倍速いネットワーク機器用リモートコマンド実行ツールを書きました

ネットワーク機器のコマンドをリモート実行するツール「telee」を書きました。

https://github.com/umatare5/telee

このツールは、機器へのログイン処理とコマンド実行を代理します。
従来の expect スクリプト, NAPALM や Ansible の役割を部分的に担えます。

以下は動作例です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1472771/fc8195c8-0685-45b8-b08c-beef5946ffec.gif" width=90%>
Cisco 社製 OS はもちろん、Juniper, YAMAHA 等、他社製 OS へのログインにも対応しています。
接続プロトコルは telnet もしくは ssh が選択出来ます。その他のプロトコルには対応していません。

実行速度を NAPALM の同一機能と比較すると、一般的な用途で 6 - 72 倍高速です。
※ 測定の詳細は [Performance Comparison: telee and napalm](https://github.com/umatare5/telee/tree/main/docs/performance_comparison) をご確認ください。

最新版のバイナリは、リポジトリの [Releases page](https://github.com/umatare5/telee/releases) からダウンロード出来ます。
プラットフォームは、Linux, Mac の amd64, arm64 にそれぞれ対応しています。

- 記事更新時点の最新バージョンは v1.7.6 です。
  - [Download v1.7.6 for Linux 64-bit](https://github.com/umatare5/telee/releases/download/v1.7.6/telee-v1.7.6_linux_amd64.tar.gz)
  - [Download v1.7.6 for Linux 64-bit ARM](https://github.com/umatare5/telee/releases/download/v1.7.6/telee-v1.7.6_linux_arm64.tar.gz)
  - [Download v1.7.6 for Mac OS 64-bit](https://github.com/umatare5/telee/releases/download/v1.7.6/telee-v1.7.6_darwin_amd64.tar.gz)
  - [Download v1.7.6 for Mac OS 64-bit ARM (M1)](https://github.com/umatare5/telee/releases/download/v1.7.6/telee-v1.7.6_darwin_arm64.tar.gz)

ネットワークエンジニアの皆様、ぜひお試しください。フィードバックも大歓迎です。

以下、詳細です。

## 背景

ネットワーク機器の操作には、telnet を利用する場合があります。
しかし telnet は、公開鍵のようなシームレスな認証に対応していません。
機器にログインするには、大半のケースでユーザ・パスワード認証が必要です。

この入力に手間を感じていました。

ネットワーク業界で最も高いシェアを持つ Cisco 社製のスイッチを例に取ります。
このスイッチで設定の一覧を表示するには、以下の 7 ステップが必要です。

- (1) telnet コマンドを実行
- (2) ユーザ名を入力
- (3) パスワードを入力
- (4) enable コマンドを実行
- (5) 特権 EXEC パスワードを入力
- (6) terminal length 0 コマンドを実行
- (7) show running-config コマンドを実行

多いです。数台であれば耐えられますが、台数が増えるにつれて辛みも増していきます。

## 解決策

この課題は、一般的に以下のような手段で解決します。

- (1) [TeraTerm マクロ](https://ttssh2.osdn.jp/manual/4/ja/macro/) で TTL ファイルを書く
- (2) [expect コマンド](https://linux.die.net/man/1/expect) を用いてスクリプトを書く
- (3) [Ansible](https://www.ansible.com/) の [network_cli module](https://docs.ansible.com/ansible/latest/collections/ansible/netcommon/network_cli_connection.html) 等を用いて task を書く
- (4) [NAPALM](https://napalm-automation.net/) を用いてコードまたは YAML を書く
- (5) [NAPALM: Command Line Tool](https://napalm.readthedocs.io/en/latest/cli.html) を利用する
 
(1) - (4) は、いずれも 1 行のコマンドを実行するために複数行の構文が必要です。
また、運用継続に伴ってスクリプトやコードが焼き増された場合、多重メンテが必要になります。

(5) は解決策たりえますが、telnet や SSH と比較すると処理が緩慢で、普段使いには難があります。
豊富な機能を搭載している反面、ワンラインが伸びやすく、簡潔に書きづらい点も課題です。

これらを回避しつつ、より手軽にコマンドを実行したいという思いで、今回「telee」を書きました。

## 利用方法

以下は、記事作成時点の README.md (日本語版) です。最新の情報は[リポジトリ](https://github.com/umatare5/telee)をご参照ください。

### 基本書式

```
telee -H HOSTNAME -C COMMAND [options...]
```

### コマンドオプション

|オプション             |概要                            |デフォルト値  |環境変数          |
|:------------------|--------------------------------|----------|-----------------|
|--hostname<br>(-H)                             |ホスト名または IP アドレスを<br>指定します。  |-         |$TELEE_HOSTNAME |
|--port<br>(-P)                                        |ポート番号を指定します。              |23       |- |
|--command<br>(-C)                                   |実行するコマンドを指定します。          |-         |$TELEE_COMMAND  |
|--exec-platform<br>(-x)                             |接続先の環境名を指定します。<br>※後述参照  |ios       |-                |
|--username<br>(-u)                                  |ユーザ名を指定します。               |admin      |$TELEE_USERNAME |
|--password<br>(-p)                                  |パスワードを指定します。              |cisco     | $TELEE_PASSWORD |
|--priv-password<br>(--pp)                          |特権モードのパスワードを<br>指定します。     |enable     |$TELEE_PRIVPASSWORD |
|--enable-mode<br>(-e, --ena, --enable)  |特権モードの利用時に<br>設定します。   |false      |-               |
|--redundant-mode<br>(-r, --redundant)  |HA 専用のプロンプトを持つ<br>機器への接続時に設定します。   |false      |-               |
|--secure-mode<br>(-s, --sec, --secure)  |SSH での接続時に設定します。<br>--port は 22 に設定されます。   |false      |-               |
|--timeout<br>(-t)                                   |タイムアウト秒を指定します。       |5         |-                |


### Exec Platform

- `--exec-platform` はログインプロンプトの識別に利用しています。
- 指定を誤った場合、正常にログイン出来ず、コマンドがタイムアウトします。
- 指定可能なプラットフォームと、動作確認バージョンはそれぞれ以下の通りです。

| 定義名 (-x 指定)  | プラットフォーム名                       | Telnet          | SSH|     
| :-------------- | :---------------------------- | :-------------- | :------------- |
| aireos          | Cisco AireOS                  | ✅ 8.5.120.0    | ✅ 8.5.120.0  |
| allied          | AlliedTelesis AlliedWare      | ✅ 1.6.14B02    | Not Supported  |
| asa             | Cisco ASA Software            | ✅ 9.0(4)       | Not Supported  | 
| asa (redundant) | Cisco ASA Software (HA)       | ✅ 9.10(1)      | Not Supported |
| foundry         | Brocade IronWare              | ✅ 07.2.02aT7e1 | Not Supported  |
| ios             | Cisco IOS, IOS-XE       | ✅ 15.2(5c)E    | ✅ 15.2(5c)E   |
| nxos            | Cisco NX-OS       | ✅ 6.2(14)    | Not Supported  |
| srx             | JuniperNetworks JunOS      | Not Supported    | ✅ 15.1X49-D90.7 |
| ssg             | JuniperNetworks ScreenOS      | ✅ 6.3.0r21.0   | Not Supported  |
| ssg (redundant) | JuniperNetworks ScreenOS (HA) | ✅ 6.3.0r22.0   | Not Supported |
| yamaha          | YAMAHA Router OS                  | ✅ Rev.8.03.94  |  ✅ Rev.10.01.78 |

### 実行手順

- ログインに利用するユーザ名とパスワードを、環境変数に設定します。

```bash
export TELEE_USERNAME=telee
export TELEE_PASSWORD=Teleedev!
export TELEE_PRIVPASSWORD=Teleedev!!
```

- ホスト名を指定してコマンドを実行します。

```console
$ telee --hostname lab-cat29l-02f99-01 --command "show int descr"
show int descr
Load for five secs: 2%/0%; one minute: 1%; five minutes: 1%
Time source is NTP, 23:16:54.302 JST Sat May 8 2021

Interface                      Status         Protocol Description
Vl1                            admin down     down
Vl800                          up             up       *** LAB-MGMT ***
Gi0/1                          up             up       CLIENT_DEVICE_LONG_DESCR
Gi0/2                          up             up       CLIENT_DEVICE
Gi0/3                          up             up       CLIENT_DEVICE
Gi0/4                          up             up       CLIENT_DEVICE
Gi0/5                          up             up       CLIENT_DEVICE
Gi0/6                          down           down     CLIENT_DEVICE
Gi0/7                          down           down     CLIENT_DEVICE
Gi0/8                          up             up       GATEWAY_ROUTER
Gi0/9                          admin down     down
Gi0/10                         admin down     down
lab-cat29l-02f99-01>
```

完了です。

### 応用例

#### パイプやリダイレクトにかける

- 出力結果を別のコマンドで処理出来ます。以下のように実行します。

<details><summary>実行例</summary><div>

```console
$ telee --hostname lab-cat29l-02f99-01 --command "show int descr" | grep "Interface\|down"
Interface                      Status         Protocol Description
Vl1                            admin down     down
Gi0/1                          down           down     CLIENT_DEVICE_LONG_DESCR
Gi0/6                          down           down     CLIENT_DEVICE
Gi0/7                          down           down     CLIENT_DEVICE
Gi0/9                          admin down     down
Gi0/10                         admin down     down
```

```console
$ telee --hostname lab-cat29l-02f99-01 --command "show run" --enable > telee.log
$ head -n 10 telee.log
show run
Load for five secs: 1%/0%; one minute: 1%; five minutes: 1%
Time source is NTP, 23:21:34.501 JST Sat May 8 2021

Building configuration...

Current configuration : 18687 bytes
!
! Last configuration change at 01:30:16 JST Sun Feb 14 2021
!
```

</div></details>

#### Cisco IOS 以外を操作する

- `--exec-platform` オプションの指定が必要です。
- AireOS を操作する場合は、以下のように実行します。

<details><summary>実行例</summary><div>

```console
$ telee -H 192.168.0.250 -C "show sysinfo" -x aireos
show sysinfo

Manufacturer's Name.............................. Cisco Systems Inc.
Product Name..................................... Cisco Controller
Product Version.................................. 8.5.120.0
Bootloader Version............................... 1.0.20
Field Recovery Image Version..................... 7.6.101.1
Firmware Version................................. PIC 19.0

OUI File Last Update Time........................ Sun Sep 07 10:44:07 IST 2014

Build Type....................................... DATA + WPS

System Name...................................... lab-wlc-01f01-01a
System Location..................................
System Contact...................................
System ObjectID.................................. 1.3.6.1.4.1.9.1.1279
IP Address....................................... 192.168.0.250
<snip>
```

</div></details>

#### Cisco ASA を操作する

- `--enable-mode` オプションの指定が必要です。
- Cisco ASA は、ユーザ権限で terminal pager 0 が実行出来ません。
- Cisco ASA を操作する場合は、以下のように実行します。

<details><summary>実行例</summary><div>

```console
$ telee -H lab-asa5505-02f01-01 -C "show version" -x asa --enable-mode
show version

Cisco Adaptive Security Appliance Software Version 9.0(4)
Device Manager Version 7.1(5)100

Compiled on Wed 04-Dec-13 08:33 by builders
System image file is "disk0:/asa904-k8.bin"
Config file at boot was "startup-config"

lab-asa5505-02f01-01 up 70 days 2 hours

Hardware:   ASA5505, 512 MB RAM, CPU Geode 500 MHz,
Internal ATA Compact Flash, 128MB
BIOS Flash M50FW016 @ 0xfff00000, 2048KB

Encryption hardware device : Cisco ASA-5505 on-board accelerator (revision 0x0)
                             Boot microcode        : CN1000-MC-BOOT-2.00
                             SSL/IKE microcode     : CNLite-MC-SSLm-PLUS-2.03
<snip>
```

</div></details>

#### SSH で接続する

- `--secure-mode` オプションの指定が必要です。以下のように実行します。

<details><summary>実行例</summary><p>

```console
$ telee -H lab-cat29l-02f99-01 -C "show run" --enable --secure
show run
Load for five secs: 8%/0%; one minute: 2%; five minutes: 1%
Time source is NTP, 02:25:22.496 JST Fri May 14 2021

Building configuration...

Current configuration : 18716 bytes
!
! Last configuration change at 01:46:41 JST Fri May 14 2021 by raciadev
!
version 15.2
no service pad
service tcp-keepalives-in
service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec localtime show-timezone
service password-encryption
!
hostname lab-cat29l-02f99-01
<snip>
```

</div></details>

#### 応答の遅い機器を操作する

- `--timeout` でタイムアウト値を調整出来ます。以下のように実行します。

<details><summary>実行例</summary><div>

```console
$ telee -H lab-fs909-02f01-01 -C "show system" -x allied -u manager --timeout 10
show system
Switch System Status                     Date 2021-05-09 Time 01:04:54
Board     Bay      Board Name
----------------------------------------------------------------------
Base      -        FS909M
----------------------------------------------------------------------
Memory -  DRAM : 32768 kB  FLASH : 8192 kB   MAC : 00-1A-EB-93-1C-95
----------------------------------------------------------------------
SysDescription  : CentreCOM FS909M Ver 1.6.14 B02
SysContact      :
SysLocation     : LAB
SysName         : lab-fs909-02f01-01
SysUpTime       : 1267989237(146days, 18:11:32)
Release Version : 1.6.14
Release built   : B02 (Nov 23 2010 at 14:29:56)
Flash PROM      : Good
RAM             : Good
SW chip         : Good
<snip>
```

</div></details>

#### RADIUS Attribute を用いて特権を付与した環境で利用する

- `--default-privilege-mode` オプションの指定が必要です。以下のように実行します。

<details><summary>実行例</summary><p>

```console
$ telee -H lab-nx70-02f01-01 -C "show version" -x nxos --default-privilege-mode
show version
Cisco Nexus Operating System (NX-OS) Software
TAC support: http://www.cisco.com/tac
Documents: http://www.cisco.com/en/US/products/ps9372/tsd_products_support_series_home.html
Copyright (c) 2002-2015, Cisco Systems, Inc. All rights reserved.
The copyrights to certain works contained in this software are
owned by other third parties and used and distributed under
license. Certain components of this software are licensed under
the GNU General Public License (GPL) version 2.0 or the GNU
Lesser General Public License (LGPL) Version 2.1. A copy of each
such license is available at
http://www.opensource.org/licenses/gpl-2.0.php and
http://www.opensource.org/licenses/lgpl-2.1.php

Software
BIOS:      version N/A
kickstart: version 6.2(14)
system:    version 6.2(14)
BIOS compile time:
kickstart image file is: bootflash:///n7000-s1-kickstart.6.2.14.bin
<snip>
```

</div></details>


## おわりに

今回は、ネットワーク機器の運用を効率化するツールを紹介しました。

ネットワーク機器のコマンド実行結果をシェル上で直接扱うことには、汎用性があります。

例えば、旧来の Rancid や Ansible による情報取得を、より単純なシェルスクリプトで代替出来ます。
コマンドとシェルの知識だけ持っていれば良いため、学習コスト・運用コストとも安く済みます。

Syslog サーバを有している場合は、EEM のように、ログに基づいたコマンドの実行が出来ます。
サーバ主導となるため、A のログをトリガーに B でコマンドを実行、といった構成が実現出来ます。

有効なユースケースがありましたら是非お試しください。

最後までお読み頂きありがとうございました。