Y_Yamashitaのブログ

勉強したことのアウトプット・メモが中心。記事の内容は個人の見解であり、所属組織を代表するものではありません。

ユーザーデータを使用してEC2のSSHのListenポートを変えてみる(JAWS-UG CLI専門支部 #184R EC2入門の復習)

はじめに

6/24(木)開催の「JAWS-UG CLI専門支部 #184R EC2入門」に参加した。

jawsug-cli.connpass.com

今回のハンズオンではユーザーデータを使ってWEBサーバの立ち上げを実施した。自分はユーザーデータを使ったのは初めてだったので、復習がてら、何かオリジナルのユーザーデータを使ってみようと思う。
といっても大層なものは思い浮かばなかったしサクッと試したかったので、タイトル通り、SSHのListenポートを変えてみることにした。

前提

今回は以下の前提で作業を実施する。

  • VPCは作成済みのデフォルトVPCを使用する
  • EC2はAmazon Linux2を使用する
  • EC2インスタンスの作成、起動はCloud9から実施する

手順1. Cloud9への権限付与

Cloud9でEC2インスタンスの起動を実施するため、Cloud9用のIAMロールを作成し、"AmazonEC2FullAccess"権限を付与する。権限の付与はCloudShellで実施する。権限付与の流れはこちらの記事を参照。

手順2. ユーザーデータの作成

今回使うユーザーデータ

今回は、Amazon Linux2でSSHのListenポートを変更するスクリプトをユーザーデータとして用意した。

#!/bin/bash

sed -i.old -e 's/#Port 22/Port 51512/g' /etc/ssh/sshd_config
systemctl restart sshd

スクリプトと呼ぶのが憚られる簡便さだが、とりあえずユーザーデータを使った設定を試してみたいだけなのでよしとしよう。
なお、ユーザーデータはroot権限で実施されるので、sudoコマンドを使わないことに注意する。
また、Amazon Linux2では動作したが、他のディストリビューションで動くかどうかは不明。(SELinuxが有効かどうかでも変わると思うし、sshdコンフィグのパスが違う可能性もあるため)

ユーザーデータの格納

Cloud9上に上記のスクリプトを準備する。

[ec2-user@ip-10-0-0-127%]$ DIR_USER_DATA="${HOME}/environment/conf-handson-cli-ec2"
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ ls -d ${HOME}/environment/conf-handson-cli-ec2
ls: cannot access /home/ec2-user/environment/conf-handson-cli-ec2: No such file or directory
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ ls -d ${DIR_USER_DATA}
ls: cannot access /home/ec2-user/environment/conf-handson-cli-ec2: No such file or directory
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ mkdir -p ${HOME}/environment/conf-handson-cli-ec2
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ USER_DATA_NAME='ec2-ssh-port-change'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ FILE_USER_DATA="${DIR_USER_DATA}/${USER_DATA_NAME}.bash" \
>   && echo ${FILE_USER_DATA}
/home/ec2-user/environment/conf-handson-cli-ec2/ec2-ssh-port-change.bash
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ cat << EOF > ${FILE_USER_DATA}
> #!/bin/bash
> 
> sed -i.old -e 's/#Port 22/Port 51512/g' /etc/ssh/sshd_config
> 
> systemctl restart sshd
> 
> EOF
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ cat ${FILE_USER_DATA}
#!/bin/bash

sed -i.old -e 's/#Port 22/Port 51512/g' /etc/ssh/sshd_config

systemctl restart sshd

[ec2-user@ip-10-0-0-127%]$ ls ${FILE_USER_DATA}
/home/ec2-user/environment/conf-handson-cli-ec2/ec2-ssh-port-change.bash
[ec2-user@ip-10-0-0-127%]$ 

EC2インスタンスの起動

キーペアの作成

EC2インスタンスSSH接続するために、キーペアを作成する。

[ec2-user@ip-10-0-0-127%]$ aws ec2 create-key-pair --key-name SampleKeyPair \
> --query 'KeyMaterial' \
> --output text > SampleKeyPair.pem
[ec2-user@ip-10-0-0-127%]$

--query 'KeyMaterial'は「暗号化されていないPEMエンコードされたRSA秘密鍵」の指定になる模様。
ちゃんと作成されているか確認してみる。

[ec2-user@ip-10-0-0-127%]$ aws ec2 describe-key-pairs --key-name SampleKeyPair
{
    "KeyPairs": [
        {
            "KeyPairId": "key-0d1de70fb6fa94734",
            "KeyFingerprint": "6e:ff:0b:0a:9c:02:81:86:92:fe:0b:6c:18:13:80:bf:85:49:c6:d1",
            "KeyName": "SampleKeyPair",
            "Tags": []
        }
    ]
}
[ec2-user@ip-10-0-0-127%]$

問題なく作成されていた。作成された秘密鍵は、ローカルにダウンロードしておく。

EC2インスタンスの起動

いよいよEC2インスタンスを起動する。今回は以下のコマンド、オプションでEC2を起動する。

コマンド 内容
aws ec2 run-instances EC2インスタンスを起動する
--image-id <イメージID> インスタンスのイメージIDを指定する
--instance-type <インスタンスタイプ> インスタンスタイプを指定する
--tag-specifications <タグキー、値> タグキーと値を指定する
--user-data <ファイルパス> ユーザーデータのファイルパスを指定する
--associate-public-ip-address パブリックIPアドレスの割当を行う
--key-name <キーペア名> キーペアを指定する

上記の実行のために、変数を準備する。

[ec2-user@ip-10-0-0-127%]$ EC2_INSTANCE_IMAGE_NAME="amzn2-ami-hvm-2.0.20210525.0-x86_64-gp2"
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_INSTANCE_TYPE="t2.micro"
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_INSTANCE_IMAGE_ID=$( \
>   aws ec2 describe-images \
>     --filters Name=name,Values="${EC2_INSTANCE_IMAGE_NAME}" \
>     --query 'Images[].ImageId' \
>     --output text \
> ) \
>   && echo ${EC2_INSTANCE_IMAGE_ID}
ami-001f026eaf69770b4
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_INSTANCE_TAG_NAME='handson-cli-ec2-userdata_public_ip_address_default_vpc-instance'
[ec2-user@ip-10-0-0-127%]$ EC2_TAG_KEY='Name'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ STRING_TAG_CONF="ResourceType=instance,Tags=[{Key=${EC2_TAG_KEY},Value=${EC2_INSTANCE_TAG_NAME}}]" \
>   && echo ${STRING_TAG_CONF}
ResourceType=instance,Tags=[{Key=Name,Value=handson-cli-ec2-userdata_public_ip_address_default_vpc-instance}]
[ec2-user@ip-10-0-0-127%]$ 

変数の設定が完了したので、実際にEC2インスタンスを起動する。

[ec2-user@ip-10-0-0-127%]$ aws ec2 run-instances \
>   --image-id ${EC2_INSTANCE_IMAGE_ID} \
>   --instance-type ${EC2_INSTANCE_TYPE} \
>   --tag-specifications ${STRING_TAG_CONF} \
>   --user-data file://${FILE_USER_DATA} \
>   --associate-public-ip-address \
>   --key-name SampleKeyPair
{
    "Groups": [],
    "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-001f026eaf69770b4",
            "InstanceId": "i-04e7cc3f33fe110c4",
            "InstanceType": "t2.micro",
            "KeyName": "SampleKeyPair",

-------------- 中略 --------------
    ],
    "OwnerId": "XXXXXXXXXXXX",
    "ReservationId": "r-048e604b224cb5961"
}
[ec2-user@ip-10-0-0-127%]$

