Thursday, January 31, 2019

EC2 인스턴스 접속 불가능? 'REMOTE HOST IDENTIFICATION HAS CHANGED' 오류의 근본 원인과 해결법

클라우드 컴퓨팅의 선두주자 AWS(Amazon Web Services)의 EC2(Elastic Compute Cloud) 인스턴스는 개발자, 시스템 관리자, 그리고 수많은 IT 전문가들에게 강력하고 유연한 가상 서버 환경을 제공합니다. 개발 환경 구축부터 프로덕션 서비스 운영까지, EC2는 이제 현대 IT 인프라의 핵심적인 부분으로 자리 잡았습니다. EC2 인스턴스를 생성하고, 탄력적 IP(Elastic IP)를 할당하고, 정성껏 만든 `.pem` 키 페어를 이용해 SSH(Secure Shell)로 접속을 시도하는 순간, 많은 사용자들이 당혹스러운 경고 메시지를 마주하게 됩니다.


@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@       WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!      @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator.
Add correct host key in /home/username/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/username/.ssh/known_hosts:5
  remove with:
  ssh-keygen -f "/home/username/.ssh/known_hosts" -R "your-ec2-instance-ip"
ECDSA host key for your-ec2-instance-ip has changed and you have requested strict checking.
Host key verification failed.

이 무시무시한 경고 메시지는 'REMOTE HOST IDENTIFICATION HAS CHANGED!'라는 문구와 함께 "누군가 당신을 도청하고 있을 수 있다(man-in-the-middle attack)!"는 섬뜩한 가능성까지 제시합니다. 처음 이 메시지를 접하면 해킹을 당했거나, 계정에 심각한 문제가 생긴 것은 아닌지 불안감에 휩싸이기 쉽습니다. 하지만 결론부터 말하자면, 대부분의 경우 이는 실제 공격 상황이 아니라, SSH의 매우 중요한 보안 메커니즘이 정상적으로 작동하고 있다는 신호입니다. 여러분의 로컬 컴퓨터가 여러분을 보호하기 위해 접속을 의도적으로 차단하고 있는 것입니다.

이 글에서는 이 'REMOTE HOST IDENTIFICATION HAS CHANGED' 오류가 왜 발생하는지, 그 근본적인 원인이 되는 SSH의 호스트 키 인증 매커니즘을 심도 있게 파헤쳐 볼 것입니다. 그리고 단순히 문제를 해결하는 명령어 한 줄을 소개하는 것을 넘어, 상황에 따른 다양한 해결 방법과 각 방법의 장단점, 나아가 이러한 문제를 미연에 방지할 수 있는 예방책까지 총망라하여 완벽하게 이해하고 대처할 수 있도록 도와드리겠습니다.

1. 오류의 근원: SSH와 '신뢰의 증표', 호스트 키(Host Key)

문제를 해결하기 위해서는 먼저 그 원인을 알아야 합니다. 이 오류의 핵심에는 SSH의 '호스트 키 검증(Host Key Verification)'이라는 보안 절차가 있습니다. 이는 마치 우리가 처음 방문하는 은행에서 신분증을 제시하여 본인임을 확인하고, 다음 방문부터는 안면 인식이나 지문으로 더 빠르게 신원을 확인하는 과정과 유사합니다.

1.1. SSH 통신과 중간자 공격(Man-in-the-Middle Attack)의 위협

SSH는 클라이언트(우리의 노트북 또는 데스크톱)와 서버(EC2 인스턴스) 간의 모든 통신을 암호화하여 안전하게 만들어주는 프로토콜입니다. 우리가 입력하는 명령어, 서버가 보내오는 응답 등 모든 데이터가 암호화되어 중간에 누군가 가로채더라도 내용을 알 수 없습니다.

