서버·SSH

SSH 키 인증 설정하는 법, 접속 거부까지 잡는 실전 순서

SSH 키 인증 설정하는 법, 접속 거부까지 잡는 실전 순서

비밀번호로는 잘 들어가지는 서버에 키를 등록했는데 Permission denied (publickey). 만 뜨거나, 반대로 키를 넣었는데도 계속 비밀번호를 묻는 상황. SSH 키 인증에서 막히는 지점은 대부분 정해져 있습니다. 키를 잘못 만든 경우보다 위치와 권한, 그리고 sshd 설정이 다른 파일에서 덮어써지는 문제가 압도적으로 많습니다.

아래는 키 생성부터 비밀번호 로그인 차단, 그리고 안 될 때 로그를 읽는 순서까지 실제로 치는 명령어 그대로 정리한 것입니다.

먼저 정리하고 시작합니다: 키 인증은 어디에 뭐가 들어가는가

구조는 한 줄로 끝납니다. 개인키는 내 PC의 ~/.ssh/id_ed25519, 공개키는 서버의 ~/.ssh/authorized_keys 에 들어갑니다. 개인키는 절대 서버로 올라가지 않습니다.

여기서 가장 흔한 착각이 키를 서버에서 만드는 것입니다. 서버에 SSH로 들어가서 ssh-keygen을 돌리고 “키를 만들었는데 왜 접속이 안 되죠”라고 하는 경우가 꽤 있습니다. 키 쌍은 접속하는 쪽(내 노트북, 내 PC) 에서 만듭니다. 서버에서 만든 키는 그 서버가 또 다른 서버로 나갈 때 쓰는 키입니다.

⚠️ 작업 중에는 지금 열려 있는 비밀번호 세션을 절대 닫지 마세요.

sshd 설정을 잘못 건드리면 다시 못 들어갑니다. 반드시 새 터미널 창을 열어 키 접속이 되는 걸 확인한 뒤에, 그때 원래 창을 닫습니다. 콘솔 접근이 없는 VPS라면 이 순서를 어기는 순간 복구가 상당히 번거로워집니다.

시작 전에 하나 정해두면 좋습니다. root로 직접 붙을지, 일반 사용자로 붙고 sudo를 쓸지입니다. 이후 PermitRootLogin 설정이 여기에 달려 있습니다. 서버를 여러 명이 만진다면 사용자별 계정 + sudo 쪽이 로그 추적에 유리합니다.

1단계: 로컬에서 키 쌍 만들기 (ssh-keygen)

내 PC 터미널에서 실행합니다.

ssh-keygen -t ed25519 -C "hong@macbook-2024"

프롬프트가 세 번 뜹니다.

프롬프트무엇을 입력하나
Enter file in which to save the key그냥 엔터 → ~/.ssh/id_ed25519 생성. 이미 같은 이름 키가 있으면 덮어쓰기 경고가 뜨니 주의
Enter passphrase개인키 자체를 잠그는 암호. 비워도 되지만 노트북 분실 대비면 거는 쪽을 권합니다
Enter same passphrase again위와 동일하게 한 번 더

-C는 주석입니다. 공개키 맨 끝에 그대로 붙어서 authorized_keys에 남기 때문에, 나중에 “이게 누구 키였지” 할 때 이거 하나로 판별합니다. 이메일이든 노트북-회사 든 알아볼 수 있게 넣으세요.

키 쌍 만들기
키 쌍 만들기

ed25519가 안 받아질 때는 rsa 4096

오래된 서버나 일부 웹호스팅 관리 패널에서 ed25519 키를 등록 폼에서 거부하는 경우가 있습니다. 그럴 때만 rsa로 만듭니다.

ssh-keygen -t rsa -b 4096 -C "hong@macbook-2024"

서버별로 키 파일 분리하기

키 하나를 모든 서버에 돌려쓰면 회수할 때 곤란해집니다. -f로 파일명을 지정합니다.

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_myserver -C "hong@macbook-2024"

패스프레이즈를 매번 안 묻게 하기

ssh-agent에 한 번 올려두면 세션 동안 다시 묻지 않습니다.

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

macOS는 키체인에 저장해두면 재부팅 후에도 유지됩니다.

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Windows는 PowerShell 기본 OpenSSH 클라이언트로 위 명령이 그대로 동작합니다. 경로만 C:\Users\사용자명\.ssh 로 바뀝니다. ssh-agent 서비스가 꺼져 있을 수 있는데, 그때는 서비스 앱에서 OpenSSH Authentication Agent를 자동 시작으로 바꿔주면 됩니다.

2단계: 서버에 공개키 등록하기

가장 쉬운 방법: ssh-copy-id

macOS/리눅스라면 이거 한 줄로 끝납니다. 비밀번호를 한 번 묻고, 권한까지 알아서 맞춰줍니다.

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@서버IP