コマンドが成功すると、EC2の情報が記述されたJSONが出力される。

セキュリティグループの更新

次に、デフォルトのセキュリティグループを更新し、ユーザーデータで指定したListenポートを許可するようにする。インバウンドルールを更新する際はaws ec2 authorize-security-group-ingressコマンドを実施する。

コマンド 内容
aws ec2 authorize-security-group-ingress インバウンドのセキュリティグループを更新する
--group-name <グループ名> セキュリティグループ名を指定する
--protocol <プロトコル> プロトコルを指定する
--port <ポート番号> ポート番号を指定する
--cidr <CIDRブロック> CIDRブロックを指定する

実際にコマンドを実行する。

[ec2-user@ip-10-0-0-127%]$ EC2_SECURITY_GROUP_NAME='default'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_SECURITY_GROUP_PROTOCOL='tcp'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_SECURITY_GROUP_PORT='51512'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ EC2_SECURITY_GROUP_CIDR='0.0.0.0/0'
[ec2-user@ip-10-0-0-127%]$ 
[ec2-user@ip-10-0-0-127%]$ aws ec2 authorize-security-group-ingress \
>   --group-name ${EC2_SECURITY_GROUP_NAME} \
>   --protocol ${EC2_SECURITY_GROUP_PROTOCOL} \
>   --port ${EC2_SECURITY_GROUP_PORT} \
>   --cidr ${EC2_SECURITY_GROUP_CIDR}
[ec2-user@ip-10-0-0-127%]$

