제 목 :
SSH Keygen으로 키 만들어서 호스트 접속하기

오늘 아침 서버에 키를 하나 새로 만들어 넣으려는데 ssh-keygen 옵션이 하나도 기억나지 않았다. 검색해 보니 명령어만 툭 던져 놓은 글, 개념만 길게 설명한 글, 몇 년 전 기준으로 쓴 글이 섞여 있어서 한 번에 정리된 곳이 없었다. 그래서 다음의 나를 위해 한 번에 정리해 둔다.
순서는 이렇다.
- 비대칭 키가 뭔지
- 왜 SSH 키를 만드는지, 그리고 접속할 때 실제로 무슨 일이 일어나는지
- 가장 간단하게 키 만들기
- 키 종류를 골라서 만들기
- AWS의
.pem키는 정체가 뭔지 - 접속이 안 될 때 트러블슈팅
1. 비대칭 키란?
암호화 방식은 크게 두 가지다.
- 대칭 키: 잠글 때와 열 때 같은 키를 쓴다. 빠르지만, 그 키를 상대에게 어떻게 안전하게 전달하느냐가 문제다.
- 비대칭 키: 서로 다른 두 개의 키가 한 쌍으로 묶여 있다. 하나는 공개 키(public key), 하나는 **개인 키(private key)**다.
비대칭 키의 핵심 규칙은 단 하나다.
한쪽 키로 처리한 것은 짝이 되는 다른 키로만 풀거나 확인할 수 있다.
이 규칙을 두 가지 방향으로 쓴다.

