portwarpで ssm-session-manager を活用する
Tweetはじめに
AWSで最近リリースされた、ssm-session-manager と言う機能は、「IAMで権限管理ができるssh」なのだと思って、「これは便利なものができた」と喜んだのですが、実際に使ってみたらいろいろ制限がありました。
一つの問題は、/bin/shを決め打ちで起動してしまうことですが、他にも、ssh の代替にしようと思うと、以下のような機能が欲しくなります。
- port forwarding
- scp/rsync などのファイル転送
特に、テスト中などは、本来、プライベートなサーバを一時的に外から見たいということがよくあります。「プライベート」とは、AWS内にある別のサーバにAPIなどのサービスするのが目的で、ネットワーク的に外部に公開されていないものです。
そのネットワーク内に、ssh
ができるサーバがあれば、ssh -L ....
で、port forwardingをして、ローカルのサーバからAWS内のプライベートなサーバに接続することができます。しかし、ssm-session-managerには、この機能がありません。
そこで、これを実現するツールを作ってみました。
このアイディアは、下記の記事を元にしています。
portwarpとは
portwarp
とは、piping-server
経由で、サーバとクライアントを接続し、両者の間で port forwardingを行うツールです。
ポイントは、piping-server
とportwarp server
のつなぎ方ですね。
portwarp
サーバからの outbound connection で接続するので、このサーバを動かすマシンのポートを開ける必要がないことです。つまり、VPC内で孤立しているネットワークに、外部から接続するトンネルを一時的に開けることができるわけです。
必要なもの
- piping-server: portwap server および portwarp client からアクセスできるもの
- docker または ruby 実行環境
以下の例では、piping-server の URL を https://piping.server/
として記述します。ご自分が使用されるサーバのURLと置き換えて使用してください。
portwarpのインストール
Dockerを使用する場合
$ docker pull essa/portwarp
rubyを使用する場合
$ git clone https://github.com/essa/portwarp
$ cd portwarp
$ bundle
Dockerでインストールした場合は、起動方法は以下のようになります。
$ docker run --net=host -ti essa/portwarp portwarp .....
rubyの場合は、次のようになります。
$ bundle exec bin/portwarp .....
使用方法
最初にサーバ側を起動します。
$ docker run --net=host -ti essa/portwarp portwarp https://piping.server/
I, [2019-03-24T13:36:14.547737 #1] INFO -- : portwarp start
I, [2019-03-24T13:36:14.547936 #1] INFO -- : server mode
I, [2019-03-24T13:36:14.589788 #1] INFO -- : server start url = https://piping.server/29ef18e25dddece9
portwarp
は起動時に、制御用パイプのURLを表示します。これをクライアント側の起動パラメータとしてください。
$ bundle exec bin/portwarp https://piping.server/29ef18e25dddece9 8080 private.server.local:80
クライアント側では、URLの後に、転送用ポートの番号と転送先を指定します。パラメータが3つ以上あるとクライアントモードになります。
クライアント側が起動したら、localhost:8080
が private.server.local:80
に接続された状態になります。このまま、ローカルマシンのブラウザで http://localhost:8080
にアクセスすると、転送先のサーバに接続できます。
次のように転送先の後ろにコマンドをつけると、port forwardingの確立後に、そのコマンドを起動します。
$ bundle exec bin/portwarp https://piping.server/29ef18e25dddece9 8080 private.server.local:80 curl http://localhost:8080/
そのサーバで sshd が起動していれば ssh で接続することもできます。
$ bundle exec bin/portwarp https://piping.server/29ef18e25dddece9 1022 localhost:22 ssh -p 1022 ssm-user@localhost
この場合、転送先の localhost:22
は、portwarp
サーバから見た localhost
なので、portwarp
サーバを起動しているマシンの sshd に接続します。
このように ssh
のポート指定をすれば、sshでファイル転送を行う、scp
, rsynce
, git
なども同様に使用することができます。
rsyncの使用例
$ bundle exec bin/portwarp https://cached-downloads.degica.com:8081/5820c3fd8748bb7f 2022 localhost:22 'rsync -rv -e "ssh -p 2022" source_directory user@localhost:target_directory'
まとめ
portwarp
というツールを併用することにより、ssh による外部からのアクセスを完全に遮断して、ssm-session-managerのみの運用に切り替えることができました。
- 社内専用の
piping-server
を用意する(VPN経由で接続するもの) - プライベートネットワーク内に踏み台用サーバを用意し、ssm-session-managerの権限を与える
- 踏み台サーバのセキュリティグループは、inboundは完全遮断、outboundは 80 のみ許可
- プライベートネットワーク内のサーバには
openssh-server
をインストールして、port 22は、踏み台サーバからのアクセスのみ許可する
これで、上記の例のようにして、踏み台サーバ経由で、プライベートネットワーク内のサーバに外部から ssh接続したり、プライベートなサーバに直接アクセスして調査したり、テストしたりすることができます。
この経路が開いているのは portwarp
サーバ起動中だけです。これを終了すれば、外部からのアクセスは完全にできなくなります。これで、通常時は安全な運用をしながら、導入時やトラブル時には、制限なく自由にアクセスすることができるようになりました。
また、そのアクセスの権限は、ssmの権限として、AWS IAMによって管理することができます。