관리자가 서버를 관리할 때 직접 서버에서 접속하는 방식과 외부에서 네트워크를 통해 접속하는 방식이 있다.
이번 시간에는 외부에서 네트워크를 통해 원격 접속할 때 사용하는 방식 중 ssh에 대해 배운다.
telnet을 과거에 많이 사용했다.텔넷의 경우 평문전송방식으로 공격자가 중간에서 탈취할 시, 혹은 탈취해서 정보를 변조할 수 있어 안전하지 않다.
SSH는 암호키를 사용하여 시스템 간 통신할 때 데이터를 암호화한다. 따라서 중간에 데이터를 가로채거나 변조하는 행위가 어려워 현재 기본적으로 리눅스에서 사용된다.
SSH
[Protocol] SSH의 개념, 통신 과정(feat. OpenSSH)
SSH(시큐어 셸, SecureSHell) 란? : 네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고 다른 시스템으로 파일을 복사할 수 있도록 해 주는 응용 프로그램 또는 그 프로토콜
co-no.tistory.com
이전에도 언급했듯 시스템에 원격 접속할 때 보안을 위해 SSH는 데이터를 암호화해서 전송한다.
우리가 네트워크 시간에도 배웠듯, 데이터를 암호화하는 과정은 크게 대칭키/비대칭키 방식이 있고, SSH는 둘다 사용한다.
비대칭키 암호화 알고리즘은 데이터를 암호화하고 복호화할 때 사용하는 키가 다른 암호화 알고리즘을 의미한다.
이 때 사용하는 키가 공개키(Public)와 개인키(Private)키다. 공개키는 데이터를 암호화하여 전달하며 공개키와 쌍으로 이뤄진 개인키를 이용하여 암호화된 데이터를 복호화 하는데 사용한다.
대칭키 암호화 알고리즘은 암호화, 복호화의 키가 같은 알고리즘을 의미한다. 이 때 사용하는 키를 Secret Key(비밀키)라고 한다.
우선은 SSH를 통해 서버 시스템의 user02사용자로 원격 접속하는 상황을 봐보자.

