ssh-key EC2에서 수동 세팅하기

zdpk·2024년 7월 2일

AWS

목록 보기
1/4
post-thumbnail

EC2 Instance 생성

우선 EC2 Instance를 만든다.

이름은 vm1로, AMI(Amazon Machine Image)는 Amazon Linux로 설정했다.

최초 접속 시에 사용하기 위해 keypair를 새로 만들었다.

keypair인 이유는 public, private key가 존재하기 때문이다.

RSA, ED25519는 암호화 알고리즘이다.

모두 보안 상 뛰어나지만 호환성이 RSA가 더 좋아서 대체로 RSA가 많이 사용된다.

~/ec2-ex 경로에 다운로드 받았다.

동일한 경로에 디렉토리를 만들어도 되고, 원하는 위치에 만들어도 된다.


EC2 SSH 접속

public ip인 15.165.235.32에 ssh로 접속 해보겠다.

$ ssh -i keypair.pem ec2-user@15.165.235.32 -p 22

keypair라는 private key를 사용하여 ec2-user 사용자로 15.165.235.32 ip, port 22번으로 접속하겠다는 이야기다.

ssh는 기본적으로 22번 port를 사용하기 때문에 -p 22는 생략해도 자동으로 22번 포트를 사용한다.

ssh -i keypair.pem ec2-user@15.165.235.32 -p 22
   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'
[ec2-user@ip-172-31-14-50 ~]$ exit
logout
Connection to 15.165.235.32 closed.

기본적으로 Amazon Linux의 사용자명은 ec2-user이므로 아무런 설정을 안하면 ec2-user로 쓰면 된다.

어쨌든 AWS에서 생성된 SSH로 연결하는 것은 성공했다.

하지만 이래선 수동으로 SSH를 생성 및 등록하는 방법은 이해할 수 없다.

On-Premise 환경도 여전히 많이 있고, 언젠가 SSH Key를 직접 만들어서 사용해야 할 일이 반드시 생길 것이며 이후 살펴볼 오류도 더 쉽게 이해할 수 있기 때문에 수동 생성을 해보겠다.


암호화의 필요성

일반적으로 Client가 Server에게 요청을 보내면 Server는 Client에게 응답을 준다.

도표로 보면 이렇다.

그러나 실상은 위와 같이 간결한 구조가 아니며, Client가 보낸 요청은 Server에 도착하기 전에 수많은 Node를 거치게 된다.

실제로 google에 요청을 보내봐도 수많은 Node를 거치는 것을 볼 수 있다.

$ traceroute google.com

traceroute to google.com (142.251.42.142), 64 hops max, 40 byte packets
 1  192.168.1.1 (192.168.1.1)  6.595 ms  1.853 ms  2.075 ms
 2  * * *
 3  112.188.83.49 (112.188.83.49)  4.174 ms  4.245 ms  3.467 ms
 4  112.188.78.89 (112.188.78.89)  3.535 ms
    112.188.77.89 (112.188.77.89)  5.594 ms
    112.188.78.145 (112.188.78.145)  3.988 ms
 5  112.174.47.185 (112.174.47.185)  10.532 ms
    112.174.47.57 (112.174.47.57)  10.966 ms
    112.174.49.189 (112.174.49.189)  26.370 ms
 6  112.174.84.50 (112.174.84.50)  25.590 ms
    112.174.84.6 (112.174.84.6)  13.004 ms
    112.174.84.22 (112.174.84.22)  9.356 ms
 7  72.14.202.136 (72.14.202.136)  37.003 ms  33.978 ms
    142.250.165.78 (142.250.165.78)  32.771 ms
 8  * * *
 9  142.250.56.226 (142.250.56.226)  31.719 ms
    192.178.110.62 (192.178.110.62)  31.667 ms
    74.125.251.236 (74.125.251.236)  38.610 ms
10  108.170.236.127 (108.170.236.127)  33.989 ms
    142.250.58.93 (142.250.58.93)  36.792 ms
    142.250.229.51 (142.250.229.51)  35.245 ms
11  64.233.175.136 (64.233.175.136)  45.861 ms
    nrt12s45-in-f14.1e100.net (142.251.42.142)  37.707 ms
    209.85.244.36 (209.85.244.36)  36.418 ms

그런데 아무런 암호화 없이 이렇게 데이터를 보내면 이 Node 중 하나라도 해커가 개입하는 경우 정보가 유출된다.

고로 모든 데이터는 암호화가 필수적이다.

Client에서 secret을 가지고 암호화 한 데이터를 Server에게 보내고,

