3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Session Manager経由のEC2アクセスから、SSHポートフォワードまでのメモ

Last updated at Posted at 2025-04-25

こんにちは。@masatomix です。
仕事でsshのポートフォワードを整理する機会があって、そのときの作業メモとTIPSです。

開発しているときになんとなく、~/.ssh/config とかにsshの設定を書いてsshアクセスしたり、踏み台サーバを使ってアクセスしたり、 sshの転送設定を書いて踏み台経由でWEBサーバに転送したりすると思いますが、その辺のお話です。

この辺ボンヤリとした知識でやってたんですが、踏み台のEC2インスタンスがsshアクセスではなく、AWSの Session Manager経由のところがあり、sshのポートフォワードとかをまあまあ理解しないとって状況になった、という背景です。

前提の環境

というわけで、下記のような環境を想定します。

image-20250426001428513

アクセスしたい本丸のサーバは dest-ec2 (192.168.1.240)で、ここにsshしたり、WEBサーバ疎通をするのがゴールとしましょう。
(なので、ユーザPC側にdest-ec2 にsshするための秘密鍵は持ってるモノとします)

$ ls -lrt ~/.ssh/kino-KeyPair.pem 
-r-------- 1 sysmgr sysmgr 1679 Apr 23 10:32 /home/sysmgr/.ssh/kino-KeyPair.pem

その手前には、いわゆる踏み台サーバ bastion-ec2があるとします。
で、本丸dest-ec2 へのアクセスは、踏み台サーバ bastion-ec2からのみ可能としてあります1

一方踏み台サーバbastion-ec2はsshアクセスはNGで、AWSのSession Manager 経由で接続するものとします。ちなみに AWSのSession Manager ってのは、いわゆる

image-20250422184547713

コレですね。ssh接続に比べて「秘密鍵を管理しなくてよい」「ネットに対してインバウンドのポート(22ポートとかね)を開放しなくてよい」「アクセスの許可をIAMポリシーで管理出来る」などなどの利点がある接続方法です。

最後に、今回接続するPC側でいくつかコマンドを発行しますが、wslを想定しています。

必要なツールのインストール

PC側のwslに、AWS CLIはインストールされているものとします(必要に応じて下記を参考にしてください)。

参考: https://qiita.com/masatomix/items/7a1af1f6fc28258927ae

$ aws --version
aws-cli/2.13.17 Python/3.11.5 Linux/5.15.90.1-microsoft-standard-WSL2 exe/x86_64.ubuntu.22 prompt/off

$ session-manager-plugin
session-manager-plugin: command not found (インストールされていない)

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3816k  100 3816k    0     0   402k      0  0:00:09  0:00:09 --:--:--  796k

$ sudo dpkg -i session-manager-plugin.deb
[sudo] password for sysmgr:
Selecting previously unselected package session-manager-plugin.
(Reading database ... 49341 files and directories currently installed.)
Preparing to unpack session-manager-plugin.deb ...
Preparing for install
Unpacking session-manager-plugin (1.2.707.0-1) ...
Setting up session-manager-plugin (1.2.707.0-1) ...
Creating symbolic link for session-manager-plugin

$ session-manager-plugin
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.
$

インストール完了です。

やってみる

インスタンスIDを特定して、踏み台サーバへログインする

AWS CLIの Session Managerの機能で、踏み台サーバへログインします。ログインするには踏み台サーバのインスタンスIDが必要なので、まずはそれを調べてみます。

$ profile=xxx (プロファイル指定は、必要に応じて)
$ aws ssm describe-instance-information --profile ${profile}
{
    "InstanceInformationList": [
        {
            "InstanceId": "i-0abb65330e171512d",
            "PingStatus": "Online",
            "LastPingDateTime": "2025-04-21T17:45:39.609000+09:00",
            "AgentVersion": "3.1.1927.0",
            "IsLatestVersion": false,
            "PlatformType": "Linux",
            "PlatformName": "Amazon Linux",
            "PlatformVersion": "2023",
            "ResourceType": "EC2Instance",
            "IPAddress": "192.168.xx.10",
            "ComputerName": "ip-192-168-xx-10.ap-northeast-1.compute.internal",
            "SourceId": "i-0abb65330e171512d",
            "SourceType": "AWS::EC2::Instance"
        }
    ]
}

踏み台のインスタンスID(i-0abb65330e171512d)が特定できました。このインスタンスへのログインにはsshはつかえずSession Manager で接続するので、下記のコマンドを実行します。

$ instance_id=i-0abb65330e171512d
$ aws ssm start-session --target ${instance_id} --profile ${profile}

Starting session with SessionId: kino@example.com-vfxbak3l2uj8srn7vlnbu4s688
sh-5.2$

入れました。うまくいったようですね!

いちおう、本丸サーバdest-ec2の22番ポートへの疎通も兼ねて、踏み台の先の本丸サーバまでログインしておきましょう。先ほどの手元の秘密鍵を、コピペとかで踏み台サーバにもっていって