하지만 여기서 한 가지 치명적인 허점이 생길 수 있습니다. 만약 우리가 접속하려는 '진짜' EC2 서버가 아닌, 해커가 만든 '가짜' 서버에 접속하게 된다면 어떻게 될까요? 해커는 우리의 접속 요청을 중간에서 가로채 자신의 가짜 서버로 연결합니다. 우리는 진짜 서버에 접속한 줄 알고 아이디와 비밀번호, 혹은 중요한 명령어를 입력하게 되고, 해커는 이 모든 정보를 얻어낸 뒤 다시 진짜 서버로 요청을 전달해 우리에게 정상적인 응답을 보여줍니다. 우리는 아무것도 눈치채지 못하지만, 우리의 모든 정보는 해커에게 노출됩니다. 이를 '중간자 공격(Man-in-the-Middle Attack, MITM)'이라고 부릅니다.

1.2. 중간자 공격을 막는 방패: 호스트 키와 `known_hosts` 파일

SSH는 이러한 중간자 공격을 방지하기 위해 '호스트 키'라는 매우 영리한 장치를 사용합니다.

  • 호스트 키(Host Key): 모든 SSH 서버(EC2 인스턴스 포함)는 처음 설치되고 설정될 때, 고유한 한 쌍의 키(공개키와 개인키)를 생성합니다. 이것이 바로 '호스트 키'입니다. 이 키는 해당 서버의 '신분증'과 같은 역할을 합니다.
  • 첫 만남 (최초 접속): 우리가 어떤 서버에 생애 처음으로 SSH 접속을 시도하면, 클라이언트(우리의 컴퓨터)는 해당 서버에게 "너의 신분증(호스트 키의 공개키)을 보여줘"라고 요청합니다. 서버는 자신의 공개키를 보내주고, 우리 컴퓨터는 다음과 같은 질문을 합니다.

The authenticity of host 'ec2-xx-xx-xx-xx.ap-northeast-2.compute.amazonaws.com (xx.xx.xx.xx)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])? 

이 메시지의 의미는 "이 서버는 처음 보는 곳인데, 이 서버의 키 지문(fingerprint)이 이거래. 정말 이 서버가 네가 접속하려는 그 서버가 맞아? 연결을 계속할까?"라고 묻는 것입니다. 여기서 우리가 yes를 입력하면, 우리 컴퓨터는 '아, 이 IP 주소(또는 도메인)의 신분증은 이것이구나'라고 판단하고, 해당 서버의 IP 주소와 공개키 정보를 자신의 '신뢰 목록'에 저장합니다.

  • `known_hosts` 파일: 이 '신뢰 목록'이 바로 우리 컴퓨터의 ~/.ssh/known_hosts 파일입니다. 이 파일은 우리가 신뢰하기로 결정한 모든 서버들의 주소와 그들의 고유한 공개키 정보를 기록해두는 일종의 '보안 연락처'입니다.

1.3. 'REMOTE HOST IDENTIFICATION HAS CHANGED' 오류가 발생하는 시나리오

자, 이제 모든 조각이 맞춰졌습니다. 오류 메시지가 발생하는 상황은, 우리가 다시 같은 주소로 접속을 시도했는데, 서버가 제시한 '신분증(호스트 키)'이 known_hosts 파일에 기록된 '신분증'과 다를 때 발생합니다.

우리 컴퓨터는 이렇게 생각합니다. "어? 분명 이 IP 주소를 가진 서버의 신분증은 A였는데, 방금 접속하니 B라는 다른 신분증을 내미네? 이거 중간에 누가 서버를 바꿔치기한 것일 수 있어! (중간자 공격 가능성!) 일단 연결을 차단하고 사용자에게 알려야겠다!" 이것이 바로 'REMOTE HOST IDENTIFICATION HAS CHANGED!' 경고의 본질입니다.

