🗝️

[Ruby] net-ssh v6.1.0(Net::SSH_6.1.0)の奮闘記

に公開

バージョン

  • クライアント:Net::SSH_6.1.0
  • サーバー:OpenSSH_9.6p1

経緯

とあるRubyを使用したシステムに、SSH2クライアントプロトコルを純粋に実装したライブラリnet-ssh(Net::SSH)でのSSH接続を行う処理が存在し、そこでいくつか問題が発生したので一つ一つ解決していきました。

其の壱

問題

最初はシンプルにNet::SSHの認証エラーが出ました。(username@example.comの部分は置き換えています。)

Net::SSH::AuthenticationFailed: Authentication failed for user username@example.com
...
check out ssh secret key, config, known_hosts, and so on.

結構ざっくりとしたエラー内容なのでいきなり苦戦しました。

解決

今回サーバー側の環境が最新のOSを使用しておりそれでOpenSSHのバージョンも上がりその関係でエラーが起きているのではと思い調べたところ、下記のような記事を見つけました。

https://news.mynavi.jp/techplus/article/20200529-1044828/

OpenSSH 8.3以降のバージョンでは、「ssh-rsa」公開鍵署名アルゴリズムをデフォルトで無効化するようになっている(SHA-1アルゴリズムの脆弱性に対する処置)ようです。「ssh-rsa」はキーペアを生成するssh-keygenで、アルゴリズム指定をしないとこちらで秘密鍵・公開鍵が生成されます。

今回はまさにssh-rsaを使用しており、新たにed25519で鍵を生成し接続しなおしました。

$ ssh-keygen -t ed25519

すると上記のようなエラーは無くなりました。

其の弐

問題

壱の問題が解消し、エラーなく処理が進んている、よかった!

と思いながら画面を眺めていたところ、処理がいつまでたっても終わらない。

エラーも特に出ないので、しびれを切らしてサーバー側のログを確認したところ、

/var/log/auth.log
Connection closed by authenticating user username xxx.xxx.xxx.xxx port yyy [preauth]

人知れず接続が拒否されてる!?

解決

またもや認証系が関わっていそうだったのでさらに調査したところ、下記のような記事を見つけました。

https://hirose31.hatenablog.jp/entry/2022/04/25/141938

この記事には先ほどのssh-rsaについても言及しており、さらにそれ以外の鍵を使用した場合の挙動についても書かれていました。

すこしまとめると、下記のように言及されていました。

Ruby の net-ssh で接続するには、rsa 以外の鍵を使う
・手元の環境では ecdsa 鍵なら追加 gem なしで接続できた
・ed25519 鍵は追加 gem が必要な模様

先ほど新たに生成したed25519を使用する場合は追加のgemが必要なようです。
ただ、ecdsaであればそのまま接続できるみたいです。

$ ssh-keygen -t ecdsa

鍵を新たに作り直し、再試行してみたところ、サーバー側のログに変化がありました。

其の参

問題

ログに変化はあったものの、最終的には接続が拒否されます。

Postponed publickey for username from xxx.xxx.xxx.xxx port yyy ssh2 [preauth]
Connection closed by authenticating user username xxx.xxx.xxx.xxx port yyy [preauth]

ただ今回は、Postponed publickey for ...というログのあと30秒ほど待機し、
そのまま接続が切れています。

解決

Net::SSHにはuse_agentというオプションがあり、これがデフォルトでtrueになっているようです。

https://www.rubydoc.info/gems/net-ssh/Net/SSH#assign_defaults-class_method

これはssh-agentを使用するかどうかのオプションで、そのシステムではtrueになっていました。
なのでssh-agentに秘密鍵を登録しておく必要がありました。

クライアント側で下記のように起動し鍵を登録しておきます。

# SSHエージェントの起動
$ eval "$(ssh-agent -s)"
Agent pid 3083853
# エージェントに鍵がロードされているか確認
$ ssh-add -l
The agent has no identities.
# エージェントに鍵を追加
$ ssh-add /home/user/.ssh/id_ecdsa
Identity added: /home/user/.ssh/id_ecdsa (user@server-A)
# 確認
$ ssh-add -l
3072 ECDSA:MYZ3Nm2gmpPTFDgLWKNZXrh6Zky3q7BsyeVXu5h3eun user@server-A (ECDSA)

すると、無事問題が解消しssh接続処理が走るようになりました!
これで安心して眠れる。。。

注意点

SSHエージェントに追加した鍵の有効範囲は「1セッション毎」になります。
よって一度CLIからログアウトしたり、別窓を立てたりする場合は鍵を再度追加する必要があります(不安な場合は都度ssh-add -lで確認してみてください)。

Discussion