アクセス確認

EC2が立ち上がり、セキュリティグループも更新されたので、変更後のポート指定でSSH出来るか試してみる。
今回は、TeraTermを使用してSSHログインを試行する。

EC2インスタンスグローバルIPアドレスの確認

まずはアクセスするために、EC2インスタンスグローバルIPアドレスを確認する。

[ec2-user@ip-10-0-0-127%]$ EC2_IP_PUBLIC=$( \
>   aws ec2 describe-instances \
>     --filters Name=tag-key,Values=Name \
>               Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
>     --instance-ids ${ARRAY_EC2_INSTANCE_IDS} \
>     --query "Reservations[].Instances[].PublicIpAddress" \
>     --output text \
> ) \
>   && echo ${EC2_IP_PUBLIC}
54.248.6.20
[ec2-user@ip-10-0-0-127%]$

TeraTermによるアクセス試行

続いてTeraTermでアクセスを試す。 f:id:YuY_83:20210628030036p:plain f:id:YuY_83:20210628030230p:plain

サーバがTeraTermのknownhostsリストに未登録のため警告が出るが、問題ないので続行する。この時点で接続自体は出来ている。
あとは、事前にダウンロードした秘密鍵を使ってログインする。 f:id:YuY_83:20210628030638p:plain f:id:YuY_83:20210628031017p:plain

問題なくログインできたので、sshdコンフィグの内容が書き換わっているか確認してみる。ついでにポートのListen状況も確認する。

[ec2-user@ip-172-31-45-52 ~]$ sudo cat /etc/ssh/sshd_config | grep Port
Port 51512
#GatewayPorts no
[ec2-user@ip-172-31-45-52 ~]$ 
[ec2-user@ip-172-31-45-52 ~]$ 
[ec2-user@ip-172-31-45-52 ~]$ netstat -alt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:smtp          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:51512           0.0.0.0:*               LISTEN     
tcp        0    252 ip-172-31-45-52.a:51512 dynamic-xxx-xxx-xxx:51280 ESTABLISHED
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN     
tcp6       0      0 [::]:51512              [::]:*                  LISTEN     
[ec2-user@ip-172-31-45-52 ~]$ 
[ec2-user@ip-172-31-45-52 ~]$ 

問題なさそう。あとは、このEC2インスタンスのプライベートIPアドレスが合っているかどうかも、念のためCloud9上で再確認する。

[ec2-user@ip-10-0-0-127%]$ aws ec2 describe-instances \
>     --filters Name=tag-key,Values=Name \
>               Name=tag-value,Values=${EC2_INSTANCE_TAG_NAME} \
>     --instance-ids i-04e7cc3f33fe110c4 \
>     --query "Reservations[].Instances[].PrivateIpAddress" \
>     --output text
172.31.45.52
[ec2-user@ip-10-0-0-127%]$ 

こちらも想定通りだった。満足したので、後片付けをする。今回作成したEC2インスタンスやキーペアは全て削除し、デフォルトVPCからセキュリティグループをデタッチし、Cloud9のIAMロールから"AmazonEC2FullAccess"をデタッチする。(手順は割愛)

おわりに

今回は最低限のスクリプトを使って、ユーザーデータによる設定変更の確認が出来た。機会があれば、もう少し複雑な処理も試してみたいと思う。