그렇다면 AWS EC2 환경에서 왜 이런 일이 흔하게 발생할까요? 실제 해킹이 아니라면 말이죠.

  • 가장 흔한 원인: 탄력적 IP(Elastic IP) 재사용
    • 기존에 사용하던 EC2 인스턴스(A 서버)를 종료(Terminate)했습니다. 이 인스턴스는 12.34.56.78 이라는 탄력적 IP를 사용하고 있었습니다.
    • 새로운 EC2 인스턴스(B 서버)를 생성하고, 똑같은 탄력적 IP 주소인 12.34.56.78을 할당했습니다.
    • 우리 컴퓨터의 `known_hosts` 파일에는 여전히 12.34.56.78 = 'A 서버의 호스트 키'라고 기록되어 있습니다.
    • 이제 12.34.56.78로 접속을 시도하면, B 서버는 자신의 새로운 호스트 키를 제시합니다.
    • 우리 컴퓨터는 'A 서버의 호스트 키'를 기대했지만 'B 서버의 호스트 키'를 받았으므로, 불일치를 감지하고 접속을 차단합니다.
  • 기타 원인
    • 인스턴스의 OS 재설치: 기존 인스턴스를 유지한 채로 운영체제(OS)를 새로 설치하면, SSH 서버 데몬이 새로 설정되면서 새로운 호스트 키를 생성할 수 있습니다.
    • AMI(Amazon Machine Image)로 인스턴스 복제: 기존 인스턴스의 AMI를 떠서 새로운 인스턴스를 생성할 때, 일부 설정에 따라 부팅 시 새로운 호스트 키를 생성하도록 구성된 경우가 있습니다.
    • 로드 밸런서 또는 프록시 변경: 직접적인 원인은 아니지만, 접속 경로상의 네트워크 장비가 변경되면서 다른 서버로 연결이 라우팅될 때도 유사한 문제가 발생할 수 있습니다.

결론적으로 EC2 환경에서의 이 오류는, IP 주소는 그대로인데 그 IP 주소에 연결된 실제 가상 머신(과 그 호스트 키)이 변경되었기 때문에 발생하는 지극히 정상적인 보안 경고인 셈입니다.

2. 단계별 해결 방법: 안전하고 빠른 방법부터 수동적인 방법까지

원인을 명확히 이해했으니 이제 해결 방법을 알아볼 차례입니다. "이 IP 주소의 주인이 바뀐 것이 맞다"고 우리 컴퓨터에게 알려주어 `known_hosts` 파일의 낡은 정보를 갱신해주면 됩니다. 여기에는 여러 가지 방법이 있으며, 각 방법의 특징을 이해하고 가장 적절한 방법을 선택하는 것이 좋습니다.

해결 방법 1: 가장 안전하고 권장되는 방법 - `ssh-keygen` 사용하기

이 방법은 SSH가 직접 제공하는 도구를 사용하여 `known_hosts` 파일에서 특정 호스트의 정보만 정확하고 깔끔하게 제거하는 가장 이상적인 방법입니다. 오류 메시지에서도 이 방법을 친절하게 안내하고 있습니다.


  remove with:
  ssh-keygen -f "/home/username/.ssh/known_hosts" -R "your-ec2-instance-ip"

ssh-keygen은 SSH 키를 생성, 관리, 변환하는 유틸리티이며, -R 옵션은 'Remove'의 약자로, 지정된 호스트 이름을 `known_hosts` 파일에서 제거하는 역할을 합니다.

실행 절차:

  1. 터미널(Mac의 Terminal, Windows의 PowerShell, WSL 또는 Git Bash 등)을 엽니다.
  2. 다음 명령어를 입력합니다. <삭제할_서버_IP_또는_도메인> 부분에 문제가 발생한 EC2 인스턴스의 IP 주소나 도메인 이름을 입력합니다.

ssh-keygen -R <삭제할_서버_IP_또는_도메인>

예시: 문제가 발생한 서버의 IP 주소가 `12.34.56.78`인 경우


ssh-keygen -R 12.34.56.78

예시: EC2의 퍼블릭 DNS 주소가 `ec2-12-34-56-78.ap-northeast-2.compute.amazonaws.com`인 경우


ssh-keygen -R ec2-12-34-56-78.ap-northeast-2.compute.amazonaws.com

실행 결과:

명령어를 실행하면 다음과 같은 메시지가 나타나며, 지정된 호스트 정보가 `known_hosts` 파일에서 제거되었음을 알려줍니다.


# Host 12.34.56.78 found: line 5
/home/username/.ssh/known_hosts updated.
Original contents retained as /home/username/.ssh/known_hosts.old