Server도 동일한 secret을 가지고 암호화 된 데이터를 복호화 하여 읽어야 한다.

그러나 Client던 Server던 secret을 처음 보낼 때는 암호화 할 수 없다는 모순이 생긴다.

고로 암호화 되지 않은 plain secret을 처음 보낼 때 털려버리면 그 뒤에 secret을 가진 해커가 암호화 된 메세지를 모두 해독하여 정보가 유출된다.

그냥 보내는 것보단 낫겠지만, 상당히 큰 헛점이 존재하게 된다.

고로 SSH는 비대칭키 암호화 방식을 채택하였다.

Server, Client가 하나의 대칭키를 갖는 구조가 아닌, Public, Private Key를 만든다.

이를 한 쌍으로 보기 때문에 Key Pair라 부른다.

Private Key는 암호화에 사용되며, Public Key는 복호화에 사용된다.

Server에서 Key Pair를 생성하여 Client에 Secret Key를 넘겨줘도 되고,

Client에서 Key Pair를 생성하여 Server에 Public Key를 넘겨줘도 된다.

어쨌든 둘이 Key Pair를 나눠 가지면 된다.

# client에서 생성한 keypair 중 public key를 server로 넘겨줌
$ ssh-copy-id -i ./secret.pub ec2-user@15.165.235.32

ssh-copy-id를 사용하면 간단하게 client에서 생성한 public key를 server로 넘겨줄 수 있지만

이를 사용하려면 password 기반 login이 활성화 되어 있어야 한다.

그러나 AWS는 기본적으로 key pair를 생성해두고 password 기반 login을 막아 두기 때문에 ssh-copy-id를 사용할 수 없다.

(물론 AWS에서 기본 발급해준 ssh key로 사용 가능하지만, 이 방법은 무시하겠다.)

고로 먼저 server에서 key pair를 만들고 private key를 client에 넘기는 방식으로 만들어 보고, 이후에 ssh-copy-id를 사용할 수 있도록 제약을 해제하여 client에서 key pair를 만들고 public key를 server에 넘기는 방식도 알아보겠다.


Server Side Key Pair 생성

먼저 Server에서 keypair를 만들어야 한다.

AWS에서 제공하는 Cloud Shell를 통해 접속해도 되고,

아까 EC2 Instance 생성할 때 다운 받았던 pem key(private key)를 사용해도 된다.

# AWS에 ssh로 접속
$ ssh -i ./keypair.pem ec2-user@15.165.235.32

이런 식으로 AWS는 EC2를 만들 때 이미 key pair를 만들어서 제공하기 때문에 사실 수동으로 만들 필요는 없다.

그래도 계속 만들어보겠다.

기본적으로 ~/.ssh 폴더 내에 key들을 등록하고 관리하기 때문에 이쪽으로 이동한 뒤 key pair를 만들겠다.

# AWS

# ~/.ssh 디렉토리로 이동
$ cd ~/.ssh

# key pair 생성
$ ssh-keygen -t rsa -b 4096 -f my-key

ssh-keygen이 바로 key pair 생성하는 명령어다.

-t는 암호화 알고리즘의 type을 나타내며, -b는 암호화 할 수의 비트 수를 일컫는다. -f는 생성한 파일명, filepath 약자인 것 같다.

-b는 암호화 할 수의 bit 수이므로 높을수록 느려지고 보안은 좋아진다.

보통 2,048, 4,096을 많이 사용한다.

4096bits512bytes이며, 우리가 알고 있는 int의 크기인 32bytes보다 15배 이상 크다.
대략 1,233자리 십진수가 나온다.

RSA 암호화에서는 임의의 1,233자리 십진수 중 소수 2개를 뽑아서 p, q라 칭하고, 이 둘의 곱을 n이라 한다.

n을 통해 지수 연산, 모듈러 연산을 반복하면 e, d가 도출되는데,(이 부분은 난해하므로 자세한 연산 과정 생략)

(n, e)가 public key, (n, d)가 private key가 된다.

그런데 실제 key를 보면 문자열로 이루어져 있는데, base64 encoding을 해서 그렇다.

실제는 매우 거대한 숫자이지만 n1234567890이라고 생각하고 Base64 Encoding하면 결과는 MTIzNDU2Nzg5MA==이 된다.

고로 Public Key, Private Key는 사실 그냥 매우 더럽게 큰 정수 + 메타 데이터라고 생각하면 된다.

어쨌든 생성된 key pair를 확인하기 위해 ls를 날려보자

$ ls

authorized_keys my-key my-key.pub

