서버·인프라

SSH 키로 비밀번호 없이 서버 접속하기 — 원리부터 문제 해결까지

SSH 키로 비밀번호 없이 서버 접속하기 — 원리부터 문제 해결까지

서버를 자동화로 다루기 시작하면 비밀번호가 걸림돌이 된다. Jenkins 가 에이전트에
붙을 때도, Ansible 이 여러 대에 명령을 내릴 때도, 사람이 비밀번호를 쳐 줄 수
없다.

그래서 키 한 쌍으로 비밀번호를 대신한다. 이 글은 그 원리와, 실제로 붙이는
순서, 안 될 때 보는 곳을 다룬다.

SSH 가 왜 필요했나#

원격 접속에는 원래 텔넷(Telnet)을 썼다. 암호화가 없어서 아이디와 비밀번호가
네트워크에 그대로 흘러 다녔다. 그걸 암호화해 대체한 것이 SSH(Secure Shell)다.

지금은 원격 접속의 기본이다. Jenkins, Ansible, 클라우드 인스턴스 — 서버를
만들면 제일 먼저 하는 일이 SSH 설정이다.

키 두 종류가 하는 일이 다르다#

SSH 접속은 두 단계로 나뉘고, 각 단계에서 다른 방식의 암호화를 쓴다. 이걸
구분해 두면 나머지가 다 이해된다.

단계 방식 하는 일
1. 신원 확인 비대칭키 (공개키 + 개인키) "너 진짜 그 사람 맞아?"
2. 데이터 주고받기 대칭키 (하나의 공유 키) 오가는 내용을 감춘다

비대칭키 — 신원을 증명한다#

키 페어는 공개 키와 개인 키 한 쌍이다.

  • 공개 키 (.pub) — 이름 그대로 유출돼도 괜찮다. 접속할 서버에 미리 넣어 둔다
  • 개인 키 — 나를 증명하는 수단이다. 절대 유출되면 안 된다

개인 키를 가진 사람이 공개 키가 저장된 서버에 접속을 시도하면, 서버는 그 둘이
한 쌍임을 확인하고 사용자를 식별한다. 비밀번호를 묻지 않는 이유가 이것이다.

대칭키 — 내용을 감춘다#

신원이 확인되면 이제 데이터를 주고받아야 한다. 이 구간은 하나의 키를 양쪽이
공유해
보내는 쪽이 암호화하고 받는 쪽이 복호화한다. 이 대칭키는 접속할 때마다
새로 만들어진다.

참고

왜 둘을 섞어 쓰나 싶을 수 있다. 비대칭키는 안전하지만 느리고, 대칭키는 빠르지만
"키를 어떻게 안전하게 건네느냐"가 문제다. 비대칭키로 신원을 확인하고 대칭키를
안전하게 합의한 뒤, 실제 통신은 빠른 대칭키로
하는 것이 SSH 의 구조다.

1. 키 페어 만들기#

접속하려는 쪽(예: Jenkins 마스터)에서 만든다.

ssh-keygen -t rsa

저장 경로를 묻는다. 기본값 ~/.ssh 를 쓰려면 그냥 엔터다.

ssh-keygen 실행 직후 키를 저장할 경로를 묻는 화면
ssh-keygen 실행 직후 키를 저장할 경로를 묻는 화면

다음은 passphrase — 개인 키에 비밀번호를 한 겹 더 걸지 묻는 것이다.

passphrase 입력을 묻는 화면
passphrase 입력을 묻는 화면

팁

자동화용 키라면 비워 둔다(엔터). passphrase 를 걸면 Jenkins 나 Ansible 이
접속할 때마다 그걸 물어봐서 자동화가 멈춘다. 반대로 사람이 쓰는 노트북의
키라면 거는 쪽이 안전하다
— 노트북을 잃어버려도 키만으로는 못 쓴다.

만들어지면 이런 그림과 함께 끝난다.

키 생성이 완료되며 randomart 이미지가 출력된 화면
키 생성이 완료되며 randomart 이미지가 출력된 화면

확인해 보면 파일 두 개가 생겨 있다.

