Ccmmutty logo
Commutty IT
0 pv7 min read

SSH多段ポートフォワーディングでRDP接続してみた

https://cdn.magicode.io/media/notebox/f34b019f-c84e-4250-806c-096f3aaf67b1.jpeg
2段の踏み台Linuxサーバがあるネットワークで、手元の作業PCから目的のWindowsへRDP接続します。
  • NW構成:Win1(作業PC) → Linux2 → Linux3 → Win4
  • 手段:SSH ローカルポートフォワーディング(-L)多段 に重ねる
  • 仕上げ:Tera Termマクロで トンネル作成〜mstsc起動までワンクリック化
※ SSHトンネルは便利な一方、攻撃にも悪用されうる技術なので、最後に「運用上の注意」もまとめます。

1. NW構成(今回のゴール)

添付図の構成です。
  • Win1(作業PC):
  • Linux2(SSH踏み台1):192.168.2.2:22
  • Linux3(SSH踏み台2):192.168.3.3:22
  • Win4(RDP先):192.168.4.4:3389
※Linux2とLinux3はIPフォワード(ルーティング)無効でWin1から直接Linux3やWin4へアクセスできない環境
ゴール:Win1から 127.0.0.1:53389 にRDPすると、Win4へ到達する
(ローカルに見せかけて、裏で多段SSHトンネルが張られている状態)

2. まずは仕組みを分解(手動だとこうなる)

今回のキモは「53389番を“同じ番号のまま”バケツリレーする」ことです。

2.1 Win1 → Linux2(1段目)

Win1上で、ローカル53389を Linux2のlocalhost:53389 へ転送します。

Win1(手元)で実行するイメージ

ssh linux2@192.168.2.2 -p 22 -L 53389:127.0.0.1:53389
これで Win1 の 127.0.0.1:53389 に投げた通信は、Linux2 の 127.0.0.1:53389 に届くようになります。

2.2 Linux2 → Linux3 → Win4(2段目)

次に Linux2上で、ローカル53389を Win4:3389 へ転送します(経路はLinux3経由)。

Linux2(踏み台1)上で実行するイメージ

ssh linux3@192.168.3.3 -p 22 -L 53389:192.168.4.4:3389
これで Linux2 の 127.0.0.1:53389 に来た通信は、SSHトンネル経由で Win4:3389 に届きます。

2.3 最後にRDPクライアント(mstsc)

Win1からローカルへRDPするだけ

mstsc → 接続先:127.0.0.1:53389

3. Tera Termマクロでワンクリック化

ここからが本題です。 上の「分解した手順」を、Tera Termマクロで一気通貫にします。
  • Tera Termで Linux2 へSSH接続しつつ、1段目の -L を設定
  • Linux2に入ったら、Linux3へ ssh して2段目の -L を設定
  • 一時ファイルとして .rdp を生成して mstsc.exe を起動
Tera Termのポート転送(SSH Forwarding)は公式マニュアルでも案内されている機能です。

4. Teratermマクロ(使ったマクロを記載)

; -- Linux2情報 --
LINUX2_IP   = '192.168.2.2'
LINUX2_PORT = '22'
LINUX2_USER = 'linux2'

; -- Linux3情報 --
LINUX3_IP   = '192.168.3.3'
LINUX3_PORT = '22'
LINUX3_USER = 'linux3'

; -- Win4情報 --
WIN4_IP     = '192.168.4.4'
WIN4_PORT   = '3389'
WIN4_USER   = 'win4'

; -- ポートフォワード設定 --
PORTFOWRD   = '53389'

; -- 設定ファイル名 --
PASSWORD_FILE = 'multihop_passwords.dat'
RDP_FILE_NAME = 'autogen_rdp_config.rdp'

; ================================================
; 1. 接続前処理(パスワード取得)
; ================================================
getdir MACRO_DIR
sprintf2 PASSWORD_FILE_PATH '%s\%s' MACRO_DIR PASSWORD_FILE

getpassword PASSWORD_FILE_PATH 'Linux2のパスワード' LINUX2_PASSWORD
getpassword PASSWORD_FILE_PATH 'Linux3のパスワード' LINUX3_PASSWORD


