
회사 업무를 하다가 JAVA로 SSH 접속을 구현해야 할 일이 생겨서 Jsch 라이브러리를 사용하게 되었습니다. 해당 라이브러리를 사용하면서 실제로 SSH 접속이 어떤 방식으로 이루어지는지 정리해보고자 글을 작성하였습니다.
Window 환경에서 리눅스 가상머신을 공개키 기반 SSH로 접속해보고 그 원리를 정리해보았습니다.
공개키 기반의 SSH 접속의 장점
비공개 서버에 접속하기 위해서는 인증 절차를 거쳐야 한다. 비밀번호를 네트워크를 통해 보내는 인증은 해당 네트워크 상에서 ID 및 비밀번호가 그대로 노출될 위험성이 존재하고, 접속할 때마다 입력해야 하는 번거로움이 존재한다. 공개키 기반으로 SSH 접속을 하게 되면 좀 더 안전하게 접속할 수 있으며 암호를 생략하고 원격 호스트로 접속할 수 있다.
윈도우 환경에서 openSSH 클라이언트가 설치가 완료된 상태에서 진행하였습니다.
키 페어 생성
관리자 권한으로 cmd 창을 실행한 후 'ssh-keygen' 명령어를 입력하여 키 페어를 생성한다.

1. 위의 명령어를 입력하면 키 페어를 저장할 경로를 묻는데 아무것도 입력하지 않고 엔터키를 누르면 기본적으로 지정된 경로에 자동으로 저장된다.
2. 이후 Passphrase를 입력하라는 메시지가 나온다. Passphrase는 개인키 자체에 대한 비밀번호로써 이것을 저장하게 되면, 누군가가 개인키를 탈취하더라도 Passphrase를 모르면 서버에 접속할 수 없게 되어, 한 층 더 강력한 보안을 할 수 있게 된다. 지금은 생성하지 않고 진행하겠다.
키 페어 생성 작업이 성공하게되면 위와 같은 그림이 출력되고 해당 키 페어가 생성된 폴더를 가보면 다음과 같이 생성된 것을 확인할 수 있다.

서버로 공개키 전송
먼저, 접속하려는 서버의 root 계정에 접속 후 생성된 공개키(id_rsa.pub)를 해당 서버로 전송해야 한다.
ssh (서버 아이디)@(ip 주소)

위의 명령어를 입력 후 비밀번호를 입력하여 root 계정으로 접속이 완료된다.
접속 후 ls -al 명령어를 통해 .ssh 디렉터리 존재 여부를 확인 후에 없다면 mkdir ~/.ssh 명령어를 입력하여 .ssh 디렉터리를 생성해준다.

윈도우로 돌아와서 이전에 생성된 공개키(id_rsa.pub)를 메모장으로 열어 복사한다.

다시 커맨드 창으로 돌아와서 .ssh 디렉터리에서 authorized_keys라는 파일을 생성하면서 공개키 전문을 저장해야 한다.
echo (공개 키 전문) >> ~/.ssh/authorized_keys
위의 명령어를 입력 후 아래와 같이 공개키 전문이 저장되었음을 확인할 수 있다.

접속
위의 과정을 완료한 후 서버와의 연결을 끊고 다시 접속을 시도해보면 아래와 같이 비밀번호를 입력하지 않고 바로 접속이 가능한 것을 확인할 수 있다.

SSH 동작 원리
위에서 실습한 내용을 바탕으로 SSH의 동작 원리를 자세히 알아보자.
SSH의 동작 원리를 크게 서버 인증, 사용자 인증, 데이터 암호화 과정으로 나누어 보았다.
서버 인증
서버에서 SSH를 설치 후 처음 구동될 때 내부적으로 비대칭키(공개키와 비밀키)가 생성된다. 클라이언트가 서버에 접속을 시도하면 공개키를 받을지 묻는 메시지에서 "Yes"를 선택하게 되면 클라이언트에 있는 .ssh/known_hosts 파일에 위에서 생성된 공개키가 저장된다.

[서버 인증 과정]
- 클라이언트는 난수 값을 발생시키고 난수값에 대한 해시값을 생성해 저장한다.
- 난수값을 공개키로 암호화하여 서버로 전송한다.
- 서버에서는 암호화된 데이터를 비밀키로 복호화한 후 난수값을 알아낸다.
- 복호화된 난수값을 통해 해시값을 다시 만든 후 클라이언트로 다시 전송한다.
- 클라이언트에서는 저장하고 있던 해시값과 서버로부터 받은 해시값을 비교해 정상적인 서버인지 확인한다.

사용자 인증
사용자 인증은 서버 인증과 원리는 같지만, 서버와 클라이언트의 역할만 바뀐다. 사용자 인증은 클라이언트에서 비대칭키(공개키와 비밀키)를 생생한다. 여기서 생성된 공개키는 사용자가 서버에 있는 .ssh/authorized_keys 파일에 사전에 복사해둔다. 서버는 공개키를 가지고 있고 클라이언트가 비밀키를 가지고 있게 된다. (위의 실습 과정 참고)
[사용자 인증 과정]
- 서버에서 난수 값을 생성한 뒤 해시값을 만들어 저장한다.
- 서버에서 난수값을 암호화해 클라이언트로 전송한다.
- 클라이언트에서 암호화된 난수값을 비밀키로 복호화한다.
- 복호화된 난수값을 통해 해시값을 다시 만든 후 서버로 다시 전송한다.
- 서버에 저장하고 있던 해시값과 클라이언트로부터 다시 받은 해시값을 비교해 정상적인 사용자인지를 확인한다.

데이터 암호화
서버 인증과 사용자 인증이 끝나면, 비대칭 키를 통해 클라이언트와 서버는 대칭키 (세션키)를 서로 교환한다.
그 후 통신되는 모든 데이터는 세션키를 통해서 암호화가 이루어지고, 통신이 종료되면 세션키도 사용할 수 없게 된다.
참고