1] SSH 접속 요청 및 KEX 알고리즘 협상
- 클라이언트가 서버에 SSH 접속을 요청한다.
- 서버는 자신이 지원하는 KEX(Key Exchange) 알고리즘 목록을 보낸다.
- 클라이언트는 "OK. 그 알고리즘 써서 내가 받을게" 라고 응답하며 사용할 알고리즘을 합의한다.
- KEX 알고리즘은 클라이언트와 서버가 안전하게 세션키를 교환하는 방식을 정의한다.
[방법 A] RSA 방식
클라이언트가 비밀키를 생성해 서버에게 안전하게 배달하는 전통적인 암호화 전달 방식이다.
- 공개키 전달: 서버가 자신의 호스트 공개키(Public Key)를 클라이언트에게 보낸다.
- 서버의 키쌍은 SSH Server 설치 시 자동으로 생성되며, Default로
/etc/ssh/위치에 저장된다.- Public Key:
_key.pub(예: ssh_host_ecdsa_key.pub) - Private Key:
_key(예: ssh_host_ecdsa_key)
- Public Key:
- 서버의 키쌍은 SSH Server 설치 시 자동으로 생성되며, Default로
- 난수 생성: 클라이언트는 대칭키로 사용할 랜덤 숫자(세션키)를 생성한다.
- 클라이언트가 서버에 접속할 때 서버의 공개키가 클라이언트에 저장되어 있지 않으면 SSH서버의 공개키를 저장하기 위한 메시지가 출력된다.
- ssh 접속할 때 (yes/no)? → yes 입력: 서버의 공개키를 클라이언트에 저장한다.
- 파일이 저장되는 위치는 접속을 시도한 사용자의 홈 디렉토리 아래
.ssh/known_hosts파일에 저장된다.- 서버로부터 받은 Public Key가 'known hosts'에 없다면, 해당 Key에 대한 지문을 출력하여 User에게 확인하는 과정이 존재한다.
- cat을 통해 확인해보면 이 파일의 내용은 서버에서 제공한 공개키 파일의 내용과 같다.
- IP주소 뒤에 ecdsa 암호화 알고리즘 사용하는 것을 확인할 수 있는데, 서버에서 이 공개키 파일의 내용을 확인하고 싶을 경우 /etc/ssh/ 디렉토리에서 확인한다.
- ssh_host_ecdsa_key를 포함한 파일 목록을 확인해보면 .pub 확장자가 추가된 파일이 서버의 ecdsa 암호화 알고리즘의 공개키 파일인 것을 알 수 있는데, 클라이언트의 known_hosts에 저장된 파일의 내용과 동일하다.
- known_hosts 파일의 역할:
- 한 번 저장된 서버 호스트 키는 이후 접속 시 자동으로 검증된다.
- 저장된 키와 서버가 보내는 키를 비교하여, 일치하면 바로 다음 단계로 진행한다.
- 불일치하면 경고 메시지가 출력되고 접속이 차단된다.
- 이는 중간자 공격(누군가 중간에서 통신을 가로채는 것)이나 서버 변경을 감지하기 위한 보안 메커니즘이다.
- 서버가 바뀌었거나 재설치되었을 경우, known_hosts 파일에서 해당 서버 정보를 삭제하고 다시 접속하면 새로운 키를 저장할 수 있다.
- 클라이언트가 서버에 접속할 때 서버의 공개키가 클라이언트에 저장되어 있지 않으면 SSH서버의 공개키를 저장하기 위한 메시지가 출력된다.
- 암호화: 클라이언트는 이 난수를 서버의 공개키로 암호화한다.
- 클라이언트는 랜덤 데이터(난수)를 생성한다.
- 이 난수를 서버로부터 받은 Public Key로 암호화한다.
- 암호화된 난수를 서버에게 전송한다.
- 서버의 Public Key로 암호화했기 때문에, 서버의 Private Key를 가진 서버만 이 값을 복호화할 수 있다.
- 클라이언트는 랜덤 데이터(난수)를 생성한다.
- 전송 및 복호화: 서버는 자신의 개인키로 이를 복호화하여 난수를 얻는다.
- 서버는 자신의 Private Key로 암호화된 난수를 복호화한다.
- 복호화한 원본 난수 값을 해시 처리하여 해시값을 생성한다.
- 이 해시값을 클라이언트에게 전송한다.
- 서버는 자신의 Private Key로 암호화된 난수를 복호화한다.
- 결과: 양측이 동일한 난수를 공유하며 이를 세션키로 사용한다.
- 클라이언트는 자신이 보냈던 원본 난수를 같은 방식으로 해시 처리한다.
- 서버로부터 받은 해시값과 자신이 계산한 해시값을 비교한다.
- 두 해시값이 일치하면 "서버가 진짜 Private Key를 가지고 있구나, 진짜 서버가 맞네!" 확인된다.
- 이제 이 난수 값을 기반으로 세션키(대칭키)를 생성한다.
- 클라이언트는 자신이 보냈던 원본 난수를 같은 방식으로 해시 처리한다.
[방법 B] 디피-헬만 방식
비밀키를 직접 보내지 않고, 양측이 정보를 조합해 같은 결과를 각자 계산해내는 현대적인 방식이다.
- 매개변수 합의: 누구나 알 수 있는 숫자 P=23, G=5를 공유한다.
- 비밀 숫자 선정: 각자 자신만 아는 숫자(a, b)를 고른다. 예시로 a=3, b=4라고 해보자.
- 결과값 교환: 각자 계산한 공개값(A, B)을 서로에게 전달한다.
- 클라이언트: A = G^a mod P = 5^3 mod 23 = 10
- 서버: B = G^b mod P = 5^4 mod 23 = 4
- 키 완성 (상세 과정): 받은 값에 자신의 비밀 숫자를 거듭제곱하여 최종 키를 도출한다.
- 클라이언트 계산: 서버로부터 받은 B를 자신의 비밀 숫자 a만큼 제곱한다.
- Key = B^a mod P = (G^b)^a mod P = G^ab mod P = 4^3 mod 23 = 18
- 서버 계산: 클라이언트로부터 받은 A를 자신의 비밀 숫자 b만큼 제곱한다.
- Key = A^b mod P = (G^a)^b mod P = G^ab mod P = 10^4 mod 23 = 18
- 동일성 증명: 지수 법칙(G^ab = G^ba)에 의해 두 결과값은 일치한다.
- 보안성: 해커는 공개된 A와 B를 훔쳐도, 로그 계산의 어려움(이산 로그 문제) 때문에 비밀 숫자 a, b를 알아낼 수 없어 최종 키를 계산하지 못한다.
- 클라이언트 계산: 서버로부터 받은 B를 자신의 비밀 숫자 a만큼 제곱한다.
RSA, Diffie-Hellman 방식 중 하나를 택해 세션키(대칭키)를 만든 뒤, 서버↔클라이언트 간에 통신 터널이 생성된다.
세션 인증이 완료되어 암호화된 채널이 구축되면
이제 "이 사람이 정말 접속할 권한이 있는 사람인가?"를 확인해야 한다.

