SSH는 어떻게 동작할까?

1

ssh

목록 보기
1/1

SSH

ssh란

secure shell은 network 보안 protocol로 암호화와 인증 매커니즘을 사용하여 'secure access', 'file transfer'과 같은 서비스를 구현하였다. 기존의 telnet과 FTP와 같은 경우는 그대로 데이터를 원문 text형식으로 전달했기 때문에, 보안상에 좋지 못했다. ssh는 network data를 암호화하고, 인증절차를 추가함으로서 안전하지 않은 network 환경에서 안전한 network 기능을 제공하였다. 이러한 이유로 오늘날에 ssh가 계속 쓰이게 되는 것이다.

ssh는 client-server model을 사용하여 두 참여자를 인증하도록 하고, 이들 사이의 data를 암호화한다. 이는 ssh로 접근할 때 먼저 remote login을 하도록 하여 안전성을 확보하고, data를 전송하거나 받을 때 해당 data를 암호화하여 hacker가 데이터에 접근해도 해독하지 못하도록 하는 것이다.

즉 다음과 같이되는 것이다.

--------                --------
|client|------SSH-------|server|
--------       |        --------
               X
               |
            --------
            |Hacker|
            --------

ssh 동작 방식

https://download.huawei.com/mdl/image/download?uuid=0b4c828d52fe460e8c434afb0d18cd28

출처: https://info.support.huawei.com/info-finder/encyclopedia/en/SSH.html

Connection setup

ssh는 TCP 연결을 기반으로 하고있기 때문에 server측에서 ssh server를 특정 port로 열어놓아야 한다. 기본적으로 22번 port를 사용하며, 상황에 따라 다른 port를 사용할 수 있다. server가 해당 port로 ssh server를 열어놓으면 client가 해당 port로 connection을 연결 요청을 보내어 client-server 간의 TCP 연결을 시도하는 것이다. TCP 연결에 성공하면 client와 server간의 version, 알고리즘 합의 단계를 거치게 된다.

Version 합의

ssh는 SSH1.XSSH2.0 두 버전을 가지는데, SSH2.0 버전이 더 나중에 나온 만큼 향상된 구조와 인증 기능, key 교환 기능, service 기능을 가진다. SSH server와 client는 다음의 process를 거쳐 어떤 SSH version을 사용할 지 결정한다.

  1. SSH server는 TCP connection을 통해서 SSH client에게 지원되는 SSH version 정보를 전달한다.
  2. client는 ssh version 정보를 받은 뒤에, 사용될 ssh version을 ssh server에게 전달한다.
  3. ssh server는 client로부터 전달된 ssh version 정보를 받은 다음에, 자신이 지원할 수 있는 지 확인하고 지원할 수 있다면 version 합의에 성공한다.

Algorithm 합의

SSH는 여러 type들에 대한 알고리즘을 사용하는데, session key를 만들기 위한 key교환 알고리즘, data암호화를 위한 대칭 암호화 알고리즘, 인증과 digital 서명을 위한 public key 알고리즘, 그리고 data 무결성 보호를 위한 HMAC 알고리즘 등이 있다. ssh server와 client는 각 type에 대해서 여러 알고리즘들을 지원하여, 각 type에서 사용되는 알고리즘을 결정하고 합의해야한다.

  1. SSH server와 client는 그들이 지원하는 알고리즘들을 서로 전달한다.
  2. SSH server와 client는 각 type에 사용될 알고리즘들을 합의한다. 서로 알고리즘이 매칭되면 알고리즘 합의가 끝난다. 만약, 알고리즘이 매칭되지 않으면 합의에 실패하고 SSH connection이 실패한다.

Key 교환

ssh server와 client는 key 교환 알고리즘을 사용하여, 암호화된 채널 사용을 위한 동적으로 공유된 session key와 session ID를 만들어낸다. session key는 전달을 위한 transimission에 사용되는 data를 암호화하기 위해 사용되며, session ID는 ssh connection을 사용하는 동안 인증 정보를 기억하기 위해 사용된다. 이 단계에서, client는 server에 대한 인증 작업을 완수한다. 이 과정은 server가 private key를 사용하여 message를 사인하고 client가 server pulbic key를 사용하여 signature를 검증한다.

ssh server와 client는 다음의 대칭 암호화를 위해 같은 session key를 가지고 있어야만 한다. key 교환의 안전성을 보장하기 위해 SSH는 secure method를 사용하여 session key를 생성한다. SSH server와 client는 같이 session key를 만들어내고, 서로 전달해주진 않는다. 대신 아래의 과정처럼 server는 public key와 함께 private key를 만드는데 사용되었던 소수 G, P를 함께 전달해준다. 즉, 직접적으로 session key를 전달하지 않으므로, key교환이 안전하게 이루어지는 것이다.