my-key, my-key.pub 두 개의 파일이 존재한다.

pub 붙은 것이 public key, my-key가 private key다.

내용을 cat으로 출력해보자.

# public key
$ cat my-key.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDK8PCPOBTeliAy56EaM46UFVP3b+SDZiPtEgBtXzLgwacZ+A
...
BrJ6Q4b7UwUKp0ppwcPeTpO1vxtEkAfdvyxo/lyvn7dZJK/I3tQf2plhPnQ== ubuntu@my-server
# private key
$ cat my-key

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAgEAyvDwjzgU3pYgMuehGjOOlBVT92/kg2Yj7RIAbV8y4MGnGfgNTNT2
K5BIlQ95xUC02cTwRx20GgdBTYnjBMgmfgxBpbE1SwC5EF0Z5TGymD1uVTlnYfQ4TjBxsl
0IWRMa6uKcqPkOAh/dbxEW0v9xpp+HwvmDD/p3AMpkbsu0oBEEb3KQGJqaqFsYYo9DQ1wG
...
oepcv/3W71OHwxv+AQjTLeCtBZwWasFczth9UIiI2hdL4ZyM3qOvnBOkgQUeHzpUwSxi5u
PG6PyYxK0HDrH/hXG4U9BjsPcKqmR/lFMJzYcQ5bFIJWZTbQJpKKVqdrZisESFm+Sug1l0
iev0RjNQgmdZJhua9DyIuPCz+nKnjFVeFMUKON3bX3TPr63sM/pd5cG50wWPPpr4uCBbr8
z+D6bJ4ypZ9VbY3CJqcPaMpor/PzjPWxEy4zgTpdYv27Sb6/SYNwh/P8AEK6MRCTDU7FQa
ZBRcCjjijiEAAAAQdWJ1bnR1QG15LXNlcnZlcgECAw==
-----END OPENSSH PRIVATE KEY-----

너무 길어서 중략했다.

이런 식으로 매우 긴 정수를 base64 인코딩으로 문자열 형태로 표현한 것이다.

(private key가 훨씬 길다.)

실제로 네트워크를 통해 public key를 보내는 일은 있지만 private key는 보내지 않는다.

authorized_keys에 public key 등록

이번에는 authorized_keys를 열어보자

$ cat authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDuxjVkn9aONS0ieIhD14LZ
...
fmTy6ZUkoTBkTkVA0DyfmsKlcA44A7Op42Hc5QZlokhbNRFEXR8e57x keypair

AWS에서 미리 만들었던 key pair의 public key가 등록되어 있다.

authorized_keys 파일에 이렇게 public key를 등록해 둬야 이 key의 pair인 private key를 가진 client가 ssh 접속을 할 수 있다.

방금 만든 key pair의 public key를 복사하여 authorized_keys 파일에 그대로 붙여넣어서 등록하자.

$ vi authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDuxjVkn9aONS0ieIhD14LZ
...
fmTy6ZUkoTBkTkVA0DyfmsKlcA44A7Op42Hc5QZlokhbNRFEXR8e57x keypair

ssh-rsa 
AAAAB3NzaC1yc2EAAAADAQABAAACAQDZo775tQaZbUbo84qDI2REfOGZ
...
xQO3/XsFbTjs5+usvqad/Y1m5XE04IurT38evjS71GfLgpHsuA
GaExIRL2PLYhKjlgQg/FVpZTfmdaZREHzhmM6P2KeOElKxHjsw== ec2-user@ip-172-31-4-174.ap-nor
theast-2.compute.internal

Client에 private key 저장

이제 server에 public key가 등록 되었으므로, 접속할 client에 private key를 저장하고 이를 통해 ssh 접속 요청을 시도하면 된다.

단순하게 터미널 2개를 열고 내용을 복사해서 client 쪽에 my-key라는 파일을 만들어서 내용을 붙여넣자.

~/ec2-ex/my-key 경로에 my-key를 만들고 AWS에서 만든 my-key 내용을 그대로 복사했다.

원하는 다른 경로에 해도 상관 없다.

# [client] my-key file
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn
...
bDd7mdUBao0AAAA4ZWMyLXVzZXJAaXAtMTcyLTMxLTQtMTc0LmFwLW5vcnRoZWFzdC0yLm
NvbXB1dGUuaW50ZXJuYWwBAgM=
-----END OPENSSH PRIVATE KEY-----

이제 이 private key로 AWS EC2에 접속하면 된다.

참고로 AWS EC2의 ip를 까먹었다면 AWS 홈페이지로 다시 돌아가기 번거롭다.

