目次

sshに関して

技術メモなどに色々バラバラに書いていたssh関係を一度まとめる。 詳細は色々な本などにあるだろうし、過去記事のまとめ程度に抑えておく。

ssh とは

sshは、Secure Shell から名前をとった、リモート端末との通信を行うためのプロトコル、コマンドのことをいう。

sshはRFCにより仕様が規定および公開されている。(20190925時点で調べたもの。今ではもっとあるんだろうけど、面倒だから調べてない)

機能関係

以下、CEoR改を実装するために必要となりそうなsshの機能のみに限定してのメモ

対象とする実装は、 OpenSSH とする。これは、CEoRで管理をしたい対象がFreeBSD/OpenBSD/Linux系のOS環境であり、これらには標準的にOpenSSHが採用されているからである。

Option Config Param name default descriptions
-A/-a 認証Agentの転送を許可/禁止
-D Debug logを引数で指定したファイルに書き出す(-v/-vv/-vvv出力)
-e EscapeChar ~ 文字/^文字 指定文字/制御文字をエスケープ文字にする
none: エスケープ文字を禁止する。(Binary Dataに対して透過になる)
-F ~/.ssh/config 設定ファイルを指定する。 システムdefaultは無視される
-f sshの認証後、BackGroundに移行する
-J 引数で指定されたマシンを踏み台にして対象ホストに接続する
対象ホストの名前解決ができなければならない
-L LocalForward Local forward
-l User login名
-N リモートコマンドを実行しない (-Mと併せて使う)
-n stdinを/dev/nullに切り替える。Passphraseなどを入力する必要がある場合 -f を使う
-O -Mで作ったMasterへの制御コマンドを送る。 check: Masterがあるかのチェック
forward: port forwardを要求 / cancel: port forwardをキャンセル
exit: Master Processを終了する / stop: これ以上の分岐を禁止する
-o 設定ファイルと同じ形式でのオプション指定
-M ControlMaster no 単一のネットワーク接続において、複数セッションを共有するか
-Q 問い合わせ。cipher(対象暗号の種類)/cipher-auth(認証付き暗号化をサポートする対象暗号の種類)
mac(メッセージ認証コードの種類)/kex(鍵交換アルゴリズム)/key-cert(証明書の鍵の形式)
-q quiet mode
-R RemoteForward リモーロフォワード
-S ControlPath Master modeにおける制御用Socketファイルの指定
-T/-t RequestTTY セッションに対してTTYを要求するか? no:要求しない/yes:要求する(-t)/forcce:強制的に割り当て(-tt)
-X/-x ForwardX11 no X11接続を転送するか yes:許可/no:禁止
-y logをsysぉg経由で飛ばす。defaultではstderrに出力される
BatchMode no Password/Passphrase入力を求めるか?
CheckHostIP yes knwnhostsファイルのエントリーとの比較を行うか?
ConnectionAttmpts 1 接続試行回数
ConnectTimeout TCP Connectionが成立するまでのTimeout時間の設定
ControlPath Master modeにおける制御用Socketファイルの指定
ControlPersist no: MasterはForegroundのまま、最初のClientが終了した直後に終了
yes / 0 : MasterはBackgroundに移行し、永続的に保持される
数値(秒) / 時間形式 : idleな時間が指定値を越えると接続が終了
OpenSSH 5.6以降でのみ利用可能
ForwardAgent no 認証エージェントへの接続を転送するか
IdentityFile 利用する秘密鍵
force: 常に要求 /auto: loginセッションの時だけ要求する

ControlMaster

ControlMasterに関するCommand line

shell scriptとssh

shell scriptにおいて、ファイルから1行ずつ読み込んで処理をするような場合、以下のようにかける。

while read line; do
  echo ${line}
done < file

ところが、この手を使ってsshを実行すると、なぜか最初の行しか実行されない

while read line; do
  ssh xxx.xxx.xxx.xxx ${line}	# XXX 期待通りに動かない
done < file

原因はsshコマンド実行に伴う標準入力の切替と考えられる。 sshコマンドを実行すると、ローカルホストのstdinからの入力を終了し、sshで指定したリモートホストのstdinからの入力受付を開始する。 従って、ローカルホストのファイルの読込みを終了させた上でsshコマンドを実行し、再びreadコマンドを実行しようとしていると考えられる。もちろん、この時点で既にファイルがcloseされている為、whileが終了してしまう。

対策は、sshに-nオプションをつけること。これよって、sshコマンドのstdin切り替えを禁止することが出来る。

この原因がちっともわからず、数時間を無駄にしてしまった。

while read line; do
  ssh -n xxx.xxx.xxx.xxx ${line}	# これで/dev/nullがsshのstdinにつながる
done < file

このほかに、for文で for line in `cat file` で代用する手も考えられるが、これは、行にスペースがある場合、$lineに代入される値が1行まるごとではなく、スペースまでの部分になるので、ここにも明確な罠があると考えられる。これを回避するにはIFSを変えれば良いのだから、

IFS=$'\n'				# 区切り文字を" "から"\n"に変える
for line in `cat file`; do		# while readの代わりにcatで読み込ませる
  ssh -n xxx.xxx.xxx.xxx ${line}
done

