SSH 인증서: 더 나은 SSH 경험
(jpmens.net)- SSH 인증서는 기존 공개키 기반 SSH 인증의 번거로움을 해결하며, 클라이언트와 서버 간 자동 신뢰를 제공함
- OpenSSH 5.4부터 지원되며, CA(인증 기관) 가 사용자와 호스트 키를 서명해
authorized_keys수정 없이 인증 가능 - 인증서에는 유효기간, 허용 사용자(principal), 접근 IP, 강제 명령(force-command) 등을 포함해 세밀한 접근 제어 지원
- TOFU(Trust on First Use) 절차가 제거되고, 호스트 키 변경 시 경고 없이 안전하게 접속 가능
- 자동 서명 서버나 도구를 활용하면 대규모 서버 환경의 SSH 관리 자동화와 보안성 향상이 가능함
SSH 인증서 개요와 기존 SSH 키 기반 인증의 한계
- SSH 연결 시 처음 접속하는 서버의 호스트 키 지문(fingerprint) 을 확인해야 하며, 대부분 사용자는 이를 검증하지 않고 ‘yes’를 입력하는 TOFU(Trust on First Use) 방식 사용
- 관리자는 서버의 지문을 직접 확인하거나
ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key명령으로 검증 가능
- 관리자는 서버의 지문을 직접 확인하거나
- 공개키 기반 인증은 비밀번호 없이 접속할 수 있지만, 각 서버의
authorized_keys파일에 공개키를 배포해야 함 - SSH 에이전트(
ssh-agent)를 이용하면 개인키를 메모리에 저장해 반복 입력 없이 인증 가능 - 기존 방식의 한계
- 사용자별로 서버에 공개키 복사 필요
- 호스트 키 변경 시 클라이언트에서 경고 메시지 발생
- TOFU로 인한 신뢰 관리의 불편함
SSH 인증서와 인증 기관(CA)
- SSH 인증서(Certificate) 는 OpenSSH 5.4(2010년 3월)부터 지원되며, 기존 SSH 키 포맷을 확장한 구조
- SSH CA는 SSH 키 쌍으로 구성되며, 공개키가 신뢰 루트 역할 수행
- 주요 장점
- 서버의
authorized_keys파일 수정 불필요 - 호스트 키 교체 시 경고 없음
- TOFU 절차 제거로 자동 신뢰 구현
- 인증서에 허용 사용자(principal), 허용 IP, 유효기간, 강제 명령(force-command) 등을 포함 가능
- 인증서 만료 시 자동 접근 차단
- 서버의
SSH CA 구축 및 서명 절차
- CA 시스템에서 ECDSA 알고리듬으로 CA 키 쌍 생성
-
ssh-keygen -t ecdsa -C "SSH CA" -f CA/ssh-ca
-
- 사용자는 자신의 공개키(
*.pub)를 CA에 전달하고, CA는 이를 서명(sign) 하여 인증서(*-cert.pub) 발급- 예:
ssh-keygen -s CA/ssh-ca -I "Jane Jolie" -n jane -z 001 -V +1w jane.pub
- 예:
- 서버 구성
- CA 공개키를
/etc/ssh/ssh-ca.pub에 저장하고TrustedUserCAKeys설정 추가 - 서버 호스트 키를 CA로 서명 (
ssh-keygen -h -s CA/ssh-ca ...) 후HostCertificate항목에 등록
- CA 공개키를
- 클라이언트 구성
-
known_hosts파일에@cert-authority한 줄 추가 - 예:
@cert-authority *.example.com $(cat CA/ssh-ca.pub)
-
SSH 인증서 기반 접속 및 검증
- 사용자는 서명된 인증서와 개인키를 함께 사용해 접속 (
ssh -i jane -l jane alice.example.com) - 서버 로그에는 인증서의 ID, 일련번호(serial), CA 지문 이 기록됨
- 여러 호스트명 또는 IP를 인증서의 principal 로 추가 가능
- 인증서에 지정된 principal 외 사용자로 로그인 시도 시 “Certificate invalid: name is not a listed principal” 오류 발생
- 인증서에 강제 명령(force-command) 또는 허용 IP(source-address) 설정으로 세밀한 접근 제어 가능
점검 및 문제 해결 체크리스트
-
서버 측 확인 항목
-
TrustedUserCAKeys설정 및 CA 공개키 존재 - 호스트 키 서명 및
HostCertificate지정 -
sshd재시작 필요
-
-
클라이언트 측 확인 항목
- 사용자 키가 CA로 서명되어 있어야 함
-
known_hosts의@cert-authority항목과 principal 일치 필요 - 인증서 만료 시 “Certificate invalid: expired” 메시지 표시
- 인증서 제약 조건 불일치 시 비밀번호 요청 발생
- SSH 에이전트에 인증서 추가 시 키와 인증서가 모두 등록됨 (
ssh-add jane) - 서명 시 옵션(
-O)으로 기능 제어 가능 - 예:
-O clear로 모든 권한 제거 후permit-agent-forwarding,permit-port-forwarding만 허용
호스트 키 인증서 자동화
- Python 모듈 sshkey-tools 와 BottlePy를 이용해 자동 서명 서버(hkbot) 구현
- CA 서버에서
hkbot.py실행 후 HTTP 요청으로 호스트 공개키 업로드 시 자동 서명 - 클라이언트에서
curl -F hostkey=@/etc/ssh/ssh_host_ed25519_key.pub http://CA:8870 | sh명령으로 자동 설치 -
/etc/ssh/sshd_config수정 및 검증 후systemctl restart sshd로 적용
- CA 서버에서
- 이후 SSH 접속 시 인증서 기반으로 자동 신뢰 및 로그인 가능
SSH 인증서의 장점 요약
- TOFU 불필요, 클라이언트와 서버 간 자동 신뢰
- 단기 유효 인증서 발급으로 일시적 접근 제어 가능
- 인증서 만료 시 자동 접근 차단,
authorized_keys정리 불필요 - 강제 명령, PTY 제한, 접근 IP 제어 등 세밀한 정책 설정 가능
- 자동화 도구로 대규모 서버 환경 관리 간소화 가능
- 관련 프로젝트로 Smallstep SSH 소개
추가 참고 자료
업데이트
- SSH CA는 자체 서버를 보유하고 루트 권한이 있는 환경에서 특히 유용
- 다중 사용자 시스템에서는 기존
known_hosts및authorized_keys방식이 여전히 필요 - SSH 인증서 포맷 표준화 초안:
draft-miller-ssh-cert-06
Hacker News 의견들
-
사람들이 아직도 SSH 비밀번호를 쓰는 게 놀라움
특히 대기업 환경에서는 여러 비밀번호 정책이 얽혀 있어서, 단순히 서버에 접속하는 데도 시간이 오래 걸림
그래서 ssh-keygen으로 키를 쓰라고 알려줘도 대부분 “언젠가 해봐야지” 하고는 결국 안 함- 키는 개인이나 회사에서 중앙 관리 체계가 있을 때 유용함
하지만 현실에서는 하나의 공용 키를 여러 서버에 쓰거나, 키를 공유하는 등 관리가 엉망이 되기 쉬움
비밀번호는 적어도 단순하다는 장점이 있음 - 나는 몇 년째 Yubikey 기반 HSM으로 SSH 키를 관리함
비밀번호는 없지만, 로그인할 때 물리적으로 Yubikey를 터치해야 함 - ssh-copy-id 같은 분산 키 사용은 해커가 네트워크 내에서 이동하기 쉽게 만들어서, 많은 조직이 이를 막음
- 키는 개인이나 회사에서 중앙 관리 체계가 있을 때 유용함
-
몇 달마다 누군가가 다시 SSH 인증서를 발견하고 블로그에 글을 씀
나도 15년 전에 관련 글을 썼는데, 지금 보면 부족했음- 많은 사람들이 키와 인증서를 혼동함
보안 엔지니어조차 SSH 인증서가 아닌 키 인증을 쓰고 있다는 걸 잊곤 함 - SSH 인증서는 특정 사용자에게 제한된 기간과 권한으로 접근을 허용할 수 있어서 유용함
- 나도 SSH 인증서를 알고는 있었지만, 키 기반에서 옮기지 못했음
여러 서버의 키를 수동으로 관리하는 게 너무 번거로움
이제라도 전환할 가치가 있을지 고민 중임 - 10년 전 내 직장에서 SSH CA를 만들 때, 위 블로그 글을 참고했음
- 많은 사람들이 키와 인증서를 혼동함
-
TOFU(Trust On First Use) 방식은 단순하지만 꽤 멀리 감
내 서버에서는 직접 호스트 키를 확인하고 나면 그걸로 충분함
대기업 환경에서는 내부 서버의 공개키 목록을 SSL로 서명된 내부 웹사이트에 올려두면 됨
하지만 서버가 많거나 자주 바뀌는 환경에서는 인증서가 훨씬 낫고, TOFU는 여러 면에서 한계가 있음
브라우저도 서버 TLS 키가 바뀌면 알려주는 기능이 있었으면 좋겠음- 1996년부터 SSH를 써왔지만, 실제로 공개키를 수동 검증하는 사람은 본 적이 없음
대부분은 그냥 “yes” 치고 넘어감
- 1996년부터 SSH를 써왔지만, 실제로 공개키를 수동 검증하는 사람은 본 적이 없음
-
회사에서 Zscaler의 SSL 검사 때문에 시간과 돈을 엄청 낭비함
“self-signed certificate in certificate chain” 오류가 뜨면 항상 골치 아픔- 친구 회사의 Windows 11에 설치된 Zscaler를 분석했는데, 거의 악성코드 수준이었음
자체 루트 인증서를 심고, 브라우저 설정을 잠가서 프록시를 못 쓰게 함
Firefox나 Chrome 설정 파일을 수정해도 즉시 덮어씀
심지어 GUI에서 끄려면 IT 비밀번호가 필요함
Cybereason 안티바이러스보다 약간 나은 정도임 - 우리 회사의 Cisco Umbrella도 마찬가지임
HTTP 기반 프로토콜을 전부 망가뜨림
Git, RubyGems, go mod, Nix 등 수많은 도구가 깨짐
벤더는 “투명하다”고 하지만 실제로는 전혀 아님
문제를 진단하는 데 몇 시간이 걸리고, 대부분의 관리자들은 이런 파괴력을 모름 - 참고로 SSH 인증서는 X.509 인증서와 다름
- 친구 회사의 Windows 11에 설치된 Zscaler를 분석했는데, 거의 악성코드 수준이었음
-
글에서는 CA 인증서의 장점만 언급했지만, 단점도 분명 존재함
나는 TOFU로 인한 보안 문제를 겪은 적이 없음- “사고가 없었으니 안전하다”는 건 안전벨트 안 매도 된다는 논리와 같음
SSH 인증서의 단점이 있다면 구체적으로 어떤 점인지 궁금함 - TOFU는 편리하지만 필수는 아님
보안을 강화하려면 USB 등 안전한 채널로 공개키를 교환하면 됨
인증서를 써도 결국 같은 절차를 밟아야 하고, 단지 관리 주체가 사용자에서 관리자 쪽으로 옮겨질 뿐임
대규모 조직에서는 인증서가 유용할 수 있지만, 일반적인 보안성은 동일함 - CA 구성을 사전에 설정할 수 있다면 TOFU를 피할 수 있음
설치 스크립트나 배포 이미지에 포함시키면 됨
TOFU는 이미 세팅된 박스에 접근할 때만 의미가 있음 - “아직 TOFU로 인한 보안 사고가 없었다”는 건, 아직 없을 뿐이라는 뜻임
- “사고가 없었으니 안전하다”는 건 안전벨트 안 매도 된다는 논리와 같음
-
우리 dev/stg 환경에서는 매일 절반의 머신을 재설치함
SSH 호스트 인증서 덕분에 known_hosts를 지우거나 키를 유지할 필요가 없어 훨씬 편함 -
개인 프로젝트로 Sshifu라는 도구를 만들고 있음
SSH 인증서 기반 로그인과 SSO를 쉽게 해주는 툴임
서버에 sshifu-server를 설치해 CA로 쓰고, 각 SSH 서버는 이 CA를 신뢰하도록 설정함
사용자는npx sshifu명령으로 로그인하면 끝임
GitHub 저장소 참고 바람 -
실제 운영 환경에서는 인증서 기반 접근이 복잡한 관리 문제로 이어짐
인증서 만료, 사용자 제거, 서버 장애 시 로그인 등 다양한 이슈가 생김
Userify에서 15년간 이런 문제를 다뤄왔는데, 안정적인 SSH 인증 인프라를 만드는 건 결코 간단하지 않음- 하지만 SaaS 방식은 최악의 선택이라고 생각함
-
pico.sh에 SSH 인증서 지원을 추가했는데, RBAC 스타일 접근 제어를 구현할 수 있어서 매우 유용했음
문서 링크 참고 -
프로덕션에서는 SSH 인증서가 오히려 복잡성을 중앙화시켜 문제를 키움
단일 CA가 항상 가용해야 하고, 장애 시 전체 접근이 막힘
TTL 조정, 신뢰 루트 관리, 디버깅 어려움 등 현실적인 문제도 많음
결국 사람들은 캐시나 에이전트를 다시 도입함
우리는 반대로 각 노드가 HTTPS로 사용자 정보를 로컬 authorized_keys에 동기화하도록 함
이렇게 하면 중앙 제어는 유지하면서도 장애가 국소화됨
Userify에서 이 방식을 사용 중이며, 인증뿐 아니라 권한 관리까지 처리함
인증서만으로는 사용자 생성, sudo 역할, 홈 디렉터리 정리 같은 문제는 해결되지 않음- TOFU는 어떻게 해결하냐는 질문을 받음