이 메시지는 `/home/username/.ssh/known_hosts` 파일의 5번째 줄에서 해당 IP 정보를 찾아 업데이트했으며, 만약을 대비해 원본 파일을 `known_hosts.old`라는 이름으로 백업해두었다는 의미입니다.

후속 조치:

이제 `known_hosts` 파일에서 이전 서버의 '신분증' 기록이 깨끗하게 사라졌습니다. 다시 평소처럼 SSH 접속을 시도합니다.


ssh -i "my-key.pem" ec2-user@12.34.56.78

그러면 맨 처음 서버에 접속했을 때와 같이, 새로운 서버의 '신분증'을 등록할 것인지 묻는 메시지가 다시 나타납니다.


The authenticity of host '12.34.56.78 (12.34.56.78)' can't be established.
...
Are you sure you want to continue connecting (yes/no/[fingerprint])?

여기서 yes를 입력하면 새로운 EC2 인스턴스의 호스트 키가 `known_hosts` 파일에 새로 등록되고, 정상적으로 접속이 완료됩니다.

이 방법의 장점:

  • 안전성: 문제가 된 특정 호스트의 정보만 정확히 제거하므로 다른 정상적인 서버의 접속 정보에 영향을 주지 않습니다.
  • 정확성: 파일 내용을 직접 수정할 때 발생할 수 있는 실수를 방지합니다.
  • 공식적인 방법: SSH 개발자들이 의도하고 권장하는 방식입니다.

해결 방법 2: 수동으로 `known_hosts` 파일 수정하기

내부적으로 어떤 일이 일어나는지 직접 확인하고 싶거나, `ssh-keygen` 명령어가 익숙하지 않은 경우 `known_hosts` 파일을 직접 편집기에서 열어 문제가 되는 라인을 삭제할 수도 있습니다. 오류 메시지에 보통 문제가 되는 라인 번호가 표시되므로 생각보다 어렵지 않습니다.


Offending ECDSA key in /home/username/.ssh/known_hosts:5

위 메시지는 `known_hosts` 파일의 5번째 줄이 문제의 원인임을 알려줍니다.

실행 절차:

  1. 선호하는 텍스트 편집기(nano, vim, emacs 또는 VS Code와 같은 GUI 편집기)로 `known_hosts` 파일을 엽니다. Linux나 macOS에서는 보통 ~/.ssh/known_hosts에 위치합니다.

nano 편집기를 사용하는 경우:


nano ~/.ssh/known_hosts

vim 편집기를 사용하는 경우:


vim ~/.ssh/known_hosts
  1. 파일을 열면 다음과 비슷한 내용을 볼 수 있습니다. 각 줄이 하나의 신뢰하는 서버 정보를 담고 있습니다. 최신 SSH 설정에서는 보안을 위해 호스트 이름과 IP가 해싱(hashing)되어 알아보기 어려울 수 있습니다.

(해싱되지 않은 경우의 예)


github.com,140.82.112.4 ssh-rsa AAAA...
gitlab.com,172.65.251.78 ssh-ed25519 AAAA...
12.34.56.78 ecdsa-sha2-nistp256 AAAA...  <-- 문제가 되는 라인!
bitbucket.org,104.192.141.1 ssh-rsa AAAA...

(해싱된 경우의 예)


|1|b3X...|pYq... ecdsa-sha2-nistp256 AAAA...
|1|jK1...|sL9... ecdsa-sha2-nistp256 AAAA... <-- 문제가 되는 라인이지만, 어느 서버인지 알기 힘듦.
  1. 오류 메시지에서 알려준 라인 번호(예: 5번째 줄)로 이동하거나, 문제가 되는 IP 주소 또는 호스트 이름이 포함된 라인을 찾습니다.
  2. 해당 라인 전체를 삭제합니다. (vim에서는 `dd` 커맨드, nano에서는 `Ctrl+K` 등으로 한 줄을 삭제할 수 있습니다.)
  3. 파일을 저장하고 편집기를 종료합니다. (nano에서는 `Ctrl+X`, `Y`, `Enter`. vim에서는 `:wq`)
  4. 이제 해결 방법 1과 마찬가지로 다시 SSH 접속을 시도하고, yes를 입력하여 새로운 키를 등록하면 됩니다.

