rcmdnk's blog
Last update

MOSH (MOBILE SHELL): A New Era of Remote Access

ちょっと前(1,2年前?)に話題になってた気がする sshのラッパープログラムのMosh (the mobile shell) を試してみました。

Sponsored Links

Mosh

Moshは特にMobile端末からsshでどこかのサーバーへ接続して ネットワークがとぎれとぎれ担ってしまうような場合にも 接続を維持できる様に(自動で再接続)してくれるプログラムです。

接続認証にはsshを使いますが、サーバー側、クライアント側両側で プログラムを動かして別のポートを使って接続を行い、維持するようにします。

これらのプログラムはmoshコマンド実行時に自動的にスタートするので、 サーバー側でも先に動かしておく必要はありません。

事前準備としては、サーバー側、クライアント側両方にmoshをインストールし、 moshが使えるポートを開けておくことです。

インストール

Mac

Homebrew でインストールできます。

ただし、パッケージ名がmoshではなくmobile-shellです。

$ brew install mobile-shell

Windows (Cygwin)

Windowsで使いたい場合はCygwinにインストールして使います。

$ apt-cyg install mosh

追記: 2015/08/10

もしくはMobaXtermを導入すれば最初からMoshが入っています。

MobaXterm: Windowsでのcygwinに代わるターミナル環境

追記ここまで

Linux

root権限を持っていて apt-getで管理している様な場合はDebianでは

$ sudo apt-get install mosh

だけでOK。Ubuntuだと

$ sudo apt-get install python-software-properties
$ sudo add-apt-repository ppa:keithw/mosh
$ sudo apt-get update
$ sudo apt-get install mosh

の様にレポジトリを追加してのインストールになります。 公式ページにあるように、その他のシステムでも広くサポートされてます。

以下では 今回やったLinuxで管理者権限を持っていなくてユーザーローカルにインストールした場合について。

今回必要だったものはpkg-configprotobufOpenSSLncurses です。

いくつかの場所にインストールしましたが、protobufは全てに入ってませんでしたが、 Opensslはもちろんシステムの/usrに通常のが入っていますがdevelバージョンが必要で 別途ローカルにインストールしました。

ncursesはローカルにインストールしてあるところもありましたが、 下に書くようにfPICオプション付きでコンパイルし直す必要がありました。

Linuxでのローカル初期設定 に書いたように、~/usr/local/下にstowを使ってインストールします。

pkg-config

moshのconfigureで

checking for pkg-config... no

となって確かに入ってないサーバーだったのでインストール。

$ v=pkg-config-0.28
$ wget http://pkgconfig.freedesktop.org/releases/${v}.tar.gz
$ tar xzf ${v}.tar.gz
$ cd $v
$ ./configure --with-internal-glib --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v

最初、configureの所で--with-internal-glibを付けなかったら

...
checking for pkg-config... no
checking for GLIB... no
configure: error: Either a previously installed pkg-config or "glib-2.0 >= 2.16" could not be found. Please set GLIB_CFLAGS and GLIB_LIBS to the correct values or pass --with-internal-glib to configure to use the bundled copy.

と言われてしまって、glibをインストールしようかと思ったら glibのインストールにpkg-configが必要だったりわけがわからなくなりましたが、 上のオプションを試してみたらうまくいきました。

protobuf

protobufが無いと、moshでconfigureするときに

configure: error: cannot find protoc, the Protocol Buffers compiler

と言われます。これを言われたらprotobufをインストール。

$ cd ~/tmp
$ v=protobuf-2.5.0
$ wget https://protobuf.googlecode.com/files/${v}.tar.gz
$ tar xzf ${v}.tar.gz
$ cd ${v}
$ ./configure --prefix=$HOME/usr/local/stow/${v}
$ make
$ make check
$ make install
$ cd ~/usr/local/stow && stow $v

な感じ。一部のシステムで(Debian)、make checkの時に 5つあるテストのうち1つがエラーを吐きましたが、 コンパイルやその後のmoshのコンパイルでも問題なかったのでそのままにしてあります。

OpenSSL

OpenSSLのdevel(libssl.so等)がないと moshのcongigure時に、

checking for OPENSSL... no
configure: error: Package requirements (openssl) were not met:

No package 'openssl' found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables OPENSSL_CFLAGS
and OPENSSL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

こんな感じで怒られます。もし、すでに/usr/lib等にあるのに怒られる場合は、 上にあるようにPKG_CONFIG_PATHの指定が必要です(下のmoshのインストールの部分参照)。

$ cd ~/tmp
$ v=openssl-1.0.1h
$ wget ftp://sunsite.cnlab-switch.ch/mirror/openssl/source/${v}.tar.gz
$ targz ${v}.tar.gz
$ cd ${v}
$ ./config --shared -fPIC --prefix=$HOME/usr/local/stow/${v}
$ make
$ make install
$ cd ~/usr/local/stow && stow $v

