
클라우드에서 VM을 띄워봤다면 SSH에 대해 알고있을 것이다. 보통 리눅스 서버를 올리면 연결은 SSH를 이용한다. 필자도 SSH를 처음 접한게 클라우드를 이용하면서이다.
사용하는 방법은 익숙하나 어떤 로직으로 동작하는지 잘 알지 못했는데 이번기회에 정리해 보려 한다.
SSH(Secure Shell)는 22번 Port를 이용하며 시스템을 원격으로 접속하여 명령/파일 등을 전송할때 사용하는 프로토콜이다.
과거에는 telnet, rsh등을 이용하였으나 해당 프로토콜들은 통신이 암호화되지 않아 스니핑에 취약했다. SSH는 대칭키를 이용해 세션을 암호화한다.

SSH 프로토콜 서비스는 2종류가 있는데 SSH Communication Security에서 개발한 SSH와 BSD 라이센스로 개발된 OpenSSH가 있다.
윈도우나 레드헷, Rocky 등에서 OpenSSH가 기본적으로 설치되어 이용할 수 있다. 이후 진행할 설명도 OpenSSH를 기준으로 진행하겠다.
SSH는 Client-Server 모델을 사용한다. SSH 연결을 위해 먼저 TCP 연결을 맺고, 프로토콜 버전/사용할 알고리즘을 협상한 뒤, 대칭 암호화를 위한 세션 키를 생성한다. 이후 사용자 인증 후 데이터 교환을 위해 세션을 수립하게 된다.
각 과정을 하나씩 자세히 설명하여 보겠다.

SSH 연결 전 서버는 22번 포트에서 연결 요청을 기다리고 있다. 클라이언트가 22번 포트로 연결을 요청하면 TCP 연결을 진행하고 이후 22번 포트를 이용해 통신을 진행한다.
SSH는 SSH1.X, SSH2.0 두가지 버전이 존재한다. 아래 과정을 통해 서버와 클라이언트는 사용할 버전을 결정하게 된다.
1. 서버에서 지원하는 SSH 버전 정보를 클라이언트에거 보낸다.
2. 클라이언트는 해당 내용을 받고 지원하는 범위 내에서 사용할 버전을 결정해 서버에 보낸다.
3. 서버가 그 버전을 지원하면 버전 협상에 성공한다.
SSH는 여러 종류의 알고리즘을 사용한다. ex) 키 교환(세선 키 생성), 대칭 암호(데이터 암호), 공개키(전자서명/인증), HMAC(무결성)
서버와 클라이언트는 가 유형별 어떤 알고리즘을 사용할지 정해야 한다.
1. 서버와 클라이언트는 자신이 지원하는 알고리즘 목록을 보낸다.
2. 각 유형별 공통 지원 알고리즘을 매칭하며 최종 알고리즘을 정한다.
서버와 클라이언트는 키 교환 알고리즘을 사용해 공유 세션 키와 세션 ID를 동적으로 생성한다. 세션 키는 데이터 암호화시 사용하며 연결을 진행할 때 마다 새로 생성된다. 세션 ID는 인증 과정에서 SSH 연결 식별에 사용한다. 해당 단계에서 서버의 신원 인증도 진행한다(서버 개인키로 메세지 성명 후 전달 후 클라이언트에서 서버 공개키로 검증)
데이터 암호에 사용하는 세션키(대칭키)를 직접 전송하지 않고 서버/클라이언트에서 각자 생성한다. 수학적인 원리에 기반해 키를 직접 전달하지 않아도 동일한 키를 생성하게 한다.
SSH 키 교환(디피-헬만 키 교환)
최근에는 디피-헬만 이외에 curve25519-sha256같은 개선된 알고리즘을 사용하나 디피-헬만 기준으로 설명하겠다.

서버: K=(x^b)%P
클라이언트: K=(y^a)%P
※ 왜 동일한 값이 생성되는가?
수학적으로 검증 가능하다
서버
개인키 b, 공개키 y=(G^b)%P, 클라이언트 공개키 x

클라이언트
개인키 a, 공개키 x=(G^a)%P, 클라이언트 공개키 y

