ShellScript
SSH
OpenSSH

最強のSSH踏み台設定

More than 1 year has passed since last update.

Ansibleでホスト毎に踏み台サーバを切り替える設定を探したりして色々悩んでたら、最強のSSH設定を編み出してしまったww

最強のSSH踏み台設定

~/.ssh/config
# 最強のSSH踏み台設定 http://bit.ly/1MD3d24
Host */*
  ProxyCommand ssh -W "$(basename "%h")":%p "$(dirname "%h")"
Host *+*
  ProxyCommand ssh -W "$(sed -E 's/.*\+//'<<<"%h")":%p "$(sed -E 's/\+[^\+]*//'<<<"%h")"

/ 区切りだとrsyncとかで都合悪い時があるので + 区切りも出来るようにしておく事にした。というかむしろ最近 + しか使ってないから / 区切り消そうかなと思ってる。

使用例

上記設定を1個書いておくだけでこんなふうに接続できます。

ssh bastion.example.jp+internal.example.jp

多段もOK

いい感じに再帰しながらマッチしてくれるので多段SSHも出来ます。

ssh bastion.example.jp+internal.example.jp+super-deep.example.jp

これは外から見ると↓こんなプロセスツリーになってます。

\_ ssh bastion.example.jp+internal.example.jp+super-deep.example.jp
    \_ ssh -W super-deep.example.jp:22 bastion.example.com+internal.example.jp
        \_ ssh -W internal.example.jp:22 bastion.example.com

各段階の接続ユーザ名やポートが異なる場合も、そこだけ切り出した設定をたとえばこんな風に書いておけばOK

# 個別設定は先に書く
Host bastion.example.jp
  Port 10022
Host bastion.example.jp+internal.example.jp
  User internaluser
Host bastion.example.jp+internal.example.jp+super-deep.example.jp
  User deepuser

# 最強のSSH踏み台設定は最後に書く
Host */*
  ProxyCommand ssh -W "$(basename "%h")":%p "$(dirname "%h")"
Host *+*
  ProxyCommand ssh -W "$(sed -E 's/.*\+//'<<<"%h")":%p "$(sed -E 's/\+[^\+]*//'<<<"%h")"

あ、別に個別設定の中にProxyCommandがない限りはどっちが先でも問題ないのか。まぁ共通系は下に書くのを基本にしとくのがベターってことで。

多段経路で rsync も実行したい

rsyncでホスト名部分に/を入れると引数のパースがうまく出来なくて駄目だけど、↓こんな風に/が無いエイリアスなホスト名を設定しておけば…

~/.ssh/config
Host super-deep
  HostName bastion.example.jp/internal.example.jp/super-deep.example.jp

実行できます!

rsync -a src/ super-deep:/path/to/remote/

もしくは追加設定などせずとも、↓こんな風に実行してやれば多段rsyncも余裕です。

rsync -a -e "ssh -o 'HostName bastion.example.jp/internal.example.jp/super-deep.example.jp'" src/ dummy:/path/to/remote/

この場合、dummy ていうホスト名はsshの追加オプションのHostNameで上書きされるからこの値は意味を持ちません。

多段経路で rsync その2

上に書いたrsyncのやり方は簡単とはいえ、折角最強設定使ったのにあまりスマートじゃないので改善したい…。
で、ホスト名のセパレータが/じゃなきゃ良いんじゃね?ってことで、+でも繋げられるようにしてみたのがこの設定。

~/.ssh/config
Host *+*
  ProxyCommand ssh -W "$(sed -E 's/.*\+//'<<<"%h")":%p "$(sed -E 's/\+[^\+]*//'<<<"%h")"

これだと何の工夫も無しにrsyncが出来る!

rsync -a src/ bastion.example.jp+internal.example.jp+super-deep.example.jp:/path/to/remote/

どっちの文字で区切るのが良いかは用途別または趣味の問題かもなー。ていうか両方設定しといても害はないだろうから両方書いておけば良いのか。

ControlPath は %C でキマリ!

今回作ったSSH踏み台設定はに実はこれを使うとホスト名がどんどん長くなってそれによりControlPathの設定がどうあがいても使い物にならなくなるという問題があった。だけどそれはOpenSSH6.7以降ならControlPathの設定で%Cを使うようにすれば解決するよって話。

詳しくはこの記事の以下コメントに書いたのでControlPathで困ってる人は見ておくと多分ご利益あります。
http://qiita.com/kawaz/items/a0151d3aa2b6f9c4b3b8#comment-8932a2c6a4d83d519bd8