2026년 원격 Mac sshd 호스트 키 로테이션: UpdateHostKeys, Ed25519 전환, 이중 키 윈도우와 CI known_hosts
규정 감사, 하드웨어 교체, 오래된 RSA 호스트 키 폐기——어느 경우든 원격 Mac의 OpenSSH 서버에서 호스트 키를 계획적으로 바꿔야 한다. 서버만 갈아끼우고 CI에 박아 둔 known_hosts를 그대로 두면, 새벽 rsync 배치가 한꺼번에 REMOTE HOST IDENTIFICATION HAS CHANGED로 멈춘다. 보안이 과한 게 아니라 변경 관리가 반쪽인 것이다. 이 글은 UpdateHostKeys, Ed25519 전환, 이중 키 병행 윈도우, GitHub Actions 동기화를 Runbook으로 묶고, known_hosts 고정, ControlMaster, OIDC 배포와 이어 준다.
목차
로테이션을 「재설치 사고」로 두지 않기
문제 ① 사후 지문 수정. macOS 업그레이드나 Time Machine 복구 뒤 /etc/ssh/ssh_host_*만 새로워지고, known_hosts 글의 Secret은 예전 지문 그대로인 경우가 많다. 로그는 rsync 대역폭이나 옵션을 의심하게 되고, 호스트 키 불일치는 묻힌다.
문제 ② 사용자 자격만 현대화. OIDC·Deploy Key는 깔끔한데 호스트 쪽은 RSA에 머무르면 「누가 로그인하나」와 「어느 서버와 대화하나」가 갈라진다. 후자는 MITM의 문이다.
문제 ③ ControlPersist가 교체를 가린다. ControlMaster로 master가 살아 있는 동안은 서버가 이미 새 키를내도 자식 잡은 옛 검증 세션을 쓴다. master가 끊기는 순간 일괄 실패한다. 로테이션 전후에는 ssh -O exit나 ControlPersist 단축을 일정에 넣는다.
문제 ④ 금요일 밤 일괄 전환. 아시아·유럽 잡이 동시에 빨개지는 패턴이다. 운영 가능한 순서는 먼저 클라이언트와 CI가 두 지문을 받아들이고, 그다음 서버가 구 키를 내리는 것이다.
macOS sshd: HostKey 목록과 Ed25519 추가
쓰는 중인 비밀 키 파일을 덮어쓰지 말고, 새 파일명으로 ssh-keygen -t ed25519 한 뒤 sshd_config의 HostKey에 추가한다. sshd -t 통과 후 launchctl로 재기동한다. Ed25519는 짧고 검증이 빨라 2026년 기본 후보로 적합하다. 레거시 RSA는 이행기에만 남겨 스캐너·구형 클라이언트를 받는다.
sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
sudo ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
sudo launchctl kickstart -k system/com.openssh.sshd
지문 수집은 대역 밖 신뢰 단말에서 ssh-keyscan -t ed25519로 한다. Runner 첫 접속 때 Secret을 고치면 TOFU를 일회성 네트워크에 맡기게 되어 감사 설명이 어렵다.
LB·유동 DNS 뒤에서 서로 다른 키가 보이면 같은 호스트명에 지문이 두 종류 붙어 「장애」처럼 보인다. 호스팅형 Mac에서는 「별칭—지문—Secret 이름」을 RACI 한 장에 고정하는 편이 낫다.
UpdateHostKeys: 사람용, Runner 대체 아님
OpenSSH 8+의 UpdateHostKeys는 서버가 새 호스트 키를보낼 때 대화형 단말의 known_hosts를 갱신한다. 운영자 노트북에는 ask·accept-new가 마찰을 줄인다.
GitHub Actions에서는 반대로 StrictHostKeyChecking=yes와 전용 UserKnownHostsFile을 유지한다(고정 글). 디스크는 매번 비어 있다. 자동 갱신은 「누가 언제 승인했는지」를 남기지 못한다. 잡 시작 시 Secret에서 ci_known_hosts를 쓴다.
ProxyJump에서는 홉마다 지문표를 갱신한다. 최종 홉만 UpdateHostKeys를 켜도 중간 bastion 교체는 전파되지 않는다.
이중 키 윈도우: T0→T1 세 단계
T0: 서버가 구 RSA와 신 Ed25519를 동시에 올리고 협상으로 둘 다 제시한다. T0~T1: Secret·운영 known_hosts·모니터 프로브에 두 줄 병기하고 rsync·sftp 배치 전체 CI를 한 바퀴 돌린다. T1 이후: 의존이 없으면 HostKey 구 행과 Secret 구 행을 삭제한다.
윈도우 길이는 최장 릴리스 주기+주말 배치를 본다. 금요일만 풀 빌드면 주말을 넘긴 이중 지문이 현실적이다. ControlMaster 환경은 T0 당일 master 없는 프로브 잡으로 새 핸드셰이크를 강제한다.
롤백은 미리 쓴다. 신 Ed25519 권한 오류로 sshd가 죽어도 구 RSA만으로 기동 가능하게 config 조각과 구 비밀 키를 변경 티켓 첨부에 둔다.
CI known_hosts: 파이프라인을 녹색으로
# Secret SSH_KNOWN_HOSTS (동일 호스트명에 구·신 두 줄, T1에서 구 줄 삭제)
[build-mac.example.com]:22 ssh-ed25519 AAAA...old...
[build-mac.example.com]:22 ssh-ed25519 AAAA...new...
export RSYNC_RSH='ssh -o BatchMode=yes -o StrictHostKeyChecking=yes \
-o UserKnownHostsFile=$HOME/.ssh/ci_known_hosts'
호스트 키 변경은 OIDC 로테이션과 같은 릴리스 심의표에 올린다. 호스트명, 구·신 지문, Secret PR, T1 수렴일, bastion 영향 열을 둔다. Secret 병합 뒤 rsync --dry-run 읽기 전용 프로브를 먼저, 본 업로드는 나중에 한다.
판단표
| 방침 | 적합 | CI | 위험 |
|---|---|---|---|
| 주말 일괄 교체 | 실험 1대 | Secret까지 전부 빨강 | 높음 |
| 이중 HostKey+두 줄 Secret | 운영 Mac | 무중단 가능 | 낮음(수렴일 필수) |
| UpdateHostKeys만 | 사람 단말 | Runner 부적합 | 감사 불가 |
| 임시 accept-new | 긴급 | 단기 녹색 | MITM 창 |
읽는 순서: 이 글 → known_hosts 고정 → ControlMaster → OIDC → 무결성·원자 배포 글. 「사용자 증명은 최신, 호스트는 TOFU」가 아닌지 합동 심의에서 묻는다.
정리와 SFTPMAC
호스트 키 로테이션은 서버·사람 클라이언트·CI 세 축 동기화다. UpdateHostKeys와 이중 키 윈도우 역할이 분명하면 Ed25519 전환 뒤에도 파이프라인은 신뢰 가능하고 설명 가능하다.
자체 Mac은 HostKey·Secret·온콜을 직접든다. SFTPMAC 호스팅형 원격 Mac은 지문 저장소와 변경 창을 패키지 Runbook에 넣어 산출물에 집중하게 한다. 요금.