아무리 안전한 암호화 채널을 만들었어도, 접속하는 사람 자체가 공격자라면 의미가 없기 때문이다.
사용자 인증 방식은 크게 2가지가 있다.
1] Password 인증
가장 기본적인 방식으로, 사용자 이름과 비밀번호를 입력해서 인증하는 방식이다.
- 동작 과정
- 사용자가 비밀번호 입력
- 세션키로 암호화되어 서버에 전송
- 서버가 /etc/shadow에서 비밀번호 확인
- 일치하면 접속 허용
- 장점
- 간단하고 직관적
- 별도 준비 없이 바로 사용 가능
- 단점
- Brute-Force 공격에 취약 (무작위 대입 공격)
- 비밀번호를 잊어버리면 곤란
- 매번 입력해야 함
- 보안상 권장하지 않음
2. Key-Pair 인증 (공개키 인증)
클라이언트가 키 쌍을 만들어서 인증하는 방식으로, Password보다 훨씬 안전하다.

인증 과정
- 클라이언트: "user02로 Key-Pair 인증할게요"
- 서버:
authorized_keys에서 등록된 Public Key 확인 - 서버: 랜덤 Challenge 데이터 생성 → 클라이언트에 전송
- 클라이언트: Private Key로 Challenge에 서명 → 서버에 전송
- 서버: Public Key로 서명 검증 → "Private Key 가진 게 맞네!" → 접속 허용
어 뭔가… 세션키를 생성하는 과정과 사용자 인증을 하는 과정이 유사하다..?
| 단계 | 누구를 확인? | Public Key 소유 | Private Key 소유 | 증명하는 쪽 |
| 세션 인증 | 서버 | 서버 | 서버 | 서버가 증명 |
| 사용자 인증 | 사용자 | 클라이언트 | 클라이언트 | 클라이언트가 증명 |
AWS EC2에 ssh 접속을 하는 거는?
사실 이 글을 적게 된 경위가 ssh로 EC2 접속을 하고 있었는데 원리가 궁금했기 때문이었다.
AWS EC2 접속은 우리가 배운 세션 인증과 사용자 인증이 모두 일어나는 과정이다.
[1] AWS 콘솔: 키 페어 생성 및 .pem 다운로드
- 인스턴스 생성 설정 중 ‘키 페어(로그인)’ 섹션에서 새 키 페어 생성을 클릭한다.
- 이름을 입력하고 생성 버튼을 누르면 브라우저를 통해 개인키(.pem 파일)가 내 로컬 컴퓨터로 다운로드된다.
[2] AWS 서버: 공개키 자동 등록
- 인스턴스가 생성되는 동안, AWS는 내가 선택한 키 페어의 공개키(Public Key)를 인스턴스 내부의 특정 경로(~/.ssh/authorized_keys)에 자동으로 심어준다.
- 이로써 서버는 ‘이 공개키와 쌍을 이루는 개인키를 가진 사람만 들어올 수 있다’는 기준을 갖게 된다.

