SSH 프로토콜과 Tunneling 이해하기

​ ​

지금까지 아무 생각없이 SSH를 사용하다가 한번 정리해보았습니다.

​ ​

SSH Protocol

SSH는 Secure Shell의 약자입니다. SSH는 한마디로 정의하면, 네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고 다른 시스템으로 파일을 복사할 수 있도록 해 주는 프로토콜입니다. VPN을 구성하는 것보다 가격이 저렴하고 쉽게 연결할 수 있어 많이 사용됩니다.

MacOS에는 OpenSSH 클라이언트와 서버가 내장되어 있기 때문에 바로 사용할 수 있습니다. SSH는 22번 포트 를 사용하며, 크게 다음의 3가지를 제공합니다.

​ ​

1. Authentication

SSH-Auth

SSH는 public key와 private key를 사용하는 비대칭 암호방식을 사용합니다. 간단히 설명하면, public keyprivate key가 모두 있어야 인증이 되는 방식입니다. 각자 private key는 외부 유출없이 가지고 있고, public key만 네트워크를 통해 전달합니다. SSH는 RSA, DSA 등 다양한 인증 방식을 지원합니다.

$ ssh-keygen
$ cat ~/.ssh/id_rsa.pub

ssh-keygen 명령어를 통해 ssh 키를 생성하고 ~/.ssh/id_rsa.pub에서 public key를 확인할 수 있습니다.

​ ​

2. Encryption & Integrity

SSH는 네트워크를 통해 전달되는 데이터를 암호화합니다. 3DES, blowfish 등 여러 가지 암호화 방식을 제공하며, 새로운 암호화 기법을 추가할 수도 있습니다.

그리고 SSH는 네트워크를 통해 받은 데이터가 변경되지 않았음(무결성)을 보장해줍니다. 이를 위해 MAC(Message Authentication Code) 이라는 알고리즘을 사용합니다.

MAC-Algo

MAC 알고리즘은 다음과 같이 동작합니다. SSH 클라이언트가 서버로 메세지를 보내면, MAC 알고리즘을 통해 secret key를 입력받아 MAC 코드를 생성합니다. 그리고, 임의 길이의 암호화 된 메시지와 MAC 코드를 SSH 서버로 보냅니다.

서버에서는 다시 메세지와 서버의 secret key를 조합하여 MAC 코드를 만들고, 클라이언트로부터 받은 MAC 코드와 비교하여 인증을 진행하게 됩니다.

​ ​

4. Compression

SSH는 네트워크 상에서 데이터를 전송하고 수신할 때 압축 과정을 거칩니다. 이를 통해 전송 데이터의 크기를 줄여 네트워크 비용을 낮출 수 있습니다.

​ ​

SSH Tunneling

SSH Tunneling은 터널을 통해 데이터를 주고받는다 해서 붙여진 이름입니다. 앞서 얘기했던 것처럼 연결, 통신은 모두 암호화되며 SMTP, IMAP 등 여러 가지로 사용될 수 있습니다.

Direct로 보내면 네트워크 층에서 수 많은 공격을 받을 수 있기 때문에 SSH를 통해 다른 Application에 연결하는 것이 안전합니다. SSH Tunneling에는 다음과 같이 두 가지 방법이 있습니다.

​ ​

Local port forwarding

SSH-Local

$ ssh -L port1:host_name:port2 server_name

로컬에서 서버에 있는 MySQL과 SSH 연결을 한다고 가정해보겠습니다. Local port forwarding은 로컬에 설치된 MySQL 클라이언트의 3306 포트가 연결된 SSH Tunnel을 거쳐 서버에 있는 MySQL 서버의 3306 포트와 연결됩니다. 이를 통해 직접 서버의 데이터베이스에 안전하게 접근할 수 있으며 요청을 보내서 서로 데이터를 주고 받을 수 있습니다.

​ ​

Remote port forwarding

SSH-Remote

$ ssh -R port1:host_name:port2 server_name

이번에는 로컬에서 파이썬 웹 애플리케이션을 개발 중인데 친구에게 보여주고 싶다고 가정 해보겠습니다. 아직 공개 IP 주소를 제공하지 않기 때문에 인터넷을 통해 직접 기기에 연결할 수 없을 겁니다. 라우터에서 NAT를 구성하여 해결할 수 있지만 라우터의 구성을 변경해야하므로 번거롭습니다. 이럴때 Remote port forwarding을 통해 쉽게 해결할 수 있습니다.

먼저 port1의 서버에서 port2로 로컬 트래픽을 전달하는 SSH 터널을 생성합니다. 이후 로컬에서 port2의 서버에 연결하면 실제로 SSH 터널을 통해 데이터를 요청하는 것을 확인할 수 있습니다.

OSI 7계층에서 생각해보면 SSH는 Application - Transport - Network 계층에 걸쳐있습니다. Application 계층에서 포트를 연결하면 Transport 계층의 TCP 통신을 통해 전달되고, Network 계층을 통해 목적지로 이동하게 됩니다.

​ ​