SSH 포트를 바꿔 쓰고 있다면 -p를 붙입니다.

ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 user@서버IP

ssh-copy-id가 없을 때 수동 등록

Windows에는 ssh-copy-id가 없습니다. 원라이너로 처리합니다.

cat ~/.ssh/id_ed25519.pub | ssh user@호스트 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

>> 를 > 로 잘못 쓰면 기존에 등록된 다른 키가 전부 날아갑니다. 이미 다른 사람 키가 들어 있는 서버라면 특히 주의하세요.

복붙할 때 줄바꿈이 들어가면 무조건 실패합니다

메모장이나 채팅창을 거쳐 공개키를 옮기다 보면 중간에 줄바꿈이 끼어듭니다. authorized_keys는 키 하나가 정확히 한 줄이어야 합니다. ssh-ed25519 AAAAC3Nza... 로 시작해서 주석까지 한 줄로 이어져야 하고, 중간이 끊기면 서버는 그 줄을 그냥 무시합니다. 에러도 안 나고 조용히 실패하기 때문에 원인 찾기가 제일 짜증나는 케이스입니다.

붙여넣기 후 확인은 이렇게 합니다.

wc -l ~/.ssh/authorized_keys   # 등록한 키 개수와 줄 수가 같아야 정상
cat -A ~/.ssh/authorized_keys | head   # 줄 끝에 $ 외에 ^M 이 보이면 CRLF 문제

권한 값 정리

sshd는 권한이 헐거우면 키를 아예 읽지 않습니다. 이게 실패 원인 1위입니다.

대상권한비고
~/.ssh700소유자만 접근
~/.ssh/authorized_keys600
~/.ssh/config (로컬)600
~/.ssh/id_ed25519 (로컬 개인키)600느슨하면 ssh가 사용 자체를 거부
홈 디렉터리 /home/user755 이하그룹 쓰기 권한이 있으면 안 됨
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 755 ~
chown -R $USER:$USER ~/.ssh

홈 디렉터리가 775나 770이면 키 인증이 막힙니다. 웹서버 그룹 권한을 준다고 홈에 g+w를 걸어둔 서버에서 자주 겪는 일입니다.

SELinux 켜진 CentOS/Rocky 계열

권한 값은 다 맞는데도 거부당한다면 SELinux 컨텍스트를 의심합니다. 다른 곳에서 파일을 복사해 왔을 때 라벨이 틀어집니다.

restorecon -Rv ~/.ssh
키 인증 설정 순서
키 인증 설정 순서

3단계: 접속 테스트와 클라이언트 설정 파일 정리

기존 세션은 그대로 둔 채, 새 터미널에서 확인합니다.

ssh -i ~/.ssh/id_ed25519 -p 2222 user@호스트

비밀번호를 안 묻고 바로 들어가면 성공입니다. 패스프레이즈를 걸었다면 패스프레이즈만 묻습니다. 계정 비밀번호를 묻는다면 아직 키 인증이 안 된 겁니다.

매번 -i와 -p를 치기 귀찮으니 ~/.ssh/config에 정리합니다.

Host myserver
    HostName 203.0.113.10
    User hong
    Port 2222
    IdentityFile ~/.ssh/id_ed25519_myserver
    IdentitiesOnly yes

Host web-prod
    HostName web.example.com
    User deploy
    IdentityFile ~/.ssh/id_ed25519_deploy
    IdentitiesOnly yes

이제 ssh myserver 한 줄이면 됩니다. scp, rsync, git 도 이 별칭을 그대로 인식합니다.

IdentitiesOnly yes 를 꼭 넣으세요

~/.ssh에 키가 여러 개 있거나 ssh-agent에 여러 키가 올라가 있으면, ssh 클라이언트는 가지고 있는 키를 순서대로 전부 시도합니다. 서버의 MaxAuthTries 기본값은 보통 6이라, 엉뚱한 키 여섯 개를 먼저 던지고 나면 정작 맞는 키를 보내기 전에 연결이 끊깁니다.

증상은 똑같이 Permission denied (publickey). 입니다. IdentitiesOnly yes는 “config에 지정한 IdentityFile만 써라”는 뜻이고, 이거 하나로 해결되는 경우가 생각보다 많습니다.

config 파일 권한도 600으로 맞춥니다.

chmod 600 ~/.ssh/config

4단계: 키 인증이 확인된 뒤 비밀번호 로그인 막기

키 접속이 성공한 다음에만 진행합니다. 순서를 바꾸면 잠깁니다.

sudo nano /etc/ssh/sshd_config

건드릴 항목은 네 개입니다.

PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password