[3] SSH 접속 시도: 세션 및 사용자 인증
사용자가 ssh -i "[파일명].pem" ec2-user@[Public-IP] 명령을 입력하면 아래 과정이 순차적으로 일어난다.
[3-1] 세션 인증 (암호화 터널 구축) - .pem 아직 안 씀
이 단계에서 -i "[파일명].pem" 옵션은 아직 사용되지 않는다.
단지 "나중에 사용자 인증할 때 이 개인키 파일을 쓸게"라고 SSH 클라이언트에게 알려준 것뿐이다.
- 클라이언트가 서버에 SSH 접속을 요청한다.
- 서버가 자신의 호스트 공개키를 보낸다.
- 이건 AWS가 인스턴스 생성 시 자동으로 만든 서버 자체의 키이다.
- 내가 다운받은 .pem 파일과는 완전히 별개이다.
- 클라이언트는 이 키를
~/.ssh/known_hosts에 저장한다.- 처음 접속하면 "이 서버 믿을래? (yes/no)"가 뜨는 이유다.
- 디피-헬만 방식으로 양측이 동일한 세션키(대칭키)를 각자 계산해낸다.
- 이제 암호화된 통신 터널이 완성된다.
이 시점까지 .pem 파일은 건드리지도 않았다.
[3-2] 사용자 인증 (나 확인) - 여기서 .pem 사용
암호화 터널이 뚫린 후에야 "이 사람이 접속 권한이 있는가?"를 확인한다.
- 클라이언트가 "ec2-user로 Key-Pair 인증할게요. 이 공개키로 인증할래요"라고 서버에 알린다.
- 서버가
~/.ssh/authorized_keys에서 해당 공개키가 등록되어 있는지 확인한다.- AWS가 인스턴스 생성 시 자동으로 심어둔 공개키다.
- 서버가 랜덤 Challenge 데이터를 생성해서 클라이언트에 보낸다.
- 클라이언트가 -i 옵션으로 지정한 .pem 파일(개인키)로 이 Challenge에 서명한다.
- 이 시점에 비로소 .pem 파일이 사용된다!
- 서명된 응답이 암호화된 터널을 통해 서버로 전송된다.
- 서버가 등록된 공개키로 서명을 검증한다.
- "이 사람이 개인키를 진짜 가지고 있구나!" → 접속 허용
[3-3] 접속 완료
서버가 사용자 인증까지 통과시키면 최종적으로 쉘 접근이 허용된다.
정리
SSH 접속은 크게 두 단계로 이루어진다.
1단계: 세션 인증 - "이 서버가 진짜 서버 맞아?"를 확인하고, 안전한 암호화 터널(대칭키)을 구축한다. 이 과정에서 서버의 호스트 키 쌍이 사용된다.
2단계: 사용자 인증 - "이 사람이 접속 권한이 있는 사람 맞아?"를 확인한다. Password 방식 또는 Key-Pair 방식이 있는데, Key-Pair 방식에서는 클라이언트의 키 쌍이 사용된다.
핵심은 두 단계에서 사용하는 키 쌍이 완전히 다르다는 점이다.
| 단계 | 목적 | 사용되는 키 쌍 | 키 생성 주체 |
| 세션 인증 | 서버 확인 + 암호화 터널 구축 | 서버의 호스트 키 쌍 | 서버 (SSH 설치 시 자동 생성) |
| 사용자 인증 | 사용자 권한 확인 | 클라이언트의 키 쌍 | 클라이언트 (ssh-keygen 또는 AWS) |
AWS EC2 접속도 결국 이 원리 그대로다.
.pem 파일은 사용자 인증용 개인키일 뿐, 세션 인증과는 아무 관련이 없다.
ssh -i 명령을 실행하면 먼저 디피-헬만으로 암호화 터널을 뚫고, 그 다음에야 .pem 파일로 클라이언트 자기 자신을 증명하는 것이다.
'Infra' 카테고리의 다른 글
| 최신 AWS SAA 후기(2026년 2월) (0) | 2026.02.23 |
|---|---|
| 오픈 소스 기여 도전기 Ep.완 (0) | 2026.01.12 |
| 오픈 소스 기여 도전기 Ep.2 (0) | 2026.01.11 |
| 오픈 소스 기여 도전기 Ep.1 (2) | 2026.01.11 |
| 네트워크 자문자답 (0) | 2025.12.29 |