서버를 자동화로 다루기 시작하면 비밀번호가 걸림돌이 된다. Jenkins 가 에이전트에
붙을 때도, Ansible 이 여러 대에 명령을 내릴 때도, 사람이 비밀번호를 쳐 줄 수
없다.
그래서 키 한 쌍으로 비밀번호를 대신한다. 이 글은 그 원리와, 실제로 붙이는
순서, 안 될 때 보는 곳을 다룬다.
SSH 가 왜 필요했나#
원격 접속에는 원래 텔넷(Telnet)을 썼다. 암호화가 없어서 아이디와 비밀번호가
네트워크에 그대로 흘러 다녔다. 그걸 암호화해 대체한 것이 SSH(Secure Shell)다.
지금은 원격 접속의 기본이다. Jenkins, Ansible, 클라우드 인스턴스 — 서버를
만들면 제일 먼저 하는 일이 SSH 설정이다.
키 두 종류가 하는 일이 다르다#
SSH 접속은 두 단계로 나뉘고, 각 단계에서 다른 방식의 암호화를 쓴다. 이걸
구분해 두면 나머지가 다 이해된다.
| 단계 | 방식 | 하는 일 |
|---|---|---|
| 1. 신원 확인 | 비대칭키 (공개키 + 개인키) | "너 진짜 그 사람 맞아?" |
| 2. 데이터 주고받기 | 대칭키 (하나의 공유 키) | 오가는 내용을 감춘다 |
비대칭키 — 신원을 증명한다#
키 페어는 공개 키와 개인 키 한 쌍이다.
- 공개 키 (
.pub) — 이름 그대로 유출돼도 괜찮다. 접속할 서버에 미리 넣어 둔다 - 개인 키 — 나를 증명하는 수단이다. 절대 유출되면 안 된다
개인 키를 가진 사람이 공개 키가 저장된 서버에 접속을 시도하면, 서버는 그 둘이
한 쌍임을 확인하고 사용자를 식별한다. 비밀번호를 묻지 않는 이유가 이것이다.
대칭키 — 내용을 감춘다#
신원이 확인되면 이제 데이터를 주고받아야 한다. 이 구간은 하나의 키를 양쪽이
공유해 보내는 쪽이 암호화하고 받는 쪽이 복호화한다. 이 대칭키는 접속할 때마다
새로 만들어진다.
참고
왜 둘을 섞어 쓰나 싶을 수 있다. 비대칭키는 안전하지만 느리고, 대칭키는 빠르지만
"키를 어떻게 안전하게 건네느냐"가 문제다. 비대칭키로 신원을 확인하고 대칭키를
안전하게 합의한 뒤, 실제 통신은 빠른 대칭키로 하는 것이 SSH 의 구조다.
1. 키 페어 만들기#
접속하려는 쪽(예: Jenkins 마스터)에서 만든다.
ssh-keygen -t rsa
저장 경로를 묻는다. 기본값 ~/.ssh 를 쓰려면 그냥 엔터다.

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

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

확인해 보면 파일 두 개가 생겨 있다.
$ 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 자리에 그 값을 적는다.
함께 읽기#
- Jenkins 분산 빌드 — 여기서 만든 키가 실제로 쓰이는 자리. 마스터가 에이전트에 SSH 로 붙는다.
- 대시보드에 웹 터미널 붙이기 — 터미널 앱 없이 브라우저에서 같은 서버를 여는 쪽.
정리#
- 비대칭키는 신원 확인, 대칭키는 내용 암호화. SSH 는 둘을 이어 붙인 구조다.
- 공개 키는 서버에, 개인 키는 내 손에. 방향을 헷갈리면 계속 거부당한다.
- 권한이 틀리면 키가 맞아도 거부된다.
~/.ssh700,authorized_keys600. - 자동화용 키에는 passphrase 를 걸지 않는다. 사람이 쓰는 키에는 거는 게 낫다.
- 비밀번호 접속을 막는 것은 맨 마지막에. 키 접속을 확인하고, 접속된 창을 하나 열어 둔 채로 바꾼다.
refused와timeout은 다른 병이다. 앞은 포트·데몬, 뒤는 방화벽이다.

댓글