ProxyCommand

自分の作业环境の作り直しをしているのですが、
たまに理解が怪しくなるので、确认ついでにここに吐き出しておこうと思います。

背景

リモート环境にあるホストAにsshあるいはscpするためには、
 踏み台(Bastion)となるホストXに一度SSHログインしないとならない

というケース/环境はそこそこ多いと思います。

これがsshなのであればまあ、ssh X -> ssh Aとするだけなのでそこまででもありませんが、
scpだった场合は概ねこんな手顺になりますよね。

  1. まずssh XとしてホストXにログイン
  2. ホストX上でscp -p A:/path/to/datafile ~/(オプションはお好み)
  3. コピーが终わるのを待ってから、Xからログアウト
  4. scp -p X:~/datafile .
  5. コピーが终わるのを待ってssh X rm ~/datafile

これで何が困るかというと、

  • コピー(scp)が2回必要なので、时间が余计にかかる
  • 1回目のコピーが终わったことに気づかず、あるいは终电 业务时间が终了するなどして、さらに时间がかかる
  • ホストXの空き容量がたりないときがある
    • 分割したり、X以外に使えそうなホストを探し回ったり作ったりと余计な时间やコストがかかる
  • ホストX上の一时ファイルを消し忘れる ←
    • むしろ「もしもの时のためにとっておこう、用が済んだらあとで消そう」などと积极的に残してしまう
    • そして忘れる1
    • 结果ホストXのディスクが一杯になって他の利用者や管理者に怒られる

こうなるからです。2

これは手动のときだけの话ではなく、
定期的にscpを実行させたいときや、スクリプトやバッチ処理时にsshでコマンド実行しないとならないときにも问题になります。

本来ならば、データ受け渡しのための仕组みをちゃんと用意すべきところではありますが、逆に(様々な事情で)恒常的な仕组みを设けられない场合もありますし、一时的なメンテナンスや调查等でしか必要にならない场合、「そこまでしなくても…」と思ってしまうのも人情というものではないでしょうか。

ProxyCommandに-Wオプションという救世主

定番中の定番という话ではあるのですが、
ProxyCommandを使えば、ワンライナで実行できます。

1
$ ssh -oProxyCommand='ssh -W %h:%p X' A
1
$ scp -p -oProxyCommand='ssh -W %h:%p X' A:/path/to/datafile .

ProxyCommand中の%h %pが、
本来の接続先である A とそのポート(无指定だとデフォルトの 22)に置换される、という动作になります。

実例としてはこんな感じになるかと。

1
$ ssh -oProxyCommand='ssh -W %h:%p [email protected]' [email protected]
  • Host X ... ec2-13-112-xxx-xxx.ap-northeast-1.compute.amazonaws.com
  • Host A ... ip-172-31-xxx-xxx.ap-northeast-1.compute.internal

键指定(-i)やポート番号の指定(-P9022-oPort=9022等)といったオプションも、
勿论上记コマンドラインの中に含めることが可能です。

その际は、
ホストXに対するオプションをProxyCommand内に、
ホストAに関するものを外侧(-oProxyCommandと同列)に记述してください。

なお、実际にAにアクセスするのはXなので、
コマンドを実行するホストがAのホスト名を名前解决できなくても构いませんし、
勿论ホスト名ではなく、IPアドレスで书いても构いません。

むしろ注意すべきなのは、ワンライナで书こうともAに接続するのはあくまでXなので、
Xが名前解决・接続できるようにAを指定(ホスト名、IPアドレス)する必要があるというところです。

要は普段Xで実行している内容そのままを记述すればいいのですが、
一方でSSHとしてAにログインする、つまりホストAと键の交换を行うのは手元のホストになるので、
键の置き场やknown_hostsの记述などは、ホストXではなく手元の环境になります。

関系する全インスタンスのユーザやSSH键が同じならそこまで问题にはならないでしょうけど、
インスタンス先によってユーザや键が変わる场合は若干ややこしいですね。。。

~/.ssh/configに记述して楽をする

このような操作をそこそこ缲り返し行うなら、~/.ssh/configに记述してしまえば楽になります。

といいますか、そういった话はさすがに定番どころの设定なので、Developers.IOでも何回か记事になっていて参考になります。

蛇足がてら付け加えるなら、ssh_configHostパターン指定ができるので、

~/.ssh/config
1
2
Host *.compute.internal 172.31.*
  ProxyCommand  ssh -W %h:%p X

のように、VPC内のホストはすべてホストX経由で接続する…という记述しておくとより楽です。

例えば上述の例で言えば、

~/.ssh/config
1
2
3
4
5
Host *.compute.internal
  ProxyCommand  ssh -W %h:%p ec2-13-112-xxx-xxx.ap-northeast-1.compute.amazonaws.com
 
Host *
  User        ec2-user

としておくことで、下记のように短くなります:

1
$ ssh ip-172-31-xxx-xxx.ap-northeast-1.compute.internal

ちなみに

この指定方法は、Ansibleやrsync等、バックエンドにssh/scpを使っているコマンドにも有効です。

参考:

また直接関系はありませんが、このような踏み台ホストは频繁にアクセスすることになるので、
ControlMasterなども设定するとより幸せになれたことを并せてご报告いたします。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章