안녕하세요. 일본서버, 미국서버 호스팅 전문 지구 IDC 기술팀입니다.
오늘은 Ubuntu 24.04에서 SSH 접속 시 Permission denied (publickey) 오류가 발생하는 원인과 해결 방법을 알아보겠습니다. 이 오류는 일반적으로 서버와의 SSH 연결 자체는 이루어졌지만, 클라이언트가 제시한 공개키를 서버가 인증에 사용할 수 없거나 허용하지 않았을 때 발생합니다.
가장 빠른 해결 방법은 키를 무작정 다시 만드는 것이 아니라 클라이언트에서 ssh -vvv로 어떤 개인키를 실제로 제시하는지 확인하고, 서버에서는 같은 시점의 journalctl -fu ssh.service 로그를 확인하는 것입니다. 이후 사용자명, authorized_keys, 파일 권한과 소유권, sshd_config.d 설정, 접근 제한 정책을 순서대로 점검하면 원인을 좁힐 수 있습니다.
적용 환경
| 항목 | 기준 |
|---|---|
| 서버 운영체제 | Ubuntu 24.04 LTS |
| SSH 서버 | openssh-server, 서비스명 ssh.service |
| 예시 서버 | 203.0.113.10, 사용자 admin_user, 기본 SSH 포트 22 |
| 예시 클라이언트 IP | 198.51.100.20 |
가장 먼저 확인할 항목
Permission denied (publickey)는 일반적으로 방화벽이나 SSH 포트가 막혔다는 뜻이 아닙니다. 이 메시지가 표시되었다면 대개 SSH 서버와 인증 단계까지 통신한 상태이므로 공개키 인증 경로를 확인해야 합니다.
먼저 사용자명, 서버 주소와 사용할 개인키를 명시하여 접속을 다시 시도합니다.
ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 [email protected]
SSH 포트를 변경한 서버라면 실제 포트를 지정합니다.
ssh -p 2222 -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 [email protected]
오류가 계속 발생하면 다음 순서로 확인합니다.
- 접속 사용자명이 공개키를 등록한 계정과 같은지 확인
- 클라이언트가 올바른 개인키를 실제로 제시하는지 확인
authorized_keys에 대응하는 공개키가 있는지 확인- 홈 디렉터리와
.ssh경로의 권한·소유권 확인 - 실제 적용 중인 OpenSSH 서버 설정 확인
- 서버 인증 로그에서 거부 원인 확인
클라이언트에서 ssh -vvv로 확인
가장 먼저 클라이언트가 실제로 어떤 키를 찾고 어떤 키를 서버에 제시하는지 확인합니다. -vvv 옵션은 SSH 인증 과정을 자세히 출력합니다.
ssh -vvv -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 [email protected]
출력에서 다음 내용을 확인합니다.
identity file: 지정한 개인키 파일을 찾았는지 확인Offering public key: 해당 키를 서버에 실제로 제시했는지 확인- 키를 제시한 직후 서버가 인증을 받아들이는지 또는 다음 인증 방법으로 넘어가는지 확인
- 서버가 허용하는 인증 방식에
publickey가 포함되는지 확인
개인키 파일이 존재하는지와 키 지문도 확인합니다.
ls -l ~/.ssh/id_ed25519
ssh-keygen -lf ~/.ssh/id_ed25519
Linux 또는 macOS에서 개인키 권한이 너무 넓으면 클라이언트가 키 사용을 거부할 수 있습니다.
chmod 600 ~/.ssh/id_ed25519
접속 사용자명 확인
공개키는 서버 전체에 공통으로 등록되는 것이 아니라 특정 사용자 계정에 등록됩니다. 따라서 admin_user 계정의 authorized_keys에 키를 등록해 놓고 다른 계정으로 접속하면 같은 오류가 발생합니다.
서버 콘솔이나 이미 열려 있는 관리 세션에서 계정과 홈 디렉터리를 확인합니다.
getent passwd admin_user
id admin_user
일반적으로 출력에 표시된 홈 디렉터리 아래의 .ssh/authorized_keys가 사용됩니다. 홈 디렉터리가 /home/admin_user가 아니라면 이후 명령의 경로도 실제 값에 맞게 변경하십시오.
개인키와 서버 공개키 일치 확인
클라이언트의 개인키에서 공개키를 추출한 뒤 지문을 확인합니다.
ssh-keygen -y -f ~/.ssh/id_ed25519 | ssh-keygen -lf -
서버에서는 대상 사용자의 authorized_keys에 등록된 공개키 지문을 확인합니다.
sudo -u admin_user ssh-keygen -lf /home/admin_user/.ssh/authorized_keys
클라이언트와 서버에서 확인한 지문이 일치해야 합니다. 일치하지 않는다면 올바른 공개키를 해당 사용자 계정에 추가합니다.
클라이언트에 ssh-copy-id를 사용할 수 있고 서버에서 임시로 비밀번호 로그인이 가능한 경우 다음과 같이 등록할 수 있습니다.
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
authorized_keys 권한과 소유권 확인
OpenSSH는 로그인 전에 사용자 홈 디렉터리와 SSH 관련 파일의 소유권 및 쓰기 권한을 검사합니다. .ssh 또는 authorized_keys가 다른 사용자에게 쓰기 가능하거나 소유자가 잘못되어 있으면 키가 올바르게 등록되어 있어도 인증이 거부될 수 있습니다.
경로 구성요소별 소유자와 권한을 확인합니다.
namei -l /home/admin_user/.ssh/authorized_keys
stat -c '%U:%G %a %n' \
/home/admin_user \
/home/admin_user/.ssh \
/home/admin_user/.ssh/authorized_keys
일반적인 전용 사용자 홈 디렉터리라면 다음과 같이 교정할 수 있습니다.
sudo chown -R admin_user:admin_user /home/admin_user/.ssh
sudo chmod go-w /home/admin_user
sudo chmod 700 /home/admin_user/.ssh
sudo chmod 600 /home/admin_user/.ssh/authorized_keys
chmod go-w는 홈 디렉터리에서 그룹과 다른 사용자의 쓰기 권한만 제거합니다. 공유 홈 디렉터리, ACL 또는 특수 권한 정책을 사용하는 환경에서는 기존 정책을 먼저 확인해야 합니다.
Canonical 공식 문서도 authorized_keys에 인증 대상 사용자 외의 쓰기 권한이 없어야 한다고 안내합니다. .ssh 700, authorized_keys 600은 일반적으로 안전하게 사용하는 설정입니다.
OpenSSH 서버 설정 확인
Ubuntu 24.04에서는 /etc/ssh/sshd_config뿐 아니라 /etc/ssh/sshd_config.d/*.conf 설정 조각도 확인해야 합니다. Ubuntu 기본 구성은 메인 설정 파일 상단에서 이 디렉터리를 포함하며 OpenSSH는 대부분의 지시어에서 먼저 읽은 값을 사용합니다.
관련 지시어가 어디에 정의되어 있는지 확인합니다.
sudo grep -RniE '^[[:space:]]*(Include|PubkeyAuthentication|AuthorizedKeysFile|AuthenticationMethods|PermitRootLogin|AllowUsers|DenyUsers|AllowGroups|DenyGroups|Match)[[:space:]]' \
/etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null
기본 유효 설정을 확인합니다.
sudo sshd -T | grep -E '^(pubkeyauthentication|authorizedkeysfile|authenticationmethods|permitrootlogin) '
pubkeyauthentication yes가 적용되어 있어야 공개키 인증을 사용할 수 있습니다. authorizedkeysfile에 표시된 경로가 기본값과 다르다면 실제 공개키 파일이 그 위치에 존재하는지 확인해야 합니다.
PubkeyAuthentication이 no인 경우
공개키 인증이 명시적으로 비활성화된 경우 설정 조각을 만들어 활성화할 수 있습니다.
sudo tee /etc/ssh/sshd_config.d/00-publickey-fix.conf > /dev/null <<'EOF'
PubkeyAuthentication yes