SSH (Secure SHell)です。コマンドラインでほとんどの全てのUnixのリモートコントロールが出来ます。 逆に言うと管理が甘いと完全に乗っ取られます。 通常はSSHでログインする時にはパスワードでの認証をして入りますが、特定の手順をとるとパスワードのやりとりを省いて接続することが出来ます。
ApplescriptでリモートからFoltiaサーバーを監視する際に問題となるのはこのSSHをいかに簡単に単純に誤動作無く行うかという点にあります。 パスワードを対話形式で反応するのは遅くなりますし、プログラム上にパスワードを平文で記載しておかなくてはならなくなりセキュリティー的な問題も発生します。 なのでここはRSA認証でパスワード認証無しで Single Lineで Shellコマンドを実行出来る様にしておきましょう。
末尾にTerminalを使って対話式に実行するアップルスクリプトのサンプルを添付しておきます。 これはこれでなかなかに良いもんです。
SSHでのFoltiaサーバーへの接続
皆さんお気づきだと思うのですが。 ssh foltia@foltia.local といったかんじでサーバーにアクセス使用とするとRSAキーを要求されます。
Unable to negotiate with 192.168.1.5 port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
とかそんな感じで帰って来ます。
これは以下の様に記載するととりあえずはssh接続が出来ます。
ssh foltia@foltia.local -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedKeyTypes=+ssh-rsa
ですがコマンドが長くなりすぎますし、この後実行するid_rsa.pub のサーバへのコピーの時に結構面倒になるので
~/.ssh/configを記載して複雑な接続手順を一括で保管しておくことが有効です。
.ssh/configをつかったrsa認証によるパスワード無し接続の設定
この方のリンクが参考になりました。
でも先ず御託は面倒なので実践して見ましょう。
1) local$ ssh-keygen
RSAキーを作成します。 いろいろ聞かれるけど、すべてエンターで対応する。 id_rsa.pubというファイルが出来ている。 この際 ~/.ssh/フォルダが作成されています。
2) local$ touch ~/.ssh/config
これでconfigファイルの空ファイルが出来ます。 その後
i ☆で記入開始できます。☆
Host foltia.local
Hostname foltia.local
User foltia
AddressFamily inet
HostKeyAlgorithms ssh-rsa
PubkeyAcceptedKeyTypes +ssh-rsa☆escapeして :qwで記入完了
3) local$ scp ~/.ssh/id_rsa.pub foltia@foltia.local:
これで公開キーをサーバーにコピー出来る。 最後のコロンが大事
4) リモートホストにログインし、authorized_keys ファイルを生成
local$ ssh foltia@foltia.local
remort$ mkdir .ssh
#あれば不要
remort$ chmod 700 .ssh
#これが違うと動かなかった。 実行フォルダなんだな
remort$ cd .ssh/
remort$ touch authorized_keys
#無ければ作っておく
remort$ chmod 600 authorized_keys
remort$ cat ~/id_rsa.pub >> authorized_keys
remort$ rm ~/id_rsa.pub
#最後にコピーしたキーを削除、後から別のマシーンから設定したりすることもあるので。
これで接続出来る様になっているはず
5) remort$ sudo vim /etc/ssh/sshd_configで設定の変更
これ自分でもどこを変えたかあまり覚えてないんですが、おそらく赤が必須かな?
14行目: #AddressFamily any → AddressFamily inet これはIPv4指定
43行目: PermitRootLogin no → PermitRootLogin yes これは後でnoに戻しておきますが、とりあえずrootでのログインの設定を完了するまでyesにしておきます。
67行目: 全て設定が終わった後に PasswordAuthentication yes → PasswordAuthentication no にします。
71行目: ChallengeResponseAuthentication no → ChallengeResponseAuthentication yes にしてますがなぜしたかよく覚えてないです。 不要かも・・。
82行目: GSSAPIAuthentication yes → GSSAPIAuthentication no これもよく覚えてないです・・。 不要かも
98行目: UsePAM yes → UsePAM no これも不要な気がする。
123行目: UseDNS yes → UseDNS no これはDNSサーバをローカルに作っていないと接続が遅くなるので noにしといた方が早いです。
126行目: #Match User anoncvs 以降末尾に追記
Match Address 192.168.0.xxx ☆ 監視サーバーのアドレスをセット
PermitRootLogin yes
PasswordAuthentication no
:wqでセーブして。
remote$ sudo /etc/init.d/sshd reload で設定をリロードできます。
6) sshd_configの設定を変更してからrootでも同様にアクセス出来る様に
shutdown -r nowとか service pcscd restart とかのsuperuser権限のコマンドを使うのに利用します。 sudoerファイルにコマンドを登録しても良いのかもしれません。
rootでアクセス出来る様にしておいたら、sshd_config 43行目はno に戻しておいた方が安全ですね。
7) remort$ sudo vim /etc/hosts.deny また remort$ sudo vim /etc/hosts.allow
結構な頻度で外部からハッキング(パスワード)チャレンジがあるんで、制限かけた方が良いです。
hosts.allowに
sshd: 192.168.1. 自分のローカルIP-range
ssh接続はさすがに制限かけといた方が良いでしょう。
hosts.deny
sshd: all
私の感想
実際このパスワード認証無しでのSSH接続がCentOSに対して上手く出来なくて悩んだ時間が1ヶ月ぐらいありましたわ・・。 このパスワード認証なしでSSH接続が出来るようになる所がこのスクリプト全体の半分ぐらいの労力を使った気がします。
また理由がわからなくていろいろsshd_configをいじって接続を試していたので、どれが必要な変更かよくわからなくなってしまったのです。
対話式のApplescriptでのTerminalのコントロール
最後にターミナルで対話型でssh 接続してコマンドを実行するハンドラーをちと紹介です。 まあ凄いガバガバなアップルスクリプトなので、必要に応じて修正してみてください。
set pswd to "******"
set q to {FailSafe:true, ActionList:{"", "@*~ %", "ssh foltia@foltia.local", "assword:", pswd, "@*~]\\$", "sudo ls", "パスワード:", pswd, "@*~]\\$", "exit", "~ %"}, closeWindow:true}
set q to term(q) of me
return q
on term(q) --termは基本的に返値なし
set q to {error_:""} & q & {tab_:"", ActionList:{}, wSec:10, ti:0.1, FailSafe:true, WaitBusy:false, closeWindow:true}
--FailSafeはfalseならチェックなし所定時間経過したら進む。
--Prompt1, Action1, Prompt2, Action2 の順番で処理し、空白が出現した段階で停止する。
--"$Here"ならproHere, "$There"ならProThereを入れる
set ProHere to "@*~"
set ProThere to "@*~"
if (do shell script "Echo " & (system info)'s system version & "|sed -e 's/\\(^[0-9]*.[0-9]*\\)[^0-9].*/\\1/g'") ≤ 10.13 then set ProHere to "~*\\$"
set max to round ( (length of q's ActionList) / 2)
--偶数個ないと最後は実行されない。
--tell application "Terminal" to close every window
repeat with i from 1 to max
if q's tab_ is "" then
tell application "Terminal" to set q's tab_ to do script item (i * 2 - 1) of q's ActionList
else
tell application "Terminal" to do script (item (i * 2 - 1) of q's ActionList) in q's tab_
end if
delay q's ti
set wPrompt to item (i * 2) of q's ActionList
if wPrompt is "$Here" or wPrompt is "$local" or wPrompt is "$client" then set wPrompt to ProHere
if wPrompt is "$There" or wPrompt is "$remote" or wPrompt is "$server" then set wPrompt to ProThere
set q to WaitPrompt({tab_:q's tab_, wPrompt:wPrompt} & q) of me & q
if q's FailSafe then return {error_:"ActionList:" & item (i * 2) of q's ActionList & "が返却されない"} & q
end repeat
if q's closeWindow then tell application "Terminal" to close window 1
return q
end term
--パスワードプロンプトはBusy待機中にBusyになる
--return WaitPrompt({wPrompt:"@iMac-17 ~ %"})
on WaitPrompt(q)
set q to q & {tab_:"", wSec:10, FailSafe:true, wPrompt:"", ti:0.1, SerchFullText:false, WaitBusy:true, LastLine:""}
if q's tab_ is "" then tell application "Terminal" to set q's tab_ to tab 1 of window 1
if q's wPrompt is "" then
delay q's ti
return {FailSafe:false} & q
end if
tell application "Terminal" to tell q's tab_
if q's WaitBusy then
repeat while busy is true
delay q's ti
end repeat
end if
if q's wPrompt is "" then return q
set a to ""
repeat q's wSec times
set history_ to history as string
set Len to 1
try
set Len to (length of history_) - 1000
end try
if Len < 1 then set Len to 1
set history_ to text Len thru end of history_
if q's SerchFullText then
set a to do shell script "echo " & quoted form of (history as string) & "|grep -v '^$'|tr -d '^\\r'|tr \\\\r \\\\n|grep '" & q's wPrompt & "'||true"
else
try
set a to do shell script "echo " & quoted form of (history_) & "|grep -v '^$'|tr -d '^\\r'|tr \\\\r \\\\n|tail -n 2|grep -B 1 '" & q's wPrompt & "'||true"
end try
end if
if a is not "" then
set q's FailSafe to false
exit repeat
end if
delay 1
end repeat
end tell
return {LastLine:a} & q
end WaitPrompt
以下参考として
MacにUnix環境を入れておきましょう私はMacPorts使ってます
きっとググるといっぱい出てきますが、適当にトップに出た物を上げときます。
Homebrewでもよいです。自分の好きな環境を入れておきましょう。 ただ今回のアップルスクリプトではもしかしたら使ってないかもな〜。 もういろいろと入っててデフォルトの状態が思い出せないんですよ。
MacOS上でコマンドファインダー上でCommand+Shift+ピリオド
不可視ファイルを見やすくしておく事ができますが、全部vimやviで操作するので、必要無い方はしなくてよいでしょうね。
番外) 相手がMac-OS ventura以降だとRSAではダメだった 25519を使う
今回出番はありませんが、接続相手が新しいOSだとRSAでの接続を許可していない場合も有ります。 その場合はもう少し新しいキーシステムを試す必要がありそうです。 参考までに。
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
パス設定せず。 あとは上記の
~/.ssh/config
に IdentityFile ~/.ssh/id_ed25519 を指定
さらにコピーするファイル scp ~/.ssh/id_ed25519.pub foltia@foltia.local:
としますし、
#cat ~/id_ed25519.pub >> authorized_keys remort$ rm ~/id_ed25519.pub とする必要があります。