$ ls ~/.ssh
id_rsa          id_rsa.pub
파일 무엇
id_rsa 개인 키. 유출되면 안 된다
id_rsa.pub 공개 키. 접속할 서버에 넣을 것

참고

~/.ssh 에는 다른 파일도 생긴다. known_hosts 는 내가 접속했던 서버의
기록이고, authorized_keys 는 내 서버에 접속을 허용한 사람들의 공개 키
목록이다. 방향이 반대다.

2. 공개 키를 서버에 등록하기#

접속하려는 서버 쪽에서, 접속할 계정의 홈 디렉터리에 넣는다. 예를 들어 그
서버의 jenkins 계정으로 붙고 싶다면:

# 접속 대상 서버에서, jenkins 계정으로
mkdir -p ~/.ssh && chmod 700 ~/.ssh
vi ~/.ssh/authorized_keys       # id_rsa.pub 내용을 붙여 넣는다
chmod 600 ~/.ssh/authorized_keys

명령 한 줄로 하는 방법도 있다.

ssh-copy-id jenkins@서버주소

주의

권한이 틀리면 키가 맞아도 거부된다. ~/.ssh 는 700, authorized_keys 는
600 이어야 한다. SSH 는 남이 읽을 수 있는 키 파일을 믿지 않는다. 원인을 못 찾고
한참 헤매는 단골 자리다.

3. 서버 설정 맞추기#

키 접속이 되는 것을 확인한 다음에 비밀번호 접속을 막는다.

# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
sudo systemctl restart sshd

주의

순서를 거꾸로 하면 그 서버에 다시 못 들어간다. 키로 접속되는 것을 먼저
확인하고, 가능하면 다른 터미널 하나를 접속된 채로 열어 둔 상태에서 설정을
바꾼다. 잘못돼도 그 창으로 되돌릴 수 있다.

확인#

ssh -i ~/.ssh/id_rsa jenkins@서버주소

비밀번호를 안 묻고 바로 들어가면 끝난 것이다.

안 될 때 — 어디를 보나#

원인이 무엇인지 보려면 -v 를 붙인다. 어느 단계에서 막혔는지 그대로 찍힌다.

ssh -v -i ~/.ssh/id_rsa jenkins@서버주소
증상 원인
Permission denied (publickey) 공개 키가 없거나, 파일·디렉터리 권한이 틀렸다
계속 비밀번호를 묻는다 키를 아예 못 읽었다. 경로와 권한을 본다
Connection refused sshd 가 안 떠 있거나 포트가 다르다
응답 없이 오래 있다가 timeout 방화벽이다

팁

Connection refused 와 timeout 은 다른 병이다. 거부는 서버까지 닿았다는
뜻
이고(포트·데몬 문제), 응답 없는 timeout 은 패킷이 중간에서 버려졌다는
뜻
이다(방화벽·보안그룹). 이 구분만으로 볼 곳이 절반으로 준다.

방화벽도 아니라면#

일부 배포판에서는 계정별 접속 허용 목록이 따로 있다. /etc/security/access.conf
를 본다.

+ : jenkins : ALL

jenkins 계정의 접속을 모든 IP 에서 허용한다는 뜻이다. 특정 IP 나 대역만
허용하려면 ALL 자리에 그 값을 적는다.

함께 읽기#

정리#

  • 비대칭키는 신원 확인, 대칭키는 내용 암호화. SSH 는 둘을 이어 붙인 구조다.
  • 공개 키는 서버에, 개인 키는 내 손에. 방향을 헷갈리면 계속 거부당한다.
  • 권한이 틀리면 키가 맞아도 거부된다. ~/.ssh 700, authorized_keys 600.
  • 자동화용 키에는 passphrase 를 걸지 않는다. 사람이 쓰는 키에는 거는 게 낫다.
  • 비밀번호 접속을 막는 것은 맨 마지막에. 키 접속을 확인하고, 접속된 창을 하나 열어 둔 채로 바꾼다.
  • refused 와 timeout 은 다른 병이다. 앞은 포트·데몬, 뒤는 방화벽이다.
공유
욱콩

욱콩

서버와 배포를 만지면서 겪은 것을 기록합니다. 직접 돌려 보고 나온 결과만 씁니다.

댓글

댓글 남기기