テックブログ

技術ネタ

ssh ポート転送 備忘録

こんにちは、技術部の阿部です。
Yahoo も Google も Amazon も 2ch も無い時代からエンジニア(らしきこと)をやってます。

バブルが終焉を迎えようとしていた頃、見ていた夢にあっさり見切りをつけて
システムエンジニアの世界へ足を踏み入れてしまったわけです。
以来ン十年、携わったシステムの9割以上がUNIX系になりますが(MS製品は避けてきました)、
転々と流れて、ネットアシストに流れ着いた現在、やっぱりUNIX系サーバの運用管理業務に
勤しんでおります。

で、sshです。
運用管理という業務の性質上、毎日あちこちのサーバへsshログインしているわけですが、
sshには便利なポート転送という機能があります。
だが、しかし、いつも”ローカル?リモート?どっちだっけ?”となってググることになるので、
今回は備忘録も兼ねてポート転送について。

| ホストA |   —>   | ホストB |   —>   | ホストC |
x.x.x.x             y.y.y.y              z.z.z.z

ホストA から ホストC へ行きたい!
=========================================================
[hostA]$ ssh y.y.y.y
[hostB]$ ssh z.z.z.z
[hostC]$
=========================================================
至極フツーのアプローチです。私もいつもコレです。

ポート転送機能を使うと ホストA から ホストC へ、いきなりジャンプできます。
(ターミナルを2個開いたり、事前の仕込みが必要ではありますが・・・。)
=========================================================
1. ターミナルを2個開いてホストAにログインしときます
=========================================================
2. ターミナル1  [hostA]$ ssh -L 10022:z.z.z.z:22 y.y.y.y
または
[hostA]$ ssh -L 127.0.0.1:10022:z.z.z.z:22 y.y.y.y
=========================================================
3. ターミナル2  [hostA]$ ssh 127.0.0.1 -p 10022
[hostC]$
=========================================================

解説
=========================================================
[hostA]$ ssh -L 127.0.0.1:10022:z.z.z.z:22 y.y.y.y

書式:ssh -L [転送元IP]:[転送元ポート]:[転送先IP]:[転送先ポート] [踏み台IP]
転送元IPアドレスは省略可能で、省略したら<127.0.0.1>が補完される
=========================================================

この1行のコマンドを投げると次のようなことが起こります。
1. ホストAからホストBへssh接続する
2. ホストAとホストBの間に、ホストCのsshポートへワープするsshの道が作られる
3. ホストA上にはホストCへ通じるsshポート10022が開く

このときnetstatの出力はこんな感じになってます。
=========================================================
【ホストA】
tcp 0.0.0.0:22    0.0.0.0:*         LISTEN        1150/sshd
tcp 127.0.0.1:10022 0.0.0.0:*         LISTEN        17527/ssh <– ポート10022が開く
tcp x.x.x.x:37714   y.y.y.y:22        ESTABLISHED  17527/ssh   <– AからBへssh接続
=========================================================
【ホストB】
tcp 0.0.0.0:22         0.0.0.0:*    LISTEN        1280/sshd
tcp y.y.y.y:22         x.x.x.x:37714  ESTABLISHED  1596/sshd   <– AからBへssh接続
=========================================================

この状態で、ターミナル2からローカルホストのポート10022にsshします。
=========================================================
[hostA]$ ssh 127.0.0.1 -p 10022
=========================================================

netstatの出力はこんな感じになってます。
=========================================================
【ホストA】
tcp 0.0.0.0:22    0.0.0.0:*      LISTEN         1150/sshd
tcp 127.0.0.1:10022 0.0.0.0:*             LISTEN         17527/ssh
tcp 127.0.0.1:10022 127.0.0.1:54502    ESTABLISHED  17527/ssh   <– 10022へ接続
tcp x.x.x.x:37714   y.y.y.y:22    ESTABLISHED  17527/ssh   <– AからBへssh接続
tcp 127.0.0.1:54502 127.0.0.1:10022 ESTABLISHED  17533/ssh   <– 10022からCへ接続
=========================================================
【ホストB】
tcp 0.0.0.0:22          0.0.0.0:*           LISTEN         1280/sshd
tcp y.y.y.y:22           x.x.x.x:37714      ESTABLISHED  1596/sshd   <– AからBへssh接続
tcp y.y.y.y:49268       z.z.z.z:22          ESTABLISHED  1600/sshd   <– BからCへssh接続
=========================================================
【ホストC】
tcp z.z.z.z:22          y.y.y.y:49268      ESTABLISHED  8078/sshd   <– CからBへssh接続
=========================================================

目的地までコツコツsshするか、ひと手間(コマンド1行)かけて飛ぶか・・・
ケースbyケースですね、ハイ。

ホストAを、ホストCへの踏み台にしたいときはどーしましょ
=========================================================
[hostA]$ ssh -g -L 10022:z.z.z.z:22 y.y.y.y
または
[hostA]$ ssh -L 0.0.0.0:10022:z.z.z.z:22 y.y.y.y
=========================================================
-gオプションまたは転送元アドレスを<0.0.0.0>明示指定すればホストAが踏み台に変身します。

 

あと・・・もし、踏み台サーバ(上の例では、ホストB)にncコマンドが入っていれば
sshのProxyCommandオプションを使ってこんな芸当もできます。
=========================================================
[hostA]$ ssh z.z.z.z -o ‘ProxyCommand ssh y.y.y.y /usr/bin/nc %h %p’
[hostC]$
=========================================================
ncコマンド、別名netcatコマンドは、CentOSなら簡単にyumインストールできますが、
使い方次第で悪のツールにも化ける危険なコマンドです。
できることなら、特にお客様サーバ等への導入は避けたいところです。

興味のある方は下記サイトが詳しいのでどーぞ。
http://www.intellilink.co.jp/article/column/security-net01.html

sshバージョン5.4から、このnetcat機能が実装されています。
http://www.openssh.com/txt/release-5.4(抜粋)
=========================================================
* Added a ‘netcat mode’ to ssh(1): “ssh -W host:port …” This connects
stdio on the client to a single port forward on the server. This
allows, for example, using ssh as a ProxyCommand to route connections
via intermediate servers. bz#1618
=========================================================
-Wオプションでイケるみたいですね。
でも残念ながらCentOS6系の最新パッケージのバージョンは5.3です。
=========================================================
# ssh -V
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013

# ssh –help
usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
[-D [bind_address:]port] [-e escape_char] [-F configfile]
[-I pkcs11] [-i identity_file]
[-L [bind_address:]port:host:hostport]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-R [bind_address:]port:host:hostport] [-S ctl_path]
[-W host:port] [-w local_tun[:remote_tun]]
[user@]hostname [command]
=========================================================
バージョン5.3なのですが・・・ヘルプを見ると-Wオプションが・・・。

パッケージの変更履歴を見てみます。
=========================================================
# rpm -q openssh –changelog | grep -i netcat -B1
* Thu Dec 13 2012 Petr Lautrbach <plautrba@redhat.com> 5.3p1-84.1
– Add a ‘netcat mode’ (ssh -W) (#860809)
=========================================================
2012年12月にはパッケージに取り込まれていたようですね、はい。
いつもmanなんてインストールしないし見ないし、全く知りませんでした。

 

以上、常に情報のアンテナを張り巡らせて、マニュアルもチェックしましょう、というお話でした。

実績数30,000件!
サーバーやネットワークなど
ITインフラのことならネットアシストへ、
お気軽にご相談ください