https://download.huawei.com/mdl/image/download?uuid=7ae23e5d704347c79c0298176b41777e

  1. SSH server는 소수 G, P와 private key b를 만들고 server의 public key인 yy = (G^b)%P 공식을 통해 만들어낸다.
  2. SSH server는 소수 G, P와 public key y를 SSH client에 전달한다.
  3. SSH client는 private key인 a를 만들어내고 client public key인 x를 다음의 공식을 통해 만들어낸다. x = (G^a)%P
  4. SSH client는 client public key x를 SSH server로 전달한다.
  5. SSH server는 대칭 key인 K를 다음의 공식을 통해 얻어낸다. K = (x^b)%P 또한, SSH client도 대칭 key인 KK = (y^a)%P 공식으로 만들어낸다. 이를 통해서 server와 client는 같은 session ID를 갖게되고, 안전하게 key를 교환할 수 있던 것이다.

자세한 알고리즘은 다음을 참고하면 된다.
https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange

user 인증

SSH client는 인증 요청을 SSH server로 전달한다. SSH client를 인증하게 되는데, SSH는 다음의 인증 모드를 제공한다.

  • 비밀번호 기반의 인증: client는 암호화된 username과 password를 server에 전달한다. server는 username과 password를 복호화하고, local에 저장된 username과 password를 비교한다. 이후 성공, 실패 여부를 client에게 제공한다.
  • public key 인증: client는 username과 public key와 public key 알고리즘을 사용하여 server 인증을 위한 data를 교환한다. 참고로 해당 public key는 위의 SSH key교환에서 사용된 public key가 아니다. 새로 ssh용으로 rsa와 같은 알고리즘으로 client가 생성해서, server에 client의 public key를 설정해주어야 한다. 이렇게하면 password 없이도 client가 인증이 가능하다.
  • password + public key 인증: client는 비밀번호와 public key 모두 같이 사용하여 인증이 가능하다.

Session 요청

인증에 성공하면 SSH client는 session request를 server에 전달한다. SSH client는 server에 session 생성 요청을 보내고, server는 이에 대한 응답을 전달해 ssh session이 이루어질 지 말지가 결정된다.

Session interaction

session이 생성되면 SSH server와 client는 해당 session을 통해 data를 안전하게 교환한다. 가령, SSH server와 client로부터 전달되는 data는 이전에 key 교환했던 session key(K)를 사용해 암호화, 복호화를 진행한다.

known_hosts 파일과 authorized_keys 파일

server가 특정 port에 ssh server를 open해있으면 ssh client가 SSH connection을 요청한다고 했다. 이때 server identity가 server의 public key로 검증되는데 다음과 같다.

  1. client가 server에 접근할 때 server가 private key를 만들고, 소수 G, P와 public key를 전달한다고 했다. 이 public key를 client측에서 가지고 있게 되는데, 이를 확인할 수 있는 곳이 바로 ~/.ssh/known_hosts이다. known_hosts 파일이 client 측에서 인증된 server의 public key를 담고 있는 것이다.

  2. 만약 client가 server에 ssh session을 열려고 하지만 key 교환에서 실패했다면, 이는 known_hosts에 있는 기존의 ssh record 정보와 충돌하였기 때문이다. 여러가지 이유가 있겠지만, 기존 ssh server가 다시 동작했을 경우가 크다.

  • cat ~/.ssh/known_hosts
192.168.182.16 ssh-ed25519 ...

다음과 같이 192.168.182.16 ssh server에 대한 key교환 public key가 저장된 것을 볼 수 있다.

만약 재생성하고 싶다면 다음의 명령어를 사용하면 된다.

ssh-keygen -R 192.168.182.16

192.168.182.16 public key를 삭제하는 것이다.

그런데 여기서 오해하면 안될 것이 known_hosts는 key 교환에서 사용되는 server의 public key이다. 즉, 로그인 할 때 사용하는 인증키가 아니라는 것이다.

key기반을 통해서 로그인하는 매커니즘은 다음과 같다.

  1. client가 ssh key쌍을 만든다.
  2. client가 ssh-add를 통해서 만들어진 private key를 등록한다.
  3. server가 client의 public key를 등록한다.

이때 server에 저장되는 client의 로그인 용 public key들은 authorized_keys 파일에 저장된다. 따라서, authorized_keys 파일은 server측에서 로그인을 위해 client의 public key를 저장하는 용도로 쓰이는 것이다.

정리하면 다음과 같다.

  • known_hosts: client측에서 server에 대한 key교환 public key를 유지하는 파일로, 로그인 인증과는 관련이 없다.
  • authorized_keys: server측에서 client에 대한 로그인 인증을 위해 client public key들을 보관하는 파일로, session을 암호화를 위한 key교환과는 관련이 없다.

0개의 댓글