Skip to content

Instantly share code, notes, and snippets.

@yjuba
Last active March 30, 2021 10:29
Show Gist options
  • Save yjuba/7e49cc03b6f59f22db5426cc18c3836c to your computer and use it in GitHub Desktop.
Save yjuba/7e49cc03b6f59f22db5426cc18c3836c to your computer and use it in GitHub Desktop.

golangからネットワーク機器へsshする

NetOpsCoding AdventCalendar2016の4日目の記事です。

概要

NW機器へsshするプログラムの類を目にしたときに、
私が見かける範囲ではPythonやRubyを利用する例が多いように感じています。

私個人としては、golangを好き好んで使っているので、
もう少しgolangの利用も広がれば嬉しいと思い、golangを利用した例を紹介したいと思います。

PythonやRuby以外にも選択肢があるという情報が、少し広がると個人的には嬉しいです。

下準備

golangの環境については、以下を参考にして頂くと良いと思います。
https://golang.org/doc/install

また、以下のコマンドでssh接続に利用するライブラリを取得しておいて下さい。

go get -u golang.org/x/crypto/ssh

サンプル

サンプルは以下になります。
sample.go
Juniperの機器に対してset cli screen-length 0show sys uptimeおよびexitを実行する例となります。

golang.org/x/crypto/sshが取得済みであれば、以下の様に実行可能です。

go run sample.go

13,14,15行目をそれぞれ自身の環境に合わせて変更してご利用下さい。

説明

サンプルは、そんなに説明が必要なほど大した事はやっていないのですが、
私が実際に業務上で困ったことがある部分について簡単に説明を記載します。

1. 特定のネットワーク機器に接続出来ない

以下の様なエラーが出力されてsshで接続出来ない事がありました。   横に長くなるため、エラーの一部を改行しています。

ssh: handshake failed: ssh: no common algorithm for client to server cipher;
client offered: [aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com arcfour256 arcfour128],
server offered: [aes128-cbc aes192-cbc aes256-cbc 3des-cbc]

エラー内容の通りなのですが、クライアントとサーバ両方で利用可能なサイファが無いのが問題です。

この対応は、サンプルの73-75行目の部分になります。
サンプルでは、デフォルトのサイファにaes128-cbcを追加しています。

    config := ssh.Config{}
    config.SetDefaults()
    config.Ciphers = append(config.Ciphers, "aes128-cbc")

サンプルの該当箇所

2. 特定の機器がchallenge responseによる認証を要求する

タイトルのとおりですが、challenge responseによる認証を要求される場合があります。
sshで接続する際の認証方法については、サンプルの77-90行目が該当します。   サンプルでは、パスワード認証およびchallenge responseによる認証を有効にしています。

    answers := KeyboardInteractive(map[string]string{
        "Password: ": password,
    })

    clientConfig := &ssh.ClientConfig{
        Config: config,
        User:   username,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
            ssh.KeyboardInteractive(
                answers.Challenge,
            ),
        },
    }

サンプルの該当箇所

やっている事は非常に単純で、Password: というサーバからの問いかけに対して、パスワードを返すだけになります。

また、golang.org/x/crypto/sshでは、以下の認証方法を利用する事が可能です。

  • ssh.Password
  • ssh.PasswordCallback
  • ssh.KeyboardInteractive
  • ssh.RetryableAuthMethod
  • ssh.PublicKeys
  • ssh.PublicKeysCallback

ssh.KeyboardInteractiveだけはサンプルが分かりづらく個人的には苦労しました。

まとめ

殆どソースコードを貼り付けただけの内容に近いですが、
個人的にはgolangを使ったNetOpsがもうちょっと出てくると嬉しいと思っています。

時折、golangでなくてもPython/Rubyで良くないですか?と聞かれますが、
私が一番楽出来るのがgolangだったという理由でgolangを採用しています。

個人的には、ツールを作るのは良くても、可能な限りその運用に手をかけたくないと思っています。
(そもそも、運用を楽にするためにわざわざツールを作っているのに、それに手を取られては本末転倒。)

昔は、Pythonで書いていたこともありましたが、
他のサーバに持っていく度に依存するパッケージをインストールしたり、
他の人が関連するパッケージをアップデートすることでツールが壊れたりするのが面倒でした。

また、他の人にツールを渡す際にも、 ツールのセットアップ手順を用意したりするのが面倒というのもあります。
(任せる相手がPython/Rubyに慣れていれば良いのですが、そうでないことも多い。)
その点、バイナリ1個をサーバにおいて叩けば概ねOKなので、気が楽でした。

参考

golang.org/x/crypto/sshのドキュメントです。
https://godoc.org/golang.org/x/crypto/ssh

golangでsshを扱う際の諸々が記載されています。
個人的には、ライブラリのドキュメントと以下のスライドで必要な情報は大体事足りると感じています。
http://talks.rodaine.com/gosf-ssh/present.slide#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment