mosh: MITからモバイル時代のSSH代替品という記事を読んでmoshというモノの存在を知りました。で、USENIXに採録予定の論文があるというのでそれも読んでみました。
moshでは、作者が独自に設計したSSP (State Synchronization Protocol)というトランスポート層の独自プロトコルを使っています。SSPというのは大雑把に言うと、下層にUDPを想定して、状態を送り合うというプロトコルのようです。
ターミナルのようなアプリケーションの場合、クライアントにせよサーバにせよ知りたいのは最新の状態であってそれ以外はドロップしてしまっても問題はない。そこで、UDPの1データグラムに収まる範囲で状態を送り合うということを想定しています。コネクションを張らないことで、クライアント側は途中でいきなりIPアドレスが変わっても問題が起きない、というのが「モバイル時代の」という触れ込みの所以です。
暗号化と認証についてはSSHに乗っかるようです。まずクライアントはサーバにSSHで接続します。するとサーバ側ではふつうにユーザプログラムとしてmoshサーバが起動し、ランダムな暗号鍵を生成してクライアントに送ります。クライアントがこれを受け取ったらSSHのコネクションは切断しても大丈夫で、あとは各パケットをこの共通の暗号鍵で暗号化します(nonceも使うので、リプレイ攻撃の問題はありません)。
moshのもうひとつの特徴がlocal echoです。ふつうのリモートシェルではキー入力はサーバに送られ、サーバからエコーバックが返されて初めて表示されるわけなのでどうしても遅延が発生します。moshではローカルの側で一時的にエコーを表示しておいて、予測通りだったらそのまま確定させる、といったことをします。このため入力のフィードバックがすぐ得られるという利点があります。
もっともこれは大きな問題もあって、sudoしたりとかvi使ったりとかすると余計な文字が出てきてしまう。そこで状態を予測してlocal echoしたいときだけする、みたいなことが書いてあります。しかし論文には出しちゃいけない状態だということがわかったらすみやかに消す、みたいなことしか書いてない気も……。コードを見ても、たんにRTTとかをみて充分に高速だったら表示しないだけな気も。あまり良くわかりません。sudoのパスワードは見えそうな気がしますが……。
なんとなく直感的には、状態をlocal echoあり、なし、不定の3状態にしておいてありのときだけlocal echoする、改行等で状態を不定に戻す、不定からはサーバのエコーバックを見てありに遷移、といった単純なものでも充分マシな気もしますが、毎回微妙な遅延があるのが嫌だったんでしょうか。
この論文はしかし、以上に書かれていない、全体の4分の1ほどの内容がなかなか味わい深いのです。moshというのはようするに仮想端末の再実装なので、仮想端末のめんどくさいところにいろいろ遭遇してしまった、そういう苦労話みたいな話があるのですね。たとえば、
- ISO-2022は状態があるのに、状態を戻さない壊れたファイルをcatしたりすると端末が文字化けして回復できなくなるんだぜ!
- UTF-8も表示できるようにしたぜ! ところでECMA-48にはそういう話は記載がないのだが(略)
- CJK文字って倍幅なんだよな! しかも行末に半分だけ余白がある場合は(略)
- ローカルとサーバでlocaleが違うばあいに(略)
- そもそもどうやってlocaleを指定するかというと(略)
……などなど。
論文本体よりは個人的にはこの辺の苦労話が味わい深く感じられる論文でした。そういうところはあんまりまっとうな論文という気はしないけど(USENIXにはありそうだけど)、片手間に読む分にはなかなか面白いのでみなさんもぜひ読んでみてください。