あと、whileはちょっと特殊な制御文で、場合によってはwhile内で変数設定しているはずなのにloopをでてくると変数が空のようなことが起こる。 これは、Whileと他のコマンドを組み合わせた場合、組み合わせ方次第で処理がsubshellがわで処理されてしまう事が原因である。 shellでpipelineを用いて実行した処理は、subshellで処理される。while loopの内部でpipelineを利用すると、whileブロック全体がsubshellで処理されるため、whileブロックの内部と外部で変数の共有が出来ない。 このような場合、whileに対して出力をredirectしてやることで解決できる。

while read line; do
  OUT=`echo ${line} | sed 's/test/test2'`
done < $1
echo ${OUT}

なお、/bin/shの引数に -v-x をつけると、デバッグに大変に役立つ

sftpとscp関連

scpには様々な問題があるということで、scpはDeprecatedになっており、sftpを利用したファイル転送を利用すべきである。

というわけで、メモ

http://d.hatena.ne.jp/cakephper/20120918/1347935609 http://f99aq.hateblo.jp/entry/20090802/1249222491

要するに、/etc/ssh/sshd_configを修正し、対象Dirをroot:wheelにすること。

ちなみに、sshd_configに ForceCommand internal-sftp を追加しないと、passwdに記載されているshellを実行しようとするので注意。

sshと二要素認証

参考

要するに、BSDでは、上記patchを当てないと出来ないが、RSA AuthenticationとChallenge Response Authenticationを組み合わせて二要素認証にするという話。

/etc/ssh/sshd_config の変更点だけ書いておく。

ChallengeResponseAuthentication yes
RSAAuthentication yes

RequiredAuthentications2 publickey,keyboard-interactive

Password Authenticationを使う事は出来ないっぽいけど、まだ試してない。

sshdでPublickeyをauthorized_keys以外から持ってくる

ちょっと某所で sshd でのPublickey Authentication時のPublickeyを~/.ssh/authorized_keys以外から持ってくる設定について聞かれたので、ちょっと調べてみた。

問題

解決

結論

sshの秘密鍵をOS-XのKeychain Accessに登録

OS-Xでman ssh-addしていたら、-KなるOptionを発見した。 そういえば、むかーしむかしに見たような気もする。

<node> -K When adding identities, each passphrase will also be stored in your

      keychain.  When removing identities with -d, each passphrase will
      be removed from your keychain.

</note>

つまり、ssh-add -K しておけば、その後はいちいちパスフレーズを入力しなくてもよくなる。

OS-Xでsshdの待ち受けポートを変更する

MacOS-Xでリモートアクセスを許可すると、sshで接続できるようになる。

しかし、/etc/sshd_configをいじってもsshの待ち受けポートが変わらないので調べてみたら、/System/Library/LaunchDaemons/ssh.plistを修正する必要があるということで、以下のように修正

       <key>Sockets</key>
        <dict>
                <key>Listeners</key>
                <dict>
                        <key>SockServiceName</key>
                        <string>65535</string>
                        <key>Bonjour</key>
                        <array>
                                <string>ssh</string>
                                <string>sftp-ssh</string>
                        </array>
                </dict>
        </dict>

このSockServiceNameの文字列sshを待ち受けたいport番号にかえればOK。なお、この例では65535にしているが、ポート番号は適当にどうぞ。

なお、当然、この変更を行った後で

% sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist
% sudo launchctl load /System/Library/LaunchDaemons/ssh.plist

を実行する事。そうしないと、変更が反映されないよ。ま、再起動でもいいけどね。

sshとcron

Backupを取得するに際して、Backupを元々のServerに置いておいたら、Disk破損の時に一気に死ぬ。 で、そんな事態は救われないので、BackupをRemoteに置いておくために、Backup Scriptまで作ったわけだが、Serverの内側でcronなどでBackupを取得するのは設定ミスとか管理の分散とかが起こってうれしくない。 というわけで、remoteからsshを利用してBackupを取得するようにscriptを作ったのだが、

Pseudo-terminal will not be allocated because stdin is not a terminal.

などといいうErrorが出た。で、これはptyの割り付けないremoteからのコマンドは実行できないということでsshが吐き出すErrorである。

しかし、shell scriptには-tは記載されていて、ちゃんと動くはずだとどはまりをしたわけで…

で、困りに困って調べてみたら、出てました。man ssh

 -t      Force pseudo-tty allocation.  This can be used to execute arbitrary screen-based pro-
         grams on a remote machine, which can be very useful, e.g. when implementing menu ser-
         vices.  Multiple -t options force tty allocation, even if ssh has no local tty.

よく見たら、Multiple -t options force tty allocation, even if ssh has no local tty.だそうな。

要するに、-t -tとしろと。

わかりにくいからメモにしておく。

教訓は、RTFM … orz.

古いNetwork機器に対するssh接続

うちの環境にはいまだに古いAlaxalAのL2 SwitchやApresiaのL3 Switchがあるのだが、これが古いssh protocolをしゃべる。 そのため、2023/05時点のmacOS(Ventura/13.3)だとsshで接続しようとした時にsshの暗号化パラメータ(鍵交換や暗号アルゴリズム)が対応していなくて接続できなくなる。

その解消のためには、~/.ssh/configに以下のような設定を入れておくこと。

# for AlaxalA AX2430S
Host [IP Address] [alias name] ...
        HostKeyAlgorithms       ssh-dss
        KexAlgorithms           +diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1

# for Apressia
Host [IP Address] [alias name] ...
        KexAlgorithms           +diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1