두가지 방식이 있다. 비밀번호를 이용한 인증과 공개키를 이용한 인증 방법이다.
공개키 인증의 경우 클라이언트가 자신의 개인키로 서명하고 서버가 클라이언트 공개키로 검증하여 비밀번호 없이 로그인을 구현하며 보안성이 높으므로 일반적인 경우 비밀번호 인증 방식보다 키 기반 인증을 권장한다
인증 성공 시 클라이언트는 서버에 세션 수립을 요청하고 서버가 응답한다.
세션 수립 시 서버와 클라이언트는 세션을 통해 데이터를 교환한다. 이 때 양측이 전달하는 데이터는 세션키로 암호화 되어 전달된다.
ssh를 이용해 접속 시 사용자 이름과 IP/DNS 를 적고 해당 사용자의 비밀번호를 입력한다.
ssh [username]@[IP or DNS]
최초 접속 시 서버의 공개키가 클라이언트에 저장되어 있지 않으므로 저장하기 위해 입력을 받는데 yes를 입력하면 저장 후 비밀번호를 입력받고 연결한다.
공개키가 저장되는 위치는 홈디렉토리에 .ssh/known_hosts 이다.


원격 접속을 하지 않고 명령만 실행하는것도 가능하다.
이 경우 명령 실행 결과만 반환하고 연결은 되지 않는다.
ssh [username]@[IP or DNS][command]
키 기반 인증을 위해 개인키/공개키 쌍을 생성해야 한다.
키는 생성 시 저장 위치를 따로 지정하지 않는다면 홈디렉토리의 .ssh/id_rsa에 개인키가 저장되고 .ssh/id_rsa.pub에 공개키가 저장된다.
ssh-keygen [optoin][argument]
공개키를 접속하고자 하는 시스템에 전달할때 해당 명령어를 이용하며 pub파일이 전송된다.
전송 받은 키는 홈디렉토리의 .ssh/authorized_keys 에서 확인할 수 있다.
ssh-copy-id [option][argument] [username]@[IP or DNS]
scp(Secure Copy)는 기존의 cp 명령어와 동일한 방식으로 이용가능하다.
scp [option][source] [username]@[IP or DNS]:[destination]
디렉토리는 -r 옵션 이용
sftp(Secure File Transfer Protocol)은 기존의 ftp와 유사하게 이용가능하다.
sftp [username]@[IP or DNS]
put을 통해 클라이언트에 있는 파일을 서버로 전송할 수 있다.
put [source][destination]
get을 통해 서버에 있는 파일을 클라이언트로 전송할 수 있다.
get [source][destination]
OpenSSH 구성 파일들은 /etc/ssh 폴더 내부에 존재한다.
| 파일 이름 | 설명 |
|---|---|
| moduli | 디피-헬만 알고리즘에 사용되는 파라미터 |
| ssh_config | OpenSSH 클라이언트 설정 파일 |
| sshd_config | OpenSSH 서버 설정 파일 |
| sshhost{암호화 알고리즘}_key | 개인키 |
| sshhost{암호화 알고리즘}_key.pub | 공개키 |
NTP란 컴퓨터 시스템의 시간을 동기화할때 사용하는 프로토콜이다. NTP 서버는 원자시계와 같은 정밀한 시간을 측정하는 장비로부터 시간정보를 얻어 제공한다.
NTP서버는 계층 구조를 이루고 있으며 Stratum으로 구분한다.
Stratum 0은 가장 상위 계층으로 원자시계, GPS등과 같은 고정밀 장비로 정확한 시간을 측정하고 Stratum 1에 전달한다.
Stratum 1~15는 상위 계층으로 부터 시간정보를 동기화하고 상위계층일수록 정확한 시간 정보를 가지고 있다.

최신 버전의 리눅스는 기존에 시간 동기화에 사용하던 도구인 ntp 대신 chrony를 사용
한다. chrony는 chronyd, chronyc로 구성되어 있다,
chronyd: 백그라운드에서 동작하는 실제 시간 동기화를 담당하는 데몬
chronyc: chronyd를 제어에 사용하는 사용자 명령
chronyd는 주기적으로 시스템 시간을 조정한다. 네트워크가 연결되어 있으면 NTP 프로토콜을 이용해 시간을 동기화하고 접근이 불가능할 경우 마지막으로 계산된 시간을 참고해 조정한다. 또는, chronyc에 의해 수동으로 설정되기도 한다.
이외에 임의로 시간을 변경할 때 date, timedatectl 명령어를 사용하기도 한다.
※ 참고자료
엔터프라이즈 리눅스 핵심 운영 가이드 vol.1
https://info.support.huawei.com/info-finder/encyclopedia/en/SSH.html
https://www.ssh.com/academy/ssh/telnet
https://guslabview.tistory.com/452