이 방법의 장단점:

  • 장점: `known_hosts` 파일의 구조를 직접 눈으로 확인할 수 있어 학습에 도움이 됩니다.
  • 단점: 실수로 다른 중요한 서버의 키를 삭제할 위험이 있습니다. 특히 호스트 이름이 해싱된 경우, 정확한 라인을 찾기가 까다로울 수 있어 라인 번호 정보가 없다면 권장되지 않습니다.

해결 방법 3: 빠르고 거칠지만 추천하지 않는 방법 - `known_hosts` 파일 전체 삭제/이름 변경

가장 빠르고 간단하게 문제를 회피하는 방법은 `known_hosts` 파일 자체를 삭제하거나 이름을 바꿔버리는 것입니다.


# 파일 삭제
rm ~/.ssh/known_hosts

# 또는 파일 이름 변경 (조금 더 안전한 백업)
mv ~/.ssh/known_hosts ~/.ssh/known_hosts.bak

이 명령어를 실행하면 '보안 연락처' 자체가 사라집니다. 따라서 다음에 어떤 서버에 접속하든, 심지어 이전에 문제없이 잘 접속하던 다른 모든 서버(예: GitHub, 회사 내부 서버 등)에 대해서도 처음 접속하는 것처럼 "Are you sure you want to continue connecting (yes/no)?"라는 질문을 다시 받게 됩니다.

이 방법은 왜 추천하지 않는가?

  • 보안 수준 저하: 이 방법은 모든 서버에 대한 신뢰 정보를 초기화합니다. 이는 모든 문의 '신뢰의 증표'를 없애고 매번 신분증을 새로 확인하는 것과 같습니다. 만약 사용자가 무의식적으로 모든 연결에 yes를 누르는 습관이 있다면, 실제 중간자 공격이 발생했을 때 알아채지 못하고 공격에 노출될 수 있습니다.
  • 불편함: 관리하는 서버가 많을수록 모든 서버의 키를 다시 확인하고 등록해야 하므로 매우 번거롭습니다.

이 방법은 오직 관리하는 서버가 단 하나뿐이고, 다른 중요한 서버 접속 기록이 전혀 없는, 완전히 격리된 테스트 환경에서만 최후의 수단으로 고려해볼 수 있습니다.

3. 예방 및 고급 팁: 애초에 오류를 마주하지 않으려면?

문제를 해결하는 것도 중요하지만, 더 나은 방법은 애초에 이런 상황을 덜 마주치도록 환경을 구성하는 것입니다.

3.1. 인스턴스 종료(Terminate) vs 정지(Stop)

EC2 인스턴스를 잠시 사용하지 않을 때는 '종료(Terminate)' 대신 '정지(Stop)'하는 습관을 들이는 것이 좋습니다.

  • 정지(Stop): 인스턴스는 꺼지지만, 루트 볼륨(EBS)과 설정 정보(호스트 키 포함)는 그대로 보존됩니다. 다시 '시작(Start)'하면 원래의 상태 그대로 부팅됩니다. 따라서 호스트 키가 변경되지 않아 SSH 오류가 발생하지 않습니다. (단, 퍼블릭 IP는 변경될 수 있으므로 탄력적 IP를 사용하는 것이 좋습니다.)
  • 종료(Terminate): 인스턴스와 연결된 루트 볼륨이 완전히 삭제됩니다(설정에 따라 보존도 가능). 이는 가상 머신을 영구적으로 폐기하는 것과 같습니다. 나중에 같은 IP로 새 인스턴스를 만들어도 그것은 완전히 다른 컴퓨터이므로 호스트 키도 다릅니다.

단순히 개발/테스트를 잠시 멈추는 경우라면 '정지'를 활용하여 불필요한 SSH 키 충돌을 예방할 수 있습니다.

