「Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版」(日経BP社)を参考に業務でインフラ構築することになりました。
インフラ初心者には特にCHAPTER6の「6−4 踏み台サーバーを経由してSSHで接続する」が難しく、解説が理解できずハマったので自分用メモに残します。
そもそも踏み台サーバーって何?
踏み台サーバーとは、インターネットに直接繋がないサーバーをSSHで接続するために経由されるサーバーのことです。
この図ではプライベートサブネット内のインスタンスはプライベートIPアドレスしか持たないので、インターネットには接続できません。
そこで、このインスタンスにMySQLなどのデータベースソフトをインストールする際には
①パブリックサブネット内のパブリックIPアドレスを持つインスタンスへSSHでアクセス
②そのインスタンスからプライベートサブネット内のインスタンスへSSHでアクセス
③プライベートサブネット内からコマンドを叩き、パブリックサブネットを経由してインストール
という流れになります。
2つのサーバーは同じVPC内にあるので、プライベートIPアドレスしか持たないインスタンスへも②の方法でアクセスが可能です。
今回はローカル環境からプライベートサブネット内のインスタンスへSSH接続するまで②をまとめました。
踏み台サーバーを使った接続方法
パブリックサブネット内のインターネット接続可能なインスタンスを「インスタンス①」、プライベートサブネット内のインスタンスを「インスタンス②」とします。
また、インスタンス①の秘密鍵ファイルは"my-key.pem"、インスタンス②の秘密鍵ファイルは"my-key-private.pem"でどちらも現在はローカル環境のホームディレクトリに存在します。
ローカル環境からインスタンス①へのSSH接続は問題ありません。現在ローカル環境にあるインスタンス①の秘密鍵を使います。
しかし、インスタンス①からインスタンス②へアクセスしようとしても、インスタンス①はインスタンス②の秘密鍵を持っていないのでSSH接続ができません。そこで図中にあるように、インスタンス②の秘密鍵をローカル環境からインスタンス①へコピーする必要があるのです。
鍵のコピーでハマった
ではscpコマンドを使ってインスタンス②の秘密鍵をインスタンス①にコピーしてみます。
scpとはSSHプロトコルを用いて安全にファイルをコピーするためのコマンドです。
[ローカル側]
$ scp -i my-key.pem my-key.pem <ユーザー名>@ <インスタンス①のパブリックIPアドレス>:~/
cp: <ユーザー名>@: No such file or directory
<ユーザー名>@<インスタンス①のパブリックIPアドレス>:: Permission denied (publickey).
p148のコードをそのまま実行しましたがファイルが見つからないのと、Permission deniedのエラーが2つ出てしまいました。
ちなみにユーザー名は本に従って進めていれば"ec2-user"になっていると思います。
正しいコマンドを確認
$ scp -i <送信先の秘密鍵のパス=インスタンス①の秘密鍵のパス> <送信するファイルのパス=インスタンス②の秘密鍵のパス> <ユーザー名>@<送信先のパブリックIPアドレス=インスタンス①のパブリックIPアドレス>:<ファイルをどこに配置するかのパス>
間違っていた点は
- 送信するファイルはインスタンス②の秘密鍵なのに、送信するファイルのパスにインスタンス①の秘密鍵のパスを書いていた
- ユーザー名と送信先のパブリックIPアドレスの間のスペースは不要 (本にはスペースが書いてあるけど不要です!)
でした。
インスタンス①の秘密鍵はmy-key.pemですが、インスタンス②の秘密鍵はmy-key-private.pemなので、送信するファイルのパスはmy-key-private.pemです。
上記2つを修正して、No such file or directoryが出ていたのでさらに秘密鍵や送信するファイルのパスを絶対パスで書きます。
$ scp -i ~/my-key.pem ~/my-key-private.pem <ユーザー名>@<インスタンス①のパブリックIPアドレス>:~/
<ユーザー名>@<インスタンス①のパブリックIPアドレス>:: Permission denied (publickey).
Permission deniedが消えません。
調べてみると、秘密鍵へのアクセス制限が無いのでファイルのコピーができないようです。
秘密鍵ファイルの権限を変更
$ chmod 777 ~/my-key-private.pem
chmod 数字 権限を変更したいファイル
で権限が変えられます。(アルファベットで権限を指定する方法もあります)
この数字が誰にどの権限を与えるかを意味しており、777はすべてのユーザーにすべての権限を与えることを意味します。
これでもう一度scpコマンドを叩くと
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/<ユーザー名>/.my-key-private.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/<ユーザー名>/.my-key-private.pem": bad permissions
秘密鍵を他のユーザーからもアクセスができる状態にしないでね!という内容のエラーが出ます。
自分だけがアクセスできるように権限を再度変更する必要があるようです。
$ chmod 700 ~/my-key-private.pem
700は所有者にすべての権限を与えることを意味します。
実際に権限が変わったかどうかを確認します。
lsはファイルをリスト表示するコマンドで、-lのオプションを付けると詳細も合わせて表示されます。
$ ls -l
total 24
<中略>
-rwx------@ 1 <ユーザー名> staff 1696 Nov 5 14:54 my-key-private.pem
"-rwx------" の部分は左からファイル種別(ディレクトリならd)、所有者の読み取り(r)、書き込み(w)、実行権限(x)、グループの所有者の読み取り(r)、書き込み(w)、実行権限(x)、他者の読み取り(r)、書き込み(w)、実行権限(x)の有無を表します。
2,3,4番目以外はハイフンになっているので、今回は所有者のみに読み取り、書き込み、実行権限があることが分かります。
インスタンス①にSSH接続し、秘密鍵を受け取る側でも権限を変更します。
$ ssh -i ~/my-key.pem <ユーザー>@<インスタンス①のパブリックIPアドレス>
ここにユーザー名のフォルダ(ec2-user)があるのでこちらの権限を700に変更して先程と同様に変更してみます。
[<ユーザー名>@ip-10-0-1-10 ~]$ chmod 700 ~
[<ユーザー名>@ip-10-0-1-10 ~]$ cd ..
[<ユーザー名>@ip-10-0-1-10 ~]$ ls -l
total 4
drwx------ 3 ec2-user ec2-user 4096 Nov 5 09:59 ec2-user
所有者に読み取り、書き込み、実行権限が与えられました。
ではローカル環境に戻って鍵ファイルのコピーを再度試します。
$ scp -i ~/my-key.pem ~/my-key-private.pem <ユーザー名>@<インスタンス①のパブリックIPアドレス>:~/
100% 1692 118.6KB/s 00:00
できた!
再度インスタンス①に入ってファイルの一覧を確認してみましょう。
[<ユーザー名>@ip-10-0-1-10 ~]$ ls -l
total 4
[<ユーザー名>@ip-10-0-1-10 ~]-rwx------ 1 ec2-user ec2-user 1692 Nov 6 02:34 my-key-private.pem
ちゃんとコピー出来ているようです。
ではこの先程ローカルからインスタンス①へSSH接続したときと同様にインスタンス②へ接続してみます。
[<ユーザー名>@ip-10-0-1-10 ~]$ ssh -i ~/my-key-private.pem <ユーザー>@<インスタンス②のプライベートIPアドレス>
The authenticity of host '<省略>' can't be established.
ECDSA key fingerprint is <省略>
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '<省略>' to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
[<ユーザー名>@ip-10-0-2-10 ~]$
この"10-0-2-10"の部分がインスタンス②のプライベートIPアドレスになっていますね。
これでパブリックサブネットを踏み台にしてプライベートサブネットに入れました!
この後は忘れずに鍵ファイルやフォルダの権限を400(所有者の読み込み権限のみ)に戻しておきましょう。