- 공개 키는 이름 그대로 공개해도 된다. 서버에 올려 두고, 깃허브에 등록하고, 동료에게 보내도 된다.
- 개인 키는 절대로 내 컴퓨터 밖으로 나가면 안 된다. 개인 키를 가진 사람이 곧 “나”다.
SSH 로그인에서 쓰는 건 ②번, 서명 쪽이다. “나는 이 공개 키의 짝인 개인 키를 갖고 있다”를 개인 키를 직접 보내지 않고 증명하는 것이다. 자물쇠(공개 키)는 서버 문에 걸어 두고, 열쇠(개인 키)는 내 주머니에만 있다고 생각하면 편하다.
2. ssh-keygen으로 키를 만드는 이유
비밀번호 대신 키로 로그인하기
SSH는 원격 서버의 터미널에 접속하는 프로토콜이다. 비밀번호로도 접속할 수 있지만 문제가 많다.
- 비밀번호는 매번 네트워크를 타고 서버로 전달된다(암호화된 채널 안이긴 하지만).
- 사람이 외울 수 있는 길이라 무차별 대입 공격에 약하다. 22번 포트를 열어 두면 하루에도 수천 번씩 로그인 시도가 들어온다.
- 스크립트나 CI에서 자동으로 접속하기 불편하다.
키로 로그인하면 개인 키는 내 컴퓨터를 떠나지 않고, 수천 비트짜리 키를 대입으로 맞추는 건 사실상 불가능하다. 그래서 ssh-keygen으로 키 쌍을 만들고, 공개 키를 서버에 등록하는 것이다.
authorized_keys: 서버의 출입 명단
서버는 “이 공개 키들의 주인은 들어와도 된다”는 명단을 사용자 홈 디렉토리의 아래 파일에 보관한다.
~/.ssh/authorized_keys파일 내용은 그냥 공개 키를 한 줄에 하나씩 적어 둔 텍스트다.
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... test@macbookssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... thereis@nasdeploy 계정으로 접속하고 싶다면 /home/deploy/.ssh/authorized_keys에 내 공개 키가 있어야 한다. 계정마다 명단이 따로라는 점을 기억해 두자.
키로 접속하는 과정
ssh deploy@server를 치면 실제로는 아래 과정이 진행된다.
정리하면 SSH 접속에는 키가 두 번 등장한다.
| 단계 | 누가 누구를 확인하나 | 쓰이는 파일 |
|---|---|---|
| 호스트 인증 (2~3번) | 클라이언트가 서버를 확인 (“내가 접속하려던 그 서버 맞아?”) | 클라이언트의 ~/.ssh/known_hosts |
| 사용자 인증 (6~10번) | 서버가 클라이언트를 확인 (“너 들어와도 되는 사람 맞아?”) | 서버의 ~/.ssh/authorized_keys |
어느 쪽에서도 개인 키 자체는 네트워크로 나가지 않는다. 오가는 건 공개 키와 서명뿐이다.
3. ssh-keygen으로 간단하게 키 만들기
일단 만들기
아무 옵션 없이 실행하면 된다.
ssh-keygenGenerating public/private ed25519 key pair.Enter file in which to save the key (/Users/test/.ssh/id_ed25519):Enter passphrase for "/Users/test/.ssh/id_ed25519" (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /Users/testjuhn/.ssh/id_ed25519Your public key has been saved in /Users/testjuhn/.ssh/id_ed25519.pub질문은 두 개다.
- 저장 위치: 엔터를 치면 기본 위치(
~/.ssh/id_<종류>)에 저장된다. 이미 같은 이름의 키가 있으면 덮어쓸지 묻는데, 여기서y를 치면 기존 키는 사라진다. 조심하자. - 패스프레이즈(passphrase): 개인 키 파일 자체를 잠그는 비밀번호다. 노트북을 잃어버려도 키 파일만으로는 쓸 수 없게 해 준다. 개인용 키라면 걸어 두는 걸 추천하고, CI처럼 사람이 입력할 수 없는 곳에서 쓸 키라면 비워 둔다.
결과물은 두 개의 파일이다.
| 파일 | 정체 | 어디에 두나 |
|---|---|---|
id_ed25519 |
개인 키 | 내 컴퓨터에만. 권한 600 |
id_ed25519.pub |
공개 키 | 서버의 authorized_keys, 깃허브 등 |
참고: OpenSSH 9.5부터 기본 키 종류가 RSA에서 Ed25519로 바뀌었다. 예전 글에서
id_rsa가 생긴다고 설명하는 건 그 이전 버전 기준이다. 내 버전은ssh -V로 확인할 수 있다.
자주 쓰는 옵션을 붙여서 만들기
키가 여러 개가 되면 이름과 메모를 붙여 두는 게 좋다.
ssh-keygen -t ed25519 -C "test@macbook-nas" -f ~/.ssh/nas_ed25519| 옵션 | 의미 |
|---|---|
-t |
키 종류 (ed25519, rsa, ecdsa …) |
-b |
키 길이(비트). RSA, ECDSA에서만 의미 있음 |
-C |
주석(comment). 공개 키 맨 끝에 붙어서 “이게 누구 키였지?“를 알려 준다 |
-f |
저장할 파일 경로 |
-N |
패스프레이즈를 명령어에서 바로 지정 (-N ""이면 패스프레이즈 없음) |
서버에 공개 키 등록하기
가장 편한 건 ssh-copy-id다. 아직은 비밀번호로 접속이 되는 상태여야 한다.
ssh-copy-id -i ~/.ssh/nas_ed25519.pub deploy@192.168.0.10이 명령어가 서버의 ~/.ssh 폴더 만들기, authorized_keys에 공개 키 추가하기, 권한 맞추기까지 다 해 준다. ssh-copy-id가 없는 환경이라면 직접 넣어도 된다.
cat ~/.ssh/nas_ed25519.pub | ssh deploy@192.168.0.10 \ "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"이제 키로 접속해 본다.
ssh -i ~/.ssh/nas_ed25519 deploy@192.168.0.10알아 두면 좋은 부가 명령어
# 개인 키에서 공개 키 다시 뽑아내기 (.pub 파일을 잃어버렸을 때)ssh-keygen -y -f ~/.ssh/nas_ed25519 > ~/.ssh/nas_ed25519.pub
# 키의 지문(fingerprint) 확인하기ssh-keygen -lf ~/.ssh/nas_ed25519.pub
# 패스프레이즈 바꾸기 (없던 패스프레이즈 추가도 이걸로)ssh-keygen -p -f ~/.ssh/nas_ed25519
# 서버를 재설치해서 호스트 키가 바뀌었을 때, known_hosts에서 옛 기록 지우기ssh-keygen -R 192.168.0.104. ssh-keygen으로 만들 수 있는 키의 종류
-t 옵션으로 고를 수 있는 키 종류는 이렇다.
종류 (-t) |
키 길이 (-b) |
특징 | 추천 |
|---|---|---|---|
ed25519 |
고정 (256비트) | 짧고 빠르고 안전하다. 현재 기본값 | ✅ 기본으로 이것 |
rsa |
기본 3072, 4096 권장 | 가장 오래되고 호환성이 가장 좋다. 키가 길다 | 오래된 장비, 일부 클라우드 |
ecdsa |
256 / 384 / 521 | 타원 곡선 방식. 일부 환경에서 요구 | 특별한 이유가 있을 때만 |
ed25519-sk |
고정 | YubiKey 같은 FIDO 보안 키에 개인 키가 묶인다 | 하드웨어 키가 있다면 |
ecdsa-sk |
고정 | 위와 같지만 ECDSA. Ed25519를 지원하지 않는 보안 키용 | 보안 키가 Ed25519 미지원일 때 |
dsa |
1024 고정 | 취약해서 OpenSSH 10.0에서 지원이 완전히 제거됐다 | ❌ 쓰지 말 것 |
종류를 지정해서 만들기
# Ed25519 (가장 무난)ssh-keygen -t ed25519 -C "test@macbook"
# RSA 4096비트 (오래된 서버나 장비와 호환이 필요할 때)ssh-keygen -t rsa -b 4096 -C "test@macbook"
# ECDSA 521비트 (주의: 512가 아니라 521이다)ssh-keygen -t ecdsa -b 521 -C "test@macbook"
# FIDO 보안 키(YubiKey 등)에 묶인 키. 접속할 때마다 키를 터치해야 한다ssh-keygen -t ed25519-sk -C "test@yubikey"고민될 때는 그냥 ed25519를 쓰고, 상대 쪽에서 “그 키 종류는 지원 안 해요”라고 할 때만 rsa -b 4096으로 내려가면 된다.
5. AWS의 pem 키에 대하여
AWS EC2 인스턴스를 만들 때 **키 페어(Key pair)**를 고르거나 새로 만들라고 한다. 새로 만들면 my-key.pem 같은 파일을 딱 한 번 내려받게 해 준다. 이 파일의 정체를 알면 헷갈릴 게 없다.
pem 파일 = 개인 키
.pem은 특별한 무언가가 아니라 AWS가 대신 만들어 준 개인 키다. PEM은 키를 -----BEGIN ... PRIVATE KEY-----로 시작하는 텍스트로 저장하는 형식 이름일 뿐이다.
그러니까 AWS에서 키 페어를 만들면 이런 일이 일어난다.
결국 우리가 앞에서 ssh-keygen + ssh-copy-id로 한 일을 AWS가 대신 해 준 것뿐이다. 그래서 접속도 똑같다.
chmod 400 my-key.pemssh -i my-key.pem ec2-user@3.35.xxx.xxx기본 사용자 이름은 AMI마다 다르다.
| AMI | 기본 사용자 |
|---|---|
| Amazon Linux | ec2-user |
| Ubuntu | ubuntu |
| Debian | admin |
| RHEL | ec2-user |
pem 키 관련해서 알아 두면 좋은 것
-
AWS는 개인 키를 다시 주지 않는다. pem 파일을 잃어버리면 다시 받을 방법이 없다. EC2 Instance Connect나 Systems Manager(SSM)로 들어가서
authorized_keys에 새 공개 키를 넣는 식으로 복구해야 한다. -
pem에서 공개 키를 뽑을 수 있다. 다른 서버에도 같은 키로 들어가고 싶다면 이렇게 하면 된다.
터미널 ssh-keygen -y -f my-key.pem > my-key.pub -
내가 만든 키를 AWS에 올릴 수도 있다. EC2 콘솔의 Key pairs → Import key pair에
ssh-keygen으로 만든.pub내용을 붙여 넣으면 된다. 개인 키를 AWS가 한 번도 만지지 않으니 이쪽이 더 깔끔하다. -
.ppk는 PuTTY용 형식이다. 윈도우에서 PuTTY를 쓸 때나 필요하고, 맥이나 리눅스에서는.pem을 고르면 된다. -
키 페어를 만들 때 RSA와 ED25519 중에 고를 수 있는데, 윈도우 인스턴스는 ED25519를 지원하지 않는다. 리눅스 인스턴스라면 ED25519를 고르면 된다.
6. 원격 호스트 접속 시 트러블슈팅
키를 다 만들고 등록까지 했는데 Permission denied (publickey)가 뜨면 일단 이것부터 친다.
ssh -v deploy@192.168.0.10 # 더 자세히 보려면 -vvv클라이언트가 어떤 설정을 읽었는지, 어떤 키를 시도했는지, 서버가 뭐라고 답했는지가 다 나온다. 서버에 다른 경로로 들어갈 수 있다면 서버 로그도 같이 보면 원인이 바로 나온다.
# Ubuntu / Debiansudo tail -f /var/log/auth.log# 또는 (systemd 환경)sudo journalctl -u ssh -f # RHEL 계열은 -u sshd6-1. ssh_config 설정 이슈
SSH 설정 파일은 두 종류가 있는데 이름이 비슷해서 헷갈린다.
| 파일 | 쪽 | 역할 |
|---|---|---|
~/.ssh/config, /etc/ssh/ssh_config |
클라이언트 | 내가 접속할 때 쓸 옵션 |
/etc/ssh/sshd_config |
서버 (d = daemon) |
서버가 접속을 받을 때 쓸 규칙 |
클라이언트: ~/.ssh/config
매번 -i, -p, 사용자 이름을 치기 귀찮으니 보통 이렇게 정리해 둔다.
Host nas HostName 192.168.0.10 User deploy Port 2222 IdentityFile ~/.ssh/nas_ed25519 IdentitiesOnly yes
Host aws-web HostName 3.35.xxx.xxx User ec2-user IdentityFile ~/.ssh/my-key.pem IdentitiesOnly yes
Host * ServerAliveInterval 60이제 ssh nas만 치면 된다. 여기서 자주 밟는 함정은 이렇다.
① Too many authentication failures
키가 여러 개 있으면 ssh는 IdentityFile로 지정한 키 말고도 ssh-agent에 들어 있는 키들을 하나씩 다 시도한다. 서버는 보통 시도 횟수를 6번(MaxAuthTries)으로 제한하기 때문에, 맞는 키를 내밀기 전에 쫓겨난다. **IdentitiesOnly yes**를 넣으면 지정한 키만 쓴다.
② 먼저 적힌 설정이 이긴다
ssh_config는 같은 옵션이 여러 번 나오면 처음 나온 값을 쓴다. 그래서 맨 위에 Host *로 User root 같은 걸 적어 두면, 아래의 Host nas에 적은 User deploy가 무시된다. 공통 설정인 Host *는 항상 맨 아래에 둔다.
헷갈릴 때는 실제로 적용될 최종 설정을 출력해 보면 된다.
ssh -G nas | grep -Ei '^(user|hostname|port|identityfile)'③ config 파일 권한
~/.ssh/config를 다른 사용자가 쓸 수 있는 권한이면 Bad owner or permissions on ~/.ssh/config 오류를 내고 아예 접속을 시도하지 않는다.
chmod 600 ~/.ssh/config서버: /etc/ssh/sshd_config
키는 맞는데도 안 되면 서버 설정을 의심한다.
PubkeyAuthentication yes # 키 로그인 허용 (기본값 yes)AuthorizedKeysFile .ssh/authorized_keys # 공개 키 명단 위치PasswordAuthentication no # 키 등록이 끝났으면 비밀번호 로그인은 막자PermitRootLogin prohibit-password # root는 키로만 (아예 막으려면 no)여기서 정말 많이 당하는 함정이 하나 있다. sshd_config를 고쳤는데 반영이 안 되는 경우다. 요즘 배포판은 sshd_config 맨 위에 이런 줄이 있다.
Include /etc/ssh/sshd_config.d/*.confsshd_config도 처음 나온 값이 이기기 때문에, sshd_config.d/ 안의 파일(예: 클라우드 이미지의 50-cloud-init.conf)에 PasswordAuthentication yes가 들어 있으면 본문에서 no로 바꿔도 소용이 없다. 실제로 적용된 값은 이렇게 확인한다.
sudo sshd -T | grep -Ei 'passwordauthentication|pubkeyauthentication|authorizedkeysfile'설정을 고친 뒤에는 문법 검사 → 재시작 순서를 지킨다. 문법이 틀린 채로 재시작하면 sshd가 안 떠서 서버에 다시 못 들어갈 수 있다. 재시작할 때 지금 접속한 세션은 끊지 말고, 새 터미널에서 접속이 되는지 확인한 뒤에 닫자.
sudo sshd -t && sudo systemctl restart ssh # RHEL 계열은 sshd6-2. authorized_keys의 777 권한 이슈
“권한 때문에 안 되나?” 싶어서 chmod 777을 날리는 순간 오히려 영영 안 된다. 이게 가장 억울한 케이스다.
sshd에는 StrictModes라는 옵션이 기본으로 켜져 있다. authorized_keys 파일, ~/.ssh 폴더, 홈 디렉토리 중 하나라도 다른 사람이 쓸 수 있는 권한이면 그 명단을 믿지 않는다. 누군가 그 파일에 몰래 자기 공개 키를 끼워 넣을 수 있다는 뜻이기 때문이다.
그래서 777로 열면 클라이언트에서는 그냥 Permission denied (publickey)만 보이고, 서버 로그에는 이런 줄이 남는다.
Authentication refused: bad ownership or modes for file /home/deploy/.ssh/authorized_keys해결은 권한을 좁히는 것이다.
chmod 755 ~ # 또는 750. 핵심은 그룹/기타 사용자의 쓰기 권한 제거 (chmod go-w ~)chmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keyschown -R deploy:deploy ~/.ssh # sudo로 파일을 만들었다면 소유자가 root로 되어 있을 수 있다서버와 클라이언트에서 맞춰야 할 권한을 한 번에 정리하면 이렇다.
| 위치 | 대상 | 권한 | 틀렸을 때 |
|---|---|---|---|
| 서버 | 홈 디렉토리 ~ |
755 이하 (그룹/기타 쓰기 금지) |
서버 로그에 bad ownership or modes |
| 서버 | ~/.ssh |
700 |
〃 |
| 서버 | ~/.ssh/authorized_keys |
600 |
〃 |
| 클라이언트 | ~/.ssh |
700 |
|
| 클라이언트 | 개인 키 (id_ed25519, *.pem) |
600 또는 400 |
UNPROTECTED PRIVATE KEY FILE! |
| 클라이언트 | 공개 키 (*.pub) |
644 |
|
| 클라이언트 | ~/.ssh/config |
600 |
Bad owner or permissions |
클라이언트 쪽 개인 키도 같은 이유로 검사한다. 내려받은 pem 파일은 보통 644라서 처음 접속할 때 거의 반드시 이 경고를 보게 된다.
WARNING: UNPROTECTED PRIVATE KEY FILE!Permissions 0644 for 'my-key.pem' are too open.This private key will be ignored.chmod 400 my-key.pem권한을 다 맞췄는데도 RHEL / Rocky / CentOS 계열에서 안 된다면 SELinux 라벨 문제일 수 있다. 직접 만든
.ssh폴더라면restorecon -Rv ~/.ssh로 라벨을 되돌려 보자.
마치며
다시 까먹었을 때 이 부분만 보면 된다.
# 1. 키 만들기ssh-keygen -t ed25519 -C "나@기기" -f ~/.ssh/서버이름_ed25519
# 2. 서버에 공개 키 등록ssh-copy-id -i ~/.ssh/서버이름_ed25519.pub 사용자@서버
# 3. 접속ssh -i ~/.ssh/서버이름_ed25519 사용자@서버
# 안 되면ssh -v 사용자@서버 # 클라이언트 쪽 상황sudo tail -f /var/log/auth.log # 서버 쪽 상황chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys # 777은 절대 금지- 공개 키는 자물쇠, 개인 키는 열쇠. 자물쇠는 서버의
authorized_keys에 걸고, 열쇠는 내 주머니에만. - AWS의
.pem은 AWS가 대신 만들어 준 개인 키일 뿐이다. - 권한 문제는 넓히는 게 아니라 좁혀서 푼다.
아휴 이제 SSH 키 관련해서 5년은 정리 안해도 되겠지. 그럼 안녕!

꼬리말을 불러오는 중...