sh-5.2$ ls -lrt ~/.ssh/kino-KeyPair.pem 
-r--------. 1 ssm-user ssm-user 1679 Apr 23 01:39 /home/ssm-user/.ssh/kino-KeyPair.pem
sh-5.2$ 

この状態で、sshします2

sh-5.2$ ssh -l ec2-user 192.168.1.240 -i ~/.ssh/kino-KeyPair.pem 

Run "/usr/bin/dnf check-release-update" for full release and version update info
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Wed Apr 23 01:58:21 2025 from 192.168.1.10
[ec2-user@ip-192-168-1-240 ~]$

Session Managerでログインした踏み台経由で、本丸サーバへsshログインする事が出来ました。

踏み台の先にポートフォワードする。

さてこれだけだと、接続に何やらアヤシゲ(?)なAWSのコマンドを使う必要があるし、いわゆる既存のsshポート転送もどう使えばよいか分からないので、もうすこしいろいろやってみます。

実は Session Managerにはポート転送の機能があり、たとえば

  • localhost のポート 2222にTCP/IP接続したら
  • 踏み台サーバに繋がり
  • 踏み台からさらにIPアドレス(192.168.1.240) のポート22 に転送させる

などが出来ます。具体的には以下の通り。

$ aws ssm start-session --target ${instance_id} --profile ${profile} \
 --document-name AWS-StartPortForwardingSessionToRemoteHost \
 --parameters localPortNumber=2222,portNumber=22,host=192.168.1.240
 

Starting session with SessionId: kino@example.com-y87fhnrz2gykocvy4x9uaqi22y
Port 2222 opened for sessionId kino@example.com-y87fhnrz2gykocvy4x9uaqi22y.
Waiting for connections...

Connection accepted for session [kino@example.com-y87fhnrz2gykocvy4x9uaqi22y]

なにやら待ち受け状態になりました。
パラメタをみたらだいたい意味は明らかですが、

  • AWS-StartPortForwardingSessionToRemoteHostで指定サーバの指定ポートへ転送する機能を使う3
  • localPortNumber=2222: localhost の待ち受けポート番号
  • host=192.168.1.240 : 転送先のサーバ名/IP
  • portNumber=22: 転送先のポート番号

ってことですね。

というわけで、別のwslコンソールからlocalhostのポート2222に SSHで繋いでみます。

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem 

Run "/usr/bin/dnf check-release-update" for full release and version update info
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Wed Apr 23 01:58:25 2025 from 192.168.1.10
[ec2-user@ip-192-168-1-240 ~]$ 

おお、踏み台サーバの転送機能を経由して、本丸サーバにsshで接続することが出来ました。

セキュリティグループで開放されていないほかのポート転送はどうする

さて、SSHのポート22はセキュリティグループで開放されていましたが、それ以外のポート番号についてです。例えば、本丸サーバdest-ec2は実はWEBサーバで、ポート8080で待ち受けているとします。さきのポート転送と同じように、

 --parameters localPortNumber=8888,portNumber=8080 host=192.168.1.240

ってやれば良さそうですが、先に説明したとおり本丸サーバのポート8080は踏み台からのアクセスが許可されていないため、上記のやり方では接続出来ません。

一応試しておきましょう。本丸サーバにWEBサーバを立ちあげて、

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem
Last login: Fri Apr 25 12:47:11 2025 from 192.168.1.10

[ec2-user@ip-192-168-1-240 ~]$ 
[ec2-user@ip-192-168-1-240 ~]$ sudo yum -y install nc
[ec2-user@ip-192-168-1-240 ~]$ while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; echo 'hello'; } | nc -l 8080; done
(8080へTCP/IPで繋ぐと、応答するヤツをつくりました)

別のwslで、AWS SSMの機能で localhost の8888ポートへのアクセスを本丸の8080ポートへ転送させます。

$  aws ssm start-session --target ${instance_id} --profile ${profile} \
 --document-name AWS-StartPortForwardingSessionToRemoteHost \
 --parameters localPortNumber=8888,portNumber=8080,host=192.168.1.240

Starting session with SessionId: kino@example.com-bb4qqviplgjakhp4obcu6gtqi4
Port 8888 opened for sessionId kino@example.com-bb4qqviplgjakhp4obcu6gtqi4.
Waiting for connections...

待ち受け状態にはなりましたが、curlしてみると、、、

$ curl localhost:8888
^C
$

案の定だめでしたね。

ようやく SSHポートフォワード

さてようやくSSHポートフォワードのはなしです。いま本丸サーバは

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem

でssh接続までは可能なのでした。

AWSのSSMを用いた 8888ポートへの転送はCtrl+Cなどで停止し、代わりにSSHポートフォワードを用いてみます。具体的には下記の通り -L オプションを用います。

Connection accepted for session [kino@example.com-bb4qqviplgjakhp4obcu6gtqi4]
(Ctrl+cします)
^CTerminate signal received, exiting.