KbdInteractiveAuthentication은 예전 OpenSSH에서 ChallengeResponseAuthentication 이라는 이름이었습니다. 설치된 버전에 따라 둘 중 하나가 파일에 들어 있으니, 파일에 이미 존재하는 이름 쪽을 no로 바꾸면 됩니다. 이걸 yes로 남겨두면 PasswordAuthentication no를 해도 키보드 인터랙티브 경로로 비밀번호를 계속 물어보는 경우가 있습니다.

PermitRootLogin 판단 기준은 이렇습니다.

값의미언제
noroot 직접 접속 완전 차단일반 사용자 + sudo 체계가 잡혀 있을 때
prohibit-passwordroot는 키로만 접속 가능root로만 관리하는 단독 서버, 자동화 스크립트가 root를 쓰는 경우
yesroot 비밀번호 접속 허용쓰지 마세요

우분투 클라우드 이미지의 함정

이게 진짜 많이 걸립니다. 우분투 계열은 sshd_config 맨 아래쯤에 이런 줄이 있습니다.

Include /etc/ssh/sshd_config.d/*.conf

AWS, GCP, Oracle Cloud 등의 공식 우분투 이미지에는 /etc/ssh/sshd_config.d/60-cloudimg-settings.conf 같은 파일이 들어 있고, 그 안에 PasswordAuthentication yes 가 박혀 있는 경우가 있습니다. 본 파일을 아무리 no로 고쳐도 이쪽이 이겨서 비밀번호 로그인이 계속 열려 있게 됩니다.

ls -l /etc/ssh/sshd_config.d/
sudo grep -ri "passwordauthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/

실제로 어떤 값이 적용됐는지는 이 명령으로 확인하는 게 확실합니다.

sudo sshd -T | grep -Ei "passwordauth|pubkeyauth|permitrootlogin|kbdinteractive"

문법 검사 후 재시작

저장했다고 바로 재시작하지 말고 반드시 문법부터 검사합니다.

sudo sshd -t

아무 출력이 없으면 정상입니다. 에러가 있으면 줄 번호와 함께 표시됩니다.

서비스 이름이 배포판마다 다릅니다.

배포판재시작 명령
데비안 / 우분투sudo systemctl restart ssh
RHEL / Rocky / AlmaLinux / CentOSsudo systemctl restart sshd

최근 우분투는 소켓 활성화(ssh.socket)를 쓰는 구성도 있어서, restart ssh가 먹지 않으면 sudo systemctl restart ssh.socket 도 확인해 보세요.

재시작해도 이미 붙어 있는 세션은 끊기지 않습니다. 그래서 착각하기 쉽습니다. 반드시 새 창에서 재접속이 되는지 확인하고, 그 다음에 원래 창을 닫으세요.

안 될 때: Permission denied (publickey) 원인별 점검

1) 클라이언트 쪽부터: ssh -vvv

ssh -vvv -i ~/.ssh/id_ed25519 user@호스트

출력이 길지만 볼 줄은 몇 개뿐입니다.

  • Offering public key: /home/hong/.ssh/id_ed25519 ED25519 SHA256:...

→ 내가 그 키를 실제로 보냈는지. 이 줄이 없으면 키 파일 경로나 IdentityFile 설정 문제입니다.

  • Authentications that can continue: publickey,password

→ 서버가 허용하는 인증 방식. publickey가 없으면 서버에서 공개키 인증이 꺼져 있는 겁니다.

  • Server accepts key: ... 가 나오면 키는 통과한 것이고, 그 뒤에서 막힌다면 계정/쉘 문제입니다.
  • no such identity: /home/hong/.ssh/id_ed25519_myserver: No such file or directory

→ config에 적은 파일명 오타입니다.

2) 서버 쪽 로그

키가 서버에 도착했는데 거절당하는 경우, 이유는 서버 로그에만 남습니다. 접속 시도를 하면서 실시간으로 봅니다.

배포판로그 확인
데비안 / 우분투sudo tail -f /var/log/auth.log
RHEL / Rocky / CentOSsudo tail -f /var/log/secure
systemd 저널만 쓰는 환경sudo journalctl -u ssh -f (RHEL 계열은 -u sshd)

여기서 제일 자주 보는 줄이 이겁니다.

Authentication refused: bad ownership or modes for directory /home/hong
Authentication refused: bad ownership or modes for file /home/hong/.ssh/authorized_keys

권한이나 소유자 문제라는 뜻입니다. 앞의 권한 표대로 다시 맞추세요. 특히 root로 sudo mkdir /home/hong/.ssh 를 해버려서 소유자가 root로 잡힌 경우가 흔합니다.

sudo chown -R hong:hong /home/hong/.ssh
sudo chmod 700 /home/hong/.ssh
sudo chmod 600 /home/hong/.ssh/authorized_keys
sudo chmod 755 /home/hong

3) 키 문제가 아닌 경우 구분하기

에러 메시지원인
Permission denied (publickey).인증 단계까지는 갔음. 키/권한/계정 문제
Connection refused해당 포트에 sshd가 안 떠 있음. 키와 무관
Connection timed out방화벽/보안그룹 차단. 키와 무관
Host key verification failed서버 재설치 등으로 호스트 키가 바뀜. ssh-keygen -R 호스트

refused와 timed out이 뜨는데 키를 고치고 있으면 시간만 버립니다. 먼저 포트가 열려 있는지 확인하세요.

ss -tlnp | grep sshd     # 서버에서
nc -zv 서버IP 22          # 로컬에서

4) 접속 허용 목록에 걸린 경우

sshd_config에 AllowUsers 나 AllowGroups 가 있으면, 거기 없는 계정은 키가 맞아도 거부됩니다.

sudo grep -Ei "allowusers|allowgroups|denyusers" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf

AllowUsers hong deploy 처럼 되어 있다면 새로 만든 계정을 여기 추가해야 합니다.

5) 계정이 잠겼거나 쉘이 nologin

sudo passwd -S hong

두 번째 필드가 L이면 잠긴 계정입니다. sudo passwd -u hong 으로 풀거나, 비밀번호 없이 키만 쓸 계정이면 sudo usermod -U hong 을 씁니다.

쉘도 확인합니다.

grep hong /etc/passwd

끝이 /usr/sbin/nologin 이나 /bin/false 면 인증에 성공해도 즉시 끊깁니다. 시스템 계정으로 만들어졌을 때 이렇게 됩니다.

sudo usermod -s /bin/bash hong

운영하면서 챙기면 좋은 것들

키 여러 개 등록하기

PC를 바꾸거나 팀원이 늘면 authorized_keys에 줄을 추가하기만 하면 됩니다. 파일을 갈아엎지 말고 append 하세요.

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... hong@macbook-2024
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... hong@desktop-win
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... kim@notebook

맨 끝 주석이 유일한 식별 수단입니다. -C 옵션을 대충 넣으면 반년 뒤에 어느 줄을 지워야 할지 알 수 없게 됩니다.

회수는 줄 삭제로 끝

퇴사자나 분실 기기의 접근을 끊을 때, 해당 줄만 지우면 됩니다. 비밀번호를 공유해 쓰던 시절처럼 나머지 사람에게 새 비밀번호를 다시 돌릴 필요가 없습니다. 이게 키 인증의 실질적인 이점입니다.

개인키 백업

개인키를 클라우드 드라이브나 메신저로 옮기는 건 권합니다만, 솔직히 말하면 대부분의 경우 백업보다 새로 만드는 편이 낫습니다. 새 PC에서 키를 새로 만들고 그 공개키를 authorized_keys에 한 줄 추가하면 끝이고, 기기별로 키가 분리되니 회수도 쉽습니다. 백업이 정말 필요하다면 패스프레이즈를 반드시 걸고 암호화된 저장소에 두세요.

GitHub용 키와 서버 접속용 키는 분리

같은 키를 Git 호스팅과 서버 양쪽에 쓰면, 한쪽이 유출됐을 때 양쪽을 동시에 갈아야 합니다. 그리고 실무적으로 더 자주 겪는 문제는 앞서 말한 MaxAuthTries 초과입니다. 키가 여러 개인데 IdentitiesOnly가 없으면 서버 접속 시 GitHub 키부터 던지다가 끊깁니다. 용도별로 파일을 나누고 ~/.ssh/config에서 Host별로 지정하는 조합이 가장 깔끔합니다.

서버 운영 기록을 어떤 기준으로 남기는지는 안녕하세요! 글에 적어뒀습니다.

다음에 할 일 체크리스트

  • [ ] 로컬에서 ssh-keygen -t ed25519 -C "식별용 주석" 으로 키 생성 (서버 아님)
  • [ ] ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 포트 user@host 로 공개키 등록
  • [ ] 서버에서 chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys, 홈은 755 이하 확인
  • [ ] chown -R 사용자:사용자 ~/.ssh 로 소유자 확인 (root로 만들었다면 필수)
  • [ ] 새 터미널에서 ssh -i 키경로 user@host 접속 성공 확인
  • [ ] ~/.ssh/config 작성 + IdentitiesOnly yes 추가 + chmod 600 ~/.ssh/config
  • [ ] sshd_config에서 PasswordAuthentication no 등 4개 항목 수정
  • [ ] ls /etc/ssh/sshd_config.d/ 확인해서 덮어쓰는 파일이 없는지 점검
  • [ ] sudo sshd -T | grep passwordauth 로 최종 적용값 확인
  • [ ] sudo sshd -t 통과 후 systemctl restart ssh 또는 sshd
  • [ ] 새 창에서 재접속 성공한 뒤에 기존 세션 종료
  • [ ] 안 되면 ssh -vvv 와 /var/log/auth.log(또는 /var/log/secure) 동시에 보기

댓글 1개

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다