自分の作业环境の作り直しをしているのですが、
たまに理解が怪しくなるので、确认ついでにここに吐き出しておこうと思います。
背景
「リモート环境にあるホストAにsshあるいはscpするためには、
踏み台(Bastion)となるホストXに一度SSHログインしないとならない」
というケース/环境はそこそこ多いと思います。
これがsshなのであればまあ、ssh X
-> ssh A
とするだけなのでそこまででもありませんが、
scpだった场合は概ねこんな手顺になりますよね。
- まず
ssh X
としてホストXにログイン - ホストX上で
scp -p A:/path/to/datafile ~/
(オプションはお好み) - コピーが终わるのを待ってから、Xからログアウト
scp -p X:~/datafile .
- コピーが终わるのを待って
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接続をWindowsクライアントから行う | Developers.IO
- Amazon VPC环境にメンテナンス用の踏み台サーバを构筑する | Developers.IO
蛇足がてら付け加えるなら、ssh_config
はHost
にパターン指定ができるので、
1
2
|
Host *.compute.internal 172.31.* ProxyCommand ssh -W %h:%p X |
のように、VPC内のホストはすべてホストX経由で接続する…という记述しておくとより楽です。
例えば上述の例で言えば、
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
なども设定するとより幸せになれたことを并せてご报告いたします。