3.2. SSH 설정 파일(`~/.ssh/config`) 활용하기

매번 긴 SSH 명령어를 입력하는 대신, ~/.ssh/config 파일을 활용하면 접속을 훨씬 편리하고 체계적으로 관리할 수 있으며, 이 문제에 대한 임시 해결책도 적용할 수 있습니다.

~/.ssh/config 파일에 다음과 같이 호스트 정보를 등록합니다.


# ~/.ssh/config 파일

Host my-dev-server
    HostName 12.34.56.78
    User ec2-user
    IdentityFile ~/.ssh/my-key.pem

Host my-prod-server
    HostName 56.78.12.34
    User ubuntu
    IdentityFile ~/.ssh/prod-key.pem

이렇게 설정하면, 이제 터미널에서 ssh my-dev-server 라는 간단한 명령만으로 접속할 수 있습니다.

만약 특정 호스트가 매우 자주 재생성되어 `REMOTE HOST IDENTIFICATION HAS CHANGED` 오류가 반복적으로 발생하는 임시 테스트 서버라면, 다음과 같은 옵션을 주의해서 추가할 수 있습니다.


Host temp-test-instance
    HostName 12.34.56.99
    User ec2-user
    IdentityFile ~/.ssh/test-key.pem
    # 아래 두 옵션은 보안 검사를 비활성화하므로 주의가 필요합니다.
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null
  • StrictHostKeyChecking no: `known_hosts` 파일에 키가 없거나 변경되었을 때, 질문하지 않고 자동으로 키를 추가하거나 업데이트합니다. 이는 편리하지만 중간자 공격에 취약해집니다.
  • UserKnownHostsFile /dev/null: 이 호스트에 대한 키 정보를 `known_hosts` 파일에 아예 기록하지 않습니다. 매번 연결할 때마다 서버 키를 확인하지 않게 됩니다.

경고: 이 옵션들은 SSH의 핵심 보안 기능을 비활성화하는 것입니다. 중요한 프로덕션 서버나 개인정보를 다루는 서버에는 절대로 사용해서는 안 됩니다. 오직 내용이 언제든 사라져도 상관없는, 신뢰할 수 있는 네트워크 내의 일회성 테스트 인스턴스에만 제한적으로 사용해야 합니다.

결론: 오류 메시지는 적이 아닌 친구

'REMOTE HOST IDENTIFICATION HAS CHANGED!'는 처음 마주하면 당황스럽고 위협적으로 느껴지는 오류입니다. 하지만 그 이면에는 우리의 연결을 안전하게 보호하려는 SSH의 충실한 보안 메커니즘이 있습니다. 이 경고는 "당신이 접속하려는 서버의 신원이 바뀌었습니다. 의도한 변경이 맞는지 확인해주세요."라고 우리에게 보내는 중요한 신호입니다.

이제 우리는 이 오류의 원인이 EC2 환경에서 IP 주소는 유지된 채 서버 인스턴스 자체가 교체되었을 때 주로 발생한다는 사실을 알았습니다. 또한, 가장 안전하고 권장되는 해결책은 `ssh-keygen -R ` 명령어를 사용하여 오래된 키 정보를 깔끔하게 제거하는 것임을 배웠습니다.

이 경험을 통해 우리는 단순히 문제를 해결하는 것을 넘어, SSH가 어떻게 우리의 통신을 보호하는지, 그리고 `known_hosts` 파일이 어떤 중요한 역할을 하는지에 대해 더 깊이 이해하게 되었습니다. 다음에 이 메시지를 다시 만나더라도, 당황하지 않고 "아, 서버가 바뀌었구나. 이전 기록을 지워주고 새롭게 신뢰 관계를 맺어야지"라고 차분하게 대처할 수 있는 능력을 갖추게 된 것입니다. 클라우드 시대를 살아가는 개발자와 엔지니어에게 이러한 기본적인 보안 원리를 이해하는 것은 더욱 강력하고 안정적인 시스템을 구축하는 밑거름이 될 것입니다.


0 개의 댓글:

Post a Comment