; ================================================
; 2. Linux2への接続
; ================================================
CONNECT_COMMAND = LINUX2_IP
strconcat CONNECT_COMMAND ':'
strconcat CONNECT_COMMAND LINUX2_PORT
strconcat CONNECT_COMMAND ' /ssh /2 /auth=password /user='
strconcat CONNECT_COMMAND LINUX2_USER
strconcat CONNECT_COMMAND ' /passwd='
strconcat CONNECT_COMMAND LINUX2_PASSWORD
strconcat CONNECT_COMMAND ' /ssh-L'
strconcat CONNECT_COMMAND PORTFOWRD
strconcat CONNECT_COMMAND ':127.0.0.1:'
strconcat CONNECT_COMMAND PORTFOWRD

connect CONNECT_COMMAND
wait '# ' '$ '


; ================================================
; 3. Linux3への接続
; ================================================
; -- Linux3のパスワード再取得
getdir MACRO_DIR
PASSWORD_FILE = 'multihop_passwords.dat'
sprintf2 PASSWORD_FILE_PATH '%s\%s' MACRO_DIR PASSWORD_FILE
getpassword PASSWORD_FILE_PATH 'Linux3のパスワード' LINUX3_PASSWORD

; -- Linux3へのSSHコマンド生成
SSH_COMMAND = 'ssh -o StrictHostKeyChecking=no -L '
strconcat SSH_COMMAND PORTFOWRD
strconcat SSH_COMMAND ':'
strconcat SSH_COMMAND WIN4_IP
strconcat SSH_COMMAND ':'
strconcat SSH_COMMAND WIN4_PORT
strconcat SSH_COMMAND ' '
strconcat SSH_COMMAND LINUX3_USER
strconcat SSH_COMMAND '@'
strconcat SSH_COMMAND LINUX3_IP
strconcat SSH_COMMAND ':'
strconcat SSH_COMMAND LINUX3_PORT

sendln SSH_COMMAND
wait "password:"
sendln LINUX3_PASSWORD
wait '# ' '$ '


; ================================================
; 4. RDPクライアント起動
; ================================================
getenv 'TEMP' TEMP_DIR
sprintf2 RDP_FILE_PATH '%s\%s' TEMP_DIR RDP_FILE_NAME

fileopen FHANDLE RDP_FILE_PATH 1
if FHANDLE = -1 then
    messagebox 'RDP設定ファイルの作成に失敗しました。 ' 'エラー'
    end
endif

filewriteln FHANDLE 'prompt for credentials:i:1'
sprintf2 LINE 'full address:s:127.0.0.1:%s' PORTFOWRD
filewriteln FHANDLE LINE
sprintf2 LINE 'username:s:%s' WIN4_USER
filewriteln FHANDLE LINE
fileclose FHANDLE

sprintf2 EXEC_COMMAND 'mstsc.exe "%s"' RDP_FILE_PATH
exec EXEC_COMMAND

5. 詰まりポイント(チェックリスト)

5.1 そもそもLinuxサーバでSSH転送が許可されているか

sshd側で転送が無効だと、channel open failed などで転送が張れません。 AllowTcpForwarding の設定が関係します。

5.2 Win4のRDP(3389)がLinux3から到達できるか

Win4側Windowsファイアウォールで Linux3 → Win4:3389 が許可されているか

5.3 ローカルポート(53389)が競合してないか

既にWin1、Linux2、Linux3で53389を使っているとトンネルが作れません。その場合は別ポートに変えてOKです。

6. 運用上の注意(大事)

  • 3389をインターネットに直出ししない(可能ならVPNや踏み台・GWで制御)
  • トンネルは便利ですが、攻撃でも“内部到達”に使われます(検知・制御の観点も意識)
  • 可能ならSSHは 鍵認証、踏み台は 接続元制限、ログ監視…など「いつもの堅実運用」を

7. おわり(使いどころ)

踏み台が増えるほど「毎回コマンド打つ」のが地味にストレスなので、 “理解は分解して、運用はワンクリック” に寄せるのはかなりアリでした。
同じ考え方はDB接続(SSHトンネル)でもよく使うので、踏み台越し接続の引き出しとして持っておくと便利です。

Discussion

コメントにはログインが必要です。