Security GroupではSSHを0.0.0.0/0に開放するべからず
AWS EC2 Linuxを利用する際、SSHでログインして利用することになりますが、
端末の所属するネットワークからAWS VPCに対するVPN等を利用できない場合、
EC2インスタンスのSSH(TCP 22)ポートをインターネットに公開することになります。
このようなケースに考えられるリスクと回避方法について考えていきます。
リスク
AWS EC2 Linuxに設定したSecurity Groupで、下記のようにSSHをAnywhere(0.0.0.0/0)に対して開放したとします。
このような場合、どういったリスクが考えられるでしょうか。
もちろん、EC2 Linuxに対するSSHログインにはキーペアが必要になるので、誰からでもログインできる状態ではありません。
ですが、万一キーペアが流出してしまった場合、クラッキングを受けた場合、SSHに脆弱性が発見された場合など、
様々なリスクを考えると必要最小限の端末からしかアクセスできないようにしておいたほうが安全だといえます。
回避方法(その1)
最も手っ取り早い回避方法は、SSHを許可するネットワークレンジを絞ることです。
自宅/自社のグローバルIPアドレスレンジが固定されている場合、そのレンジのみを許可することで、予期せぬアクセスを防ぐことができます。
自身のグローバルIPアドレスは下記のサイトなどで調べることができます。
これを調べてCIDRでIPアドレスを指定します。
しかし、この方法では下記の課題が残ります。
制限するネットワークレンジが必要以上に広い
グローバルIPアドレスが同一ISPを利用の他者に使いまわされる場合など、
自分以外の他者によってアクセスされる可能性は若干残ります。
SSHを開放する期間が長い
ネットワークレンジは制限するものの、基本的に常時SSHを開放した状態で運用することになります。
設定変更に手間がかかる
ノートPCで日常的に複数のネットワークからアクセスする場合、ISPの制約でグローバルIPを固定できない場合など、
端末のグローバルIPアドレスレンジが頻繁に変動する場合、毎回Security Groupを変更することになり、手間がかかります。
回避方法(その2)
回避方法(その1)で挙げた2つの課題ですが、プログラマブルなインフラならではの解決策が考えられます。
制限するネットワークレンジを自身のみに限定する
Security Groupで開放するSSHを自身のグローバルIPアドレスのみに限定することで、
自身以外によるアクセスを防ぐことができます。
SSHを開放する期間をログイン前後に限定する
端末からSSH接続する直前にSecurity GroupでSSHを開放し、
SSH接続を終了した直後にそのルールを削除することで、SSHを開放する期間を最小限に留めます。
設定変更の作業を自動化する
一連の手順をスクリプトとAPIで自動化することで、Security Groupの設定変更の手間を減らすことができます。
これを実現する具体的な手段が、下記のブログ記事で紹介されています。
この記事に書かれている方法をそのまま実行すると、
必要最小限のネットワークレンジと期間でSSHを開放してOSログインすることができます。
とても便利ですね。
個人的な好みですと、スクリプトはできるだけ薄くラップして、sshコマンドと同一の操作感で使えるようにしたいところです。
そこで、スクリプトを下記のように弄ってみました。
#!/bin/sh MYSECURITYGROUP=sg-xxxxxxxx MYIP=`curl -s ifconfig.me` aws ec2 authorize-security-group-ingress --group-id $MYSECURITYGROUP --protocol tcp --port 22 --cidr $MYIP/32 ssh $@ aws ec2 revoke-security-group-ingress --group-id $MYSECURITYGROUP --protocol tcp --port 22 --cidr $MYIP/32
変更点は下記の通り。
- セキュリティの観点から、アクセスキー/シークレットキーの設定をスクリプトから除外しました。
- キーペアやログイン先ホストを柔軟に変更できるよう、スクリプトの引数をそのままsshコマンドに渡すようにしました。
事前準備
awscliはあらかじめ設定しておきます。
aws configure
スクリプト内の”MYSECURITYGROUP”にSecurity GroupのIDを書き込みます。
動作確認
早速このスクリプトを使って動作を確認してみましょう。
今回はスクリプトのファイル名をssh-ec2とします。
$ ./ssh-ec2 -i xxx.pem ec2-user@ec2-xx-xxx-xxx-xx.ap-northeast-1.compute.amazonaws.com { "return": "true" } Last login: Wed May 28 13:26:23 2014 from xxxxx __| __|_ ) _| ( / Amazon Linux AMI ___|\___|___| https://aws.amazon.com/amazon-linux-ami/2014.03-release-notes/ 6 package(s) needed for security, out of 25 available Run "sudo yum update" to apply all updates. $ exit logout Connection to ec2-xx-xxx-xxx-xx.ap-northeast-1.compute.amazonaws.com closed. { "return": "true" }
意図したとおりに動作しました。
もちろん、元記事のようにssh configであらかじめ用意した設定を使うこともできます。
./ssh-ec2 myserver
mトラックバックがありません。