--sharedを忘れずに。また、-fPICをつけろ、というエラー 1 が出るような場合は 上の様に-fPICをつけるのが必須です。

Ncurses

moshのmake時(configureは通った)に、

CXXLD  mosh-client
/usr/bin/ld: $HOME/usr/local/lib/libncurses.a(lib_setup.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
$HOME/usr/local/lib/libncurses.a: could not read symbols: Bad value
collect2: ld returned 1 exit status

こんな感じのエラーが。 そもそも、ncursesの共有ライブラリが無いので、作るために --with-shared付きでconfigureし直し再インストール。

$ cd ~/tmp
$ v=ncurses-5.9
$ wget http://ftp.gnu.org/pub/gnu/ncurses/${v}.tar.gz
$ tar xzf $v
$ cd $v
$ ./configure --with-shared --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v

mosh

準備が整ったのでmoshを。 ソースはGitHubにあるのでそちらから取ってきます。

$ cd ~/tmp
$ git clone https://github.com/keithw/mosh

または

$ v=mosh-1.2.5
$ wget http://mosh.mit.edu/${v}.tar.gz

と言った感じにアーカイブも用意されています。

とりあえずGitHub版を取ってきたとして

$ cd mosh
$ v=mosh-$(grep released ChangeLog|head -n1|awk '{print $3}')
$ ./autogen.sh
$ CXXFLAGS="-I$HOME/usr/local/include" CFLAGS="-I$HOME/usr/local/include" LDFLAGS="-L$HOME/usr/local/lib" PKG_CONFIG_PATH=$HOME/usr/local/lib/pkgconfig ./configure --prefix=$HOME/usr/local/stow/$v
$ make && make install
$ cd ~/usr/local/stow && stow $v

でOK。 configureの所で幾つか環境変数を設定して渡す必要があります。

上に書いたようにPKG_CONFIG_PATHへは*.pcファイルがあるディレクトリ (通常.../lib/下)を渡します。 上でインストールしたopensslなどの情報が入ったファイルが $HOME/usr/local/libopenssl.pc等という名前などで入っているので、 ここへのパスを書きます 2

CXXFLAGS、CFLAGS、LDFLAGSは渡しておかないとmake時に見てくれないので渡す必要があります。 ここで、CFLAGSの方だけ設定しておくと、configure時には

...
checking for curses.h... no
checking for NcursesW wide-character library... no
checking for Ncurses library... yes
checking for working ncurses/curses.h... yes
checking for working ncurses.h... no
checking whether forkpty is declared... no
checking for forkpty in -lutil... yes
...

こんな感じでOKが出ますが、makeすると

$ make
...
make[3]: Entering directory `$HOME/tmp/mosh/src/terminal'
  CXX    terminaldisplayinit.o
  terminaldisplayinit.cc:48:30: fatal error: ncurses/curses.h: No such file or directory
  compilation terminated.

といった感じでCXX時にncurses/curses.hが見つかりませんので、 きちんとCXXFLAGSにも渡して上げる必要があります。

Android

AndroidではJuiceSSH がmoshを公式にサポートしてくれる様になり、クライアントとして使えます。

基本無料で、有料でCloudで設定をシェアしたり出来たりするようになりますが、 基本的な機能は無料で十分使えます。

インストールしたら、Typeでmoshを選び、

juicessh_type

ポートの変更等がある場合はCommandの部分に必要なMoshに 与えるオプションを書き加えてあげます。

juicessh_command

後は普通にsshするのと同じ様にしてあげればmoshでの接続になり、 例えば電車などですごく不安定な所でつなげても つながるたびに復活してくれます (だからといって流石に電車なんかでそれで普通に使えるほどではないですが。。。)

iPhone

iPhoneは公式にも載ってませんが、 iSSH というアプリが対応しているっぽいです(試してない)。

使い方

まず、moshはデフォルトで60000~61000番のいずれかのポートを使います。 sshでつないでサーバー側でmosh-serverを起動した後、 ポートを1つ指定し、そのポート経由でローカルで起動するmosh-client からつなげる様な作業を行います。

ですので、もし、これらのポートがファイアウォール等で外から使えない時は ルート権限があるなら/sbin/iptablesなどを使って(自己責任で)開けて置く必要があります。

serverというホストにmoshを使ってログインしたい時は単に

$ mosh server

とすればOK。~/.ssh/configにある設定に従ってホスト名の解釈やユーザー名の設定も 行ってくれます。

ユーザー名を直接

$ mosh [email protected]

と通常のsshみたくしてもOK。

または、適当に使えるポートが有るなら、ポート指定も出来ます。

$ mosh -p 5050 server

-pで指定すればOK。 ポートを指定しないと60000~61000番の空いてるポートどれか(普通は数が小さい方から) を使って行って、新たなセッションを作ると別のポートを使いますが、 ポート指定すればそのポートだけが使われるのでより安全にしたい場合もそちらで。

一方、sshのポート番号が22以外の場合には

$ mosh --ssh="ssh -p 1022" [email protected]

の様に、--sshオプションにsshコマンドに加えて与える オプションをまとめて指定することができます。

上手くいけば

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
[server ~]$

こんな感じのメッセージとともにログイン出来るはずです。 恐らくmoshを起動する際にターミナルへ\e]0;~\aの エスケープシーケンスを送っているのか 3 iTermではタイトルバーを見ると本来のタイトルの左に[mosh]という文字が追加されていました。

起動後は通常のsshと同様に作業してexit等でログアウトするとmoshのプロセスも終了します。

もし、moshのプロセスを中断したいような場合には Ctrl-^ Ctrl-zを押せば中断出来ます。

エラー等

指定したポート(もしくは指定しない場合に向こうで勝手に指定する60000番など) が外から使えないものだと

mosh: Nothing received from server on UDP port 60001. [To quit: Ctrl-^ .]

な感じのメッセージが青いバックグラウンドで表れ

mosh: Last reply 19 seconds ago. [To quit: Ctrl-^ .]

こんな感じでつながらないよ、とカウントをしていきます。 暫くそのままつながらないで放置しておくか、書いてある通り Ctrl-^ .を押せば

mosh did not make a successful connection to 1xx.1xx.2xx.xx:60001.
Please verify that UDP port 60001 is not firewalled and can reach the server.

(By default, mosh uses a UDP port between 60000 and 61000. The -p option
selects a specific UDP port number.)

[mosh is exiting.]

その後、こんな感じで終了します。

もし、ポートが既にたのセッションで使われてると、

mmbp ~]$ dcnode
Failed binding to 1xx.1xx.2xx.xx:5050
Error binding to IP 1xx.1xx.2xx.xx: bind: Address already in use
Failed binding to 0.0.0.0:5050
Error binding to any interface: bind: Address already in use
Network exception: bind: Address already in use
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.
[mmbp ~]$ ssh dcnode

の様なメッセージになります。 もし、そのようなセッションが無いのにこういったメッセージが出る場合は、 サーバー側でmosh-serverが生き残ってしまっている場合があるので、 直接sshするなりしてプロセスをkillして来る必要があります。

また、いくつか試した中で、通常は~/usr/localにおいてあるものを正しく 見てくれるのですが、中に

$ mosh server
bash: mosh-server: command not found
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.

といったふうに、mosh-serverコマンドを見つけられない所がありました。 .bashrc等は等しく同じもので~/usr/下も同じ構造なんですが、なぜだかよく分かりませんが、 とりあえず、moshには--serverと言うオプションでmosh-serverの位置を 教えられるので

$ mosh --server="~/usr/local/bin/mosh-server" server
$HOME/usr/local/bin/mosh-server: error while loading shared libraries: libprotobuf.so.8: cannot open shared object file: No such file or directory
Connection to server closed.
/usr/local/bin/mosh: Did not find mosh server startup message.
$

と、今度はLD_LIBRARY_PATHも設定がうまく行ってない模様。 仕方ないので、

$ mosh --server="LD_LIBRARY_PATH=~/usr/local/lib:$LD_LIBRARY_PATH ~/usr/local/bin/mosh-server" server

と、LD_LIBRARY_PATHまで指定してあげると動きました。

使ってみての感想

まず、普通につなげてみて、ネットワークを切ったりすると、 sshではもちろん

[server ~] $ Write failed: Broken pipe
[local ~] $

みたいな感じでセッションが切れます。

これがmoshだと、一番上に青いバックグラウンドとともに

mosh: sendto: Network is unreachable (15 s without contact.) [To quit: Ctrl-^ .]

と言ったメッセージが出ます。 この状態でもう一度ネットワークが繋がると、きちんと元に戻りました! ちょっと嬉しい。

普段、リモートで作業するときは必ずscreen を立ち上げるので、切れても作業状態へ復帰は出来るのですが、 ワイヤレス等で接続が悪いと、切れるたびに再接続させないといけないので 結構面倒です。 その煩わしさがちょっと減るので嬉しいかも。 ただ、ネットワークが繋がってから再び動き出すまでに少し時間がかかり過ぎな 感じもしました。(といっても数秒から数十秒程度ですが)

また、moshの一つの特徴であるinstant echo(local echo)は、 コマンドを打ち込むときにサーバー側がレスポンスする前にも ローカル側で表示だけしてしまう(サーバー側に送られてない部分は下線が表示される)、 というものですが、 これは確かにターミナルでコマンドを入力するには少し快適に感じるかな、と言った感じ。

実際にVimでの編集などはやはり変更が行われないと変更されないし、 書いた文字を消したりしたい場合には実際に待たないと行けなかったりするので、 あったらいいな、程度。 でもちょっと面白いです。

1つ注意としては、screenなどのセッションを立ち上げた中から moshを使って何処かへつなぐと、そのアウトプットが崩れるので、 スクロールバックした時などに本来の出力が見れなくなります4

通常の使い方ではサーバー側にmoshでつないで、サーバー側でscreenを立ち上げる、 というのが多いのであまり問題にならないと思いますが、 screenの中から他につなげる事があってスクロールバックを良く使う人は moshを使わず直接sshした方が良さそうです。

その他現状の問題点等

Xが飛ばせない

まず第一に問題なのがXフォワードに対応してないことです。 まあ、とぎれとぎれになるのにきちんと対応させる事は結構難しそうですが、 moshでのセッションは最初からXが飛ばせません。 なので、Xを飛ばす作業には使えません。

ProxyCommandが使えない

Moshの中でPorxyCommandを使っているようなもの?なので、 ~/.ssh/configに書かれている設定のうち ProxyCommandの部分は無視されます。

なので、ちょっと前に多段ssh設定のまとめ で書いたようなログインサーバーを乗り越えて外から見えないサーバーへ moshでログイン、みたいなことは出来ません。

現状、一番簡単な解としては、ローカルからの直截 多段接続は諦めて、 moshでローカルとログインサーバーをつなぎ、 ログインサーバーから目的の隠れたサーバーまでは普通に sshで入る方法(上のポストのPuTTYの件の様な)。

$ mosh login.server ssh work.server

的な感じで、moshで接続した後に目的のサーバー(work.server)まで sshします。

通常、このようなログインサーバーと目的のサーバーは しっかりつながっていて途切れることなんて無いので、 実務上はこれで殆ど問題無いと思います。

鍵認証の場合には目的のサーバー用の秘密鍵を ログインサーバーが持ってないといけないことと、 ログインサーバーにmoshをインストールしないといけない、という点 さえ大丈夫ならこれで。

ssh - mosh tunnel via proxy - Server Fault

Can’t use a ProxyCommand-based SSH connection

それから、上の下の方の議論の中で出てくるmosh_pc.sh というスクリプトが、目的はおいておいても、 サーバー側でmosh-server、クライアント側でmosh-client をmoshを使わずに別々に起動しているのですが、 moshがそれらをどのように使っているのかが理解でるので 一度見ておくとなんとなくmoshがやってることをわかった気になれます。

Sponsored Links
  1. -fPICをつけないとこんな感じのエラーが出ました。

    ...
    /usr/bin/ld: libcrypto.a(e_4758cca.o): relocation R_X86_64_32 against `.data' can not be used when making a shared object; recompile with -fPIC
    libcrypto.a(e_4758cca.o): could not read symbols: Bad value
    collect2: ld returned 1 exit status
    make[4]: *** [link_a.gnu] Error 1
    make[4]: Leaving directory `$HOME/tmp/openssl-1.0.1h'
    make[3]: *** [do_linux-shared] Error 2
    make[3]: Leaving directory `$HOME/tmp/openssl-1.0.1h'
    make[2]: *** [libcrypto.so.1.0.0] Error 2
    make[2]: Leaving directory `$HOME/tmp/openssl-1.0.1h'
    make[1]: *** [shared] Error 2
    make[1]: Leaving directory `$HOME/tmp/openssl-1.0.1h/crypto'
    make: *** [build_crypto] Error 1
    $
    

  2. これを忘れるとconfigure時に

    checking for OPENSSL... no
    configure: error: Package requirements (openssl) were not met:
    
    No package 'openssl' found
    
    Consider adjusting the PKG_CONFIG_PATH environment variable if you
    installed software in a non-standard prefix.
    
    Alternatively, you may set the environment variables OPENSSL_CFLAGS
    and OPENSSL_LIBS to avoid the need to call pkg-config.
    See the pkg-config man page for more details.
    

    こんな感じのエラーが出ます。

  3. PS1とPROMPT_COMMAND, GNU screenでの活用も

  4. Scrollback and alternate screen (was: Use alternate screen on smcup/rmcup ) · Issue #2 · keithw/mosh

    殆ど読んでないですが、mosh単体でのscrollbackについては 今後1.3のリリースでは完璧になるとのこと。(HPのFAQにあり)

    screen/tmuxのサポートについてはざっと読んだ限りではよくわからないですね。。。

Sponsored Links

« シェルスクリプトでの配列のソート#Bash MacでPowerPointをHyperlinkを保持したままPDFにしたい »