Exiting session with sessionId: kino@example.com-bb4qqviplgjakhp4obcu6gtqi4.

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem -L 8888:192.168.1.240:8080
[ec2-user@ip-192-168-1-240 ~]$

なんだかssh接続出来たようですが -L 8888:192.168.1.240:8080の意味は、

  • この本丸サーバへ接続しているSSHを用いて、
  • localhost のポート8888への接続を
  • 192.168.1.240の8080ポートへ転送する

って意味です。ということで先のwslからcurlで繋いでみると、、

$ curl localhost:8888
hello
$

おお、接続出来ましたね4

ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem -L 8888:192.168.1.240:8080

のコマンドだけみると、やたらポート番号が出てきてわけがわからなくなりますが、-L までの指定はsshでログインするためのパラメタ指定、-L以降でポート転送の指定、と考えるとすっきりします。

おつかれさまでした。

まとめ

  • 踏み台サーバがSession Manager経由だったとしても、
  • その先のサーバ群がssh接続可能であれば
  • Session Managerのポートフォワード機能でsshを転送して、
  • そのトンネルを使って sshのポートフォワード機能を用いれば、他のポートにも着弾可能

ということが分かりました。

TIPS

-N オプション、-fオプション

-Nオプションはトンネルを作るだけでコンソールを返さない、-fオプションはバックグラウンドで実行する、となります(やってみるとだいたい分かります5。)

sshで入れてしまってコンソールが返ってくるとなんだかよく分からなくなってしまうため、-Nするのが良さそうです。-fは書いてみたものの、停止がメンドイのであまり使わないかな、、。

-vvv オプション

もはやssh転送関係ないですが、TCP/IP接続のデバッグをしたい場合、この詳細オプションをつけてあげましょう。

おなじみの ~/.ssh/config を使いたい

さてさて AWS-StartPortForwardingSessionToRemoteHostしたのち、sshログインするために毎回

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem

と書いたり、sshポートフォワード するために毎回

$ ssh -l ec2-user localhost -p 2222 -i ~/.ssh/kino-KeyPair.pem -L 8888:192.168.1.240:8080

って指定するのは煩雑です。~/.ssh/config に以下を書いておきましょう。

$ cat ~/.ssh/config
Host dest-ec2
  HostName localhost
  User ec2-user
  Port 2222
  IdentityFile "/home/sysmgr/.ssh/kino-KeyPair.pem"

Host dest-ec2-web
  HostName localhost
  User ec2-user
  Port 2222
  IdentityFile "/home/sysmgr/.ssh/kino-KeyPair.pem"
  LocalForward 8888 192.168.1.240:8080
$

~/.ssh/config の指定もパッと見るとややこしく見えるけど、よくよく分解してみると -Lオプションと同じですね。一応、接続してみましょう。

$ ssh dest-ec2

Run "/usr/bin/dnf check-release-update" for full release and version update info
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
Last login: Fri Apr 25 13:50:26 2025 from 192.168.1.10
[ec2-user@ip-192-168-1-240 ~]$

お疲れさまでした!

VSCodeから踏み台経由でサーバに接続する

VSCodeから踏み台サーバ経由で本丸サーバに接続してみます。この機能はVSCode上でリモートのファイルを開いたりリモートのターミナルを操作できたりなど、超便利な機能です。

VSCodeはデフォルトでは%userprofile%\.ssh\config の設定を参照するようなので、そちらに記載をします。wslでなく、コマンドプロンプトから見てみましょう。

%userprofile%.ssh\config
C:\Users\xxx> type %userprofile%\.ssh\config

Host dest-ec2
  HostName localhost
  User ec2-user
  Port 2222
  IdentityFile "C:/Users/xxx/.ssh/kino-KeyPair.pem"

さらにVSCodeやコマンドプロンプトから上記のファイルを読み込んだ場合はwslのディレクトリのファイルを正しく扱えない場合があるみたいなので(当方の環境ではPermission関連で怒られた)、上記のように別の場所に秘密鍵ファイルを配置することにしました。

さて、AWS-StartPortForwardingSessionToRemoteHostしたのち、VSCode左下のアイコンより接続していきます。

vs01

vs02

程なくして、接続出来たようですね。

vs03

関連リンク

  1. 正確にはbastion-ec2 に設定されたセキュリティグループからのみ接続可能、としてあります。

  2. -lオプション ssh -l ec2-user 192.168.1.240 は、ssh ec2-user@192.168.1.240 と等価

  3. 自サーバの指定ポートに転送するだけの、AWS-StartPortForwardingSession などもあります。

  4. この転送プロセスは、本丸サーバ(192.168.1.240)で動いているため、実際の引数は-L 8888:localhost:8080でもOKです。自分のポート8080への転送ってことですね。

  5. バックグラウンドにはいっちゃうので、とめるときはps -ef |grep sshとかしてプロセスID突き止めてkill プロセスIDね)

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?