그리고 AWS가 아닌 환경에서는 직접 Linux Machine에서 IP를 확인해야 하는데, 명령어를 기억해두는 것이 좋을 것이다.

우선 hostname -i로 IP를 보는 방법이 있는데, 이건 private ip다.

AWS 내부망의 IP이기 때문에 외부 접속이 불가능하다.

$ [ec2-user@ip-172-31-4-174 .ssh]$ hostname -i
172.31.4.174

Linux에서 public ip 보기

고로 public ip를 봐야 하는데, 이를 보는 linux 명령어가 몇가지 존재한다.

$ host myip.opendns.com resolver1.opendns.com

$ nslookup myip.opendns.com resolver1.opendns.com

위 명령어 둘 중 하나를 쓰면 된다.

그런데 너무 길기 때문에 다음 명령어를 더 많이 쓴다.

$ curl ifconfig.me

$ curl ifconfig.so

둘 중 아무거나 쓰면 된다.

그럼 외부에서 접속 가능한 전세계 유일 ip인 public ip 한 개가 나오게 된다.

이제 이 ip로 접속하면 된다.

알다시피 Amazon Linux여서 기본 사용자명이 ec2-user였다.

$ ssh -i ./my-key ec2-user@15.165.235.32 -p 22

-p를 생략해도 기본적으로 ssh는 22 포트로 지정된다고 했었다.

권한 문제 해결 및 EC2 접속

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'my-key' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "my-key": bad permissions
ec2-user@15.165.235.32: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

그럼 이러한 오류가 날 것이다.

0644 권한 문제다.

private key는 보안 상, owner 아니면 권한을 가지면 안 된다.

It is required that your private key files are NOT accessible by others.

Owner는 읽기, 쓰기, 실행 다 가져도 되지만, Group, Others는 그 어떤 권한도 가져선 안 된다는 뜻이다.

ls -almy-key의 권한을 한번 보자

$ ls -al

-rw-r--r--  1 x  staff  3434 Jul  2 12:36 my-key

Owner에게 rw, Group, Others에게도 r이 있다.

아까 만든 private key가 Owner, Group, Others에게 각각 읽기 쓰기, 읽기, 읽기 권한을 준다는 것인데, Owner 한테만 읽기 쓰기 권한을 주고 Group, Others는 막아버리자.

0600으로 만들면 된다.

$ chmod 0600 my-key

$ chmod 600 my-key

0600, 600 둘 다 먹는다.

$ ls -al my-key
-rw-------  1 x  staff  3434 Jul  2 12:36 my-key

Group, Others의 권한이 지워졌다.

또는 다음과 같은 명령어도 가능하다.

$ chmod go-r my-key

go는 Group, Other의 약자고, -r은 read 권한을 빼라는 소리다.

반대로 +는 권한 더하라는 소리다.

$ chmod +x some-file

위와 같은 명령어를 가끔 보게 될텐데, 실행 권한을 추가하라는 소리다.

+ 앞에 아무도 붙지 않았으므로 ugo, User(Owner), Group Others의 실행 권한이 전부 추가된다.

이제 다시 접속해보자.

$ ssh -i ./my-key ec2-user@15.165.235.32 -p 22

   ,     #_
   ~\_  ####_        Amazon Linux 2023
  ~~  \_#####\
  ~~     \###|
  ~~       \#/ ___   https://aws.amazon.com/linux/amazon-linux-2023
   ~~       V~' '->
    ~~~         /
      ~~._.   _/
         _/ _/
       _/m/'

귀여운 비둘기가 잘 출력 되었다.

비둘기인가

어쨌든 접속에 성공했다.

ssh-add로 private key 등록

현재는 private key를 -i 옵션으로 명시하지 않으면 EC2 접속이 되지 않는다.

$ ssh ec2-user@15.165.235.32

ec2-user@13.125.27.127: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

그러나 이를 매번 수행하기는 매우 귀찮기 때문에 private key를 입력하지 않아도 자동으로 넣어주도록 설정 해보겠다.

$ ssh-add my-key

Identity added: my-key (ec2-user@ip-172-31-4-174.ap-northeast-2.compute.internal)

ssh-add로 등록하면 된다.

ssh-addssh agent에 private key를 등록하는 것인데,
ssh agentssh로 접속할 때 등록된 key들을 모두 넣어보고 일치하는 것으로 접속한다.

그래서 -i로 직접 키를 명시할 필요가 없어진다.

$ ssh ec2-user@15.165.235.32

이제 private key 명시 없이도 ssh로 잘 접속될 것이다.

0개의 댓글