検証環境へアクセスするために踏み台サーバ―を経由しないとアクセスできないとか、踏み台サーバーを3つ経由しないと本番環境へアクセスできないとか、そんな場合でもssh
で1コマンドでアクセスするためのオプション指定について、man ssh
を眺めていたらたまたまProxyJump
というオプションが目に留まったので確認してみた。
環境
ローカルホストから、
という順序でSSHアクセスしたい場合、以前は(というより今でも多くのところで)ProxyCommand
を使って多段アクセスしていたが、(2016年リリースのOpenSSH 7.3で)ProxyJump
オプションが追加されており、このオプションを使うとより簡潔なオプション指定で多段アクセスを実現できる。
図にするとこんな構成。
ProxyJumpを使った多段アクセス
[zaki@cloud-dev ~]$ ssh 172.29.0.89 -J 192.168.0.16,172.16.1.0 zaki@192.168.0.16's password: zaki@172.16.1.0's password: zaki@172.29.0.89's password: Last login: Wed Feb 2 21:10:16 2022 from 172.29.0.10 [zaki@restricted-node ~]$
[zaki@restricted-node ~]$ ip a s ens192 2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 00:0c:29:77:f6:c4 brd ff:ff:ff:ff:ff:ff inet 172.29.0.89/24 brd 172.29.0.255 scope global noprefixroute ens192 valid_lft forever preferred_lft forever
この通り、-J
オプションにアクセスしたい順番にカンマ区切りで踏み台ホストを羅列すれば、記述した順序でSSHアクセスして最終的にお目当てのターゲットホストへログインする動作になる。
ユーザー名やポートが異なるサーバーがある場合
踏み台の特定ホストだけユーザー名やポート番号を指定する場合は、username@host:port
の書式で記述する。
途中の踏み台の172.16.1.0
が25022
でListenしていて、さらにsample-user
ユーザーでアクセスする場合は以下の通り。
[zaki@cloud-dev ~]$ ssh 172.29.0.89 -J 192.168.0.16,sample-user@172.16.1.0:25022 zaki@192.168.0.16's password: sample-user@172.16.1.0's password: zaki@172.29.0.89's password: Last login: Wed Feb 2 21:10:49 2022 from 172.29.0.10 [zaki@restricted-node ~]$
鍵認証
ここまでの例はコマンド実行例からも分かる通り、パスワード認証でログインしている。
公開鍵認証については、ドキュメントからはちょっと読み取れなかったけど、コマンドラインオプションで指定できる秘密鍵は、お目当てのターゲットホストに登録してある公開鍵のみに作用している。
踏み台サーバーの鍵認証用の秘密鍵はコマンドラインでは指定できなさそう。
ターゲットホストとの公開鍵認証はオプション指定で従来通り特に問題なく実行できる。
ローカルにある秘密鍵~/.ssh/id_rsa_4096
の公開鍵が、ターゲットホストの~/.ssh/authorized_keys
に登録済みであれば、以下の通り。
[zaki@cloud-dev ~]$ ssh 172.29.0.89 -J 192.168.0.16,sample-user@172.16.1.0:25022 -i ~/.ssh/id_rsa_4096 zaki@192.168.0.16's password: sample-user@172.16.1.0's password: Last login: Wed Feb 2 21:18:53 2022 from 172.29.0.10 [zaki@restricted-node ~]$
172.29.0.89
アクセス時のパスワード認証が行われず、鍵認証でログインできている。
踏み台サーバーも鍵認証を行いたい場合は、少なくともssh_configに記述すれば可能。
ssh_config基本
まずは鍵認証なしの場合の記述。
踏み台2つ目以降は、その前段の踏み台のホストが何かをproxyjump
の行に記述する。
Host proxy1 hostname 192.168.0.16 Host proxy2 hostname 172.16.1.0 user sample-user port 25022 proxyjump proxy1 Host target hostname 172.29.0.89 proxyjump proxy2
踏み台サーバーへの秘密鍵の指定がある場合は、それぞれ指定すればOK
Host proxy1 hostname 192.168.0.16 identityfile ~/.ssh/id_rsa_4096 Host proxy2 hostname 172.16.1.0 user sample-user port 25022 identityfile ~/.ssh/id_rsa_nopass proxyjump proxy1 Host target hostname 172.29.0.89 identityfile ~/.ssh/id_rsa_4096 proxyjump proxy2
それぞれ対応した公開鍵をそれぞれのホストに登録してあれば、ターゲットホストへのSSHアクセスのコマンドで一気にログインできる。
(パスフレーズが設定されてればもちろん入力は必要だけど)
[zaki@cloud-dev ~]$ ssh target Last login: Wed Feb 2 21:36:41 2022 from 172.29.0.10 [zaki@restricted-node ~]$
ポートフォワード
ターゲットホスト上からlocalhost:8888
でアクセスできるwebサーバーがあるとして、このwebサーバーにSSHを実行するローカルからアクセスしたい場合について。といっても、通常のローカルポートフォワードと同じく-L
を使えばOK。
ローカルホストの8889/TCPをターゲットのlocalhost:8888にフォワードするには、-L 8889:localhost:8888
を指定する。
[zaki@cloud-dev ~]$ ssh 172.29.0.89 -J 192.168.0.16,sample-user@172.16.1.0 -L 8889:localhost:8888 zaki@192.168.0.16's password: sample-user@172.16.1.0's password: zaki@172.29.0.89's password: Last login: Wed Feb 2 23:08:47 2022 from 172.29.0.10 [zaki@restricted-node ~]$
この状態で確認用webサーバーを起動。
[zaki@restricted-node ~]$ ls -aF ./ ../ .bash_history .bash_logout .bash_profile .bashrc .ssh/ [zaki@restricted-node ~]$ python -m SimpleHTTPServer 8888 Serving HTTP on 0.0.0.0 port 8888 ...
これで、SSH接続元のブラウザでlocalhost:8889
にアクセスすると、ターゲットホストのlocalhost:8888
にフォワードされる。
ターゲットホストに対するローカルポートフォワード込みのssh_configは以下の通り。
(踏み台の記述は変更無し)
Host target hostname 172.29.0.89 identityfile ~/.ssh/id_rsa_4096 proxyjump proxy2 localforward 8889 localhost:8888
※ SimpleHTTPServerについては以下参照。
scpの多段転送
[zaki@cloud-dev ~]$ scp ./kubeconfig.yaml target:/var/tmp
ssh_configが設定されていれば、これで一気にターゲットホストへ転送できる。
ホップ数によってはこれがかなり便利。
ssh_config設定無しでコマンドラインオプションで指定するには、。(※ 後述)scp
には-J
オプションがないため、-o
でProxyJump
を指定する
[zaki@cloud-dev ~]$ scp -o 'ProxyJump 192.168.0.16,sample-user@172.16.1.0' ./kubeconfig.yaml 172.29.0.89:/var/tmp zaki@192.168.0.16's password: sample-user@172.16.1.0's password: zaki@172.29.0.89's password:
2023.08.01追記:
scp
にもOpenSSH 8.0で-J
オプションに対応していた模様。ssh
の-J
と同様に踏み台の指定を行う。
ただし現時点(OpenSSH 8.8)では、-J
オプションを転送元・転送先ファイル名の後に指定すると踏み台の指定がファイル名と認識されてしまうため、コマンドの直後に指定する。
### 後ろにオプション指定した場合 $ scp ./memo.md 172.16.1.3:~ -J 192.168.0.16 192.168.0.16: No such file or directory ### 先にオプション指定した場合 $ scp -J 192.168.0.16 ./memo.md 172.16.1.3:~ zaki@172.16.1.3's password:
Windows版SSH
動作する。
PS C:\Users\zaki> ssh -V OpenSSH_7.7p1, OpenSSL 1.0.2o 27 Mar 2018 PS C:\Users\zaki> ssh 172.29.0.89 -J 192.168.0.19,172.16.1.0 zaki@192.168.0.19's password: zaki@172.29.0.89's password: Last login: Sat Jan 29 20:13:16 2022 from 172.29.0.10 [zaki@restricted-node ~]$
5年以上前に機能追加されてたなんて知らなかった。。
ついでにいうとssh-copy-id
コマンドもしばらく知らなかった←