SSH 를 이용한 Linux 보안 원격 액세스

CompTIABeginner
지금 연습하기

소개

이 실습에서는 Secure Shell (SSH) 프로토콜을 사용하여 Linux 시스템에 대한 원격 액세스를 안전하게 보호하는 기본 사항을 배우게 됩니다. 키 기반 인증 설정 (보안 강화), 시스템 간 안전한 파일 전송, 포트 포워딩을 위한 SSH 터널 생성 등 필수적인 SSH 기능에 대한 실습 경험을 쌓게 됩니다.

실습을 더욱 현실적으로 만들기 위해 Docker 컨테이너를 설정하여 원격 서버 환경을 시뮬레이션하는 것부터 시작합니다. 그런 다음 호스트 머신에 OpenSSH 클라이언트를 설치하고 ssh-keygen 유틸리티를 사용하여 새 RSA 키 쌍을 생성합니다. 다음으로 Docker 서버를 구성하여 이 키를 인증에 사용하도록 설정하고 호스트와 컨테이너화된 서버 간에 안전한 비밀번호 없는 연결을 설정합니다. 마지막으로 안전한 파일 전송을 위해 scp 명령을 사용하고 로컬 포트를 원격 서비스로 전달하여 안전한 터널을 효과적으로 생성하기 위해 ssh -L 명령을 연습합니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 81%입니다.학습자들로부터 96%의 긍정적인 리뷰율을 받았습니다.

Docker SSH 서버 설정 및 키 쌍 생성

이 단계에서는 원격 SSH 서버를 시뮬레이션하기 위해 Docker 컨테이너를 설정하고 호스트 머신에서 안전한 키 쌍을 생성합니다. 이 접근 방식은 클라이언트 (호스트) 와 서버 (Docker 컨테이너) 를 분리하여 보다 현실적인 환경을 제공합니다.

이 환경에는 이미 Docker 와 OpenSSH 클라이언트가 설치되어 있으므로 서버 구성으로 바로 진행할 수 있습니다.

먼저 Docker 서비스가 실행 중인지 확인합니다.

sudo systemctl start docker
sudo systemctl enable docker

이제 SSH 서버 역할을 할 Docker 컨테이너를 생성해 보겠습니다. Ubuntu 를 기본 이미지로 사용하고 SSH 서버 기능으로 구성할 것입니다. Dockerfile 을 생성합니다.

cat > Dockerfile << 'EOF'
FROM ubuntu:22.04

## OpenSSH 서버 및 기타 유틸리티 설치
RUN apt-get update && \
    apt-get install -y openssh-server nginx sudo && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

## SSH 액세스를 위한 사용자 생성
RUN useradd -m -s /bin/bash sshuser && \
    echo 'sshuser:password123' | chpasswd && \
    usermod -aG sudo sshuser

## SSH 구성
RUN mkdir /var/run/sshd && \
    sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config && \
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
    sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config

## 사용자용 SSH 디렉토리 생성
RUN mkdir -p /home/sshuser/.ssh && \
    chown sshuser:sshuser /home/sshuser/.ssh && \
    chmod 700 /home/sshuser/.ssh

## SSH 포트 노출
EXPOSE 22 80

## SSH 서비스 시작
CMD ["/usr/sbin/sshd", "-D"]
EOF

Docker 이미지를 빌드합니다.

sudo docker build -t ssh-server .

호스트의 2222 번 포트를 컨테이너의 22 번 포트로 매핑하여 Docker 컨테이너를 실행합니다.

sudo docker run -d --name ssh-lab-server -p 2222:22 -p 8080:80 ssh-server

컨테이너가 실행 중인지 확인합니다.

sudo docker ps

실행 중인 컨테이너를 보여주는 출력이 표시되어야 합니다.

CONTAINER ID   IMAGE        COMMAND               CREATED         STATUS         PORTS                                        NAMES
...            ssh-server   "/usr/sbin/sshd -D"   ...             Up ...         0.0.0.0:2222->22/tcp, 0.0.0.0:8080->80/tcp   ssh-lab-server

다음으로 SSH 키 쌍을 생성합니다. SSH 키는 비밀번호만 사용하는 것보다 서버에 SSH 로 로그인하는 더 안전한 방법을 제공합니다. 키 쌍은 비밀로 유지해야 하는 **개인 키 (private key)**와 공유할 수 있는 **공개 키 (public key)**로 구성됩니다.

ssh-keygen 명령을 사용하여 새 키 쌍을 생성합니다. 강력한 보안을 위해 키 유형을 rsa로, 키 크기를 2048 비트로 지정합니다. -f 플래그를 사용하면 키 파일을 지정할 수 있어 정리하는 데 도움이 됩니다. 키 이름을 ~/.ssh/id_rsa_lab_ssh로 지정합니다.

다음 명령을 실행합니다. 암호 구문 (passphrase) 을 입력하라는 메시지가 표시되면 Enter 키를 두 번 눌러 암호 구문 없이 진행합니다. 이 실습에서는 단순화를 위해 암호 구문을 생략하지만, 실제 시나리오에서는 개인 키를 보호하기 위해 항상 강력한 암호 구문을 사용해야 합니다.

ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa_lab_ssh

명령이 키 쌍을 생성하고 파일이 저장된 위치를 보여줍니다.

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/labex/.ssh/id_rsa_lab_ssh
Your public key has been saved in /home/labex/.ssh/id_rsa_lab_ssh.pub
The key fingerprint is:
SHA256:... labex@...
The key's randomart image is:
+---[RSA 2048]----+
|        .o*+..   |
|       . =.o. .  |
|      . o o. .   |
|       o .  .    |
|      . S        |
|     . . .       |
|      o .        |
|     o .         |
|    E .          |
+----[SHA256]-----+

키 파일이 생성되었는지 확인하려면 ~/.ssh 디렉토리의 내용을 나열할 수 있습니다. 새 개인 키 (id_rsa_lab_ssh) 와 공개 키 (id_rsa_lab_ssh.pub) 가 표시되어야 합니다.

ls -l ~/.ssh/id_rsa_lab_ssh*

출력은 다음과 유사하게 표시되며 두 개의 새 파일이 표시됩니다.

-rw------- 1 labex labex 1876 ... /home/labex/.ssh/id_rsa_lab_ssh
-rw-r--r-- 1 labex labex  401 ... /home/labex/.ssh/id_rsa_lab_ssh.pub

이제 SSH 서버를 성공적으로 설치하고 키 쌍을 생성했습니다. 다음 단계에서 이를 사용하여 보안 인증을 구성하고 테스트합니다.

SSH 키 기반 인증 설정 및 테스트

이 단계에서는 Docker SSH 서버가 공개 키를 인식하도록 구성하여 비밀번호 없이 로그인할 수 있도록 합니다. 이 과정에는 공개 키를 Docker 컨테이너로 복사한 다음 연결을 테스트하는 작업이 포함됩니다.

SSH 서버가 키를 사용하여 사용자를 인증하려면 공개 키를 서버의 ~/.ssh/authorized_keys 파일에 배치해야 합니다. 서버는 Docker 컨테이너에서 실행되므로 호스트 머신에서 컨테이너로 공개 키를 복사해야 합니다.

먼저 docker cp 명령을 사용하여 공개 키를 Docker 컨테이너로 복사합니다.

sudo docker cp ~/.ssh/id_rsa_lab_ssh.pub ssh-lab-server:/home/sshuser/.ssh/authorized_keys

다음으로 컨테이너 내부에서 올바른 파일 권한을 설정해야 합니다. SSH 는 보안에 매우 민감하며 권한이 너무 개방적이면 키 사용을 거부합니다. 적절한 권한을 설정하려면 다음 명령을 실행합니다.

sudo docker exec ssh-lab-server chown sshuser:sshuser /home/sshuser/.ssh/authorized_keys
sudo docker exec ssh-lab-server chmod 600 /home/sshuser/.ssh/authorized_keys

공개 키를 추가하고 권한을 설정했으므로 키 기반 인증을 테스트할 준비가 되었습니다. 컨테이너의 22 번 포트로 매핑된 2222 번 포트를 사용하여 sshuser 사용자로 Docker 컨테이너에 SSH 로 접속하고 생성한 개인 키를 지정합니다.

개인 키 파일을 가리키는 -i 플래그와 포트를 지정하는 -p 플래그와 함께 ssh 명령을 사용합니다.

ssh -i ~/.ssh/id_rsa_lab_ssh -p 2222 sshuser@localhost

처음으로 새 호스트에 연결하는 경우 호스트의 인증을 확인하라는 메시지가 표시될 수 있습니다. yes를 입력하고 Enter 키를 누릅니다.

The authenticity of host '[localhost]:2222 ([127.0.0.1]:2222)' can't be established.
ED25519 key fingerprint is SHA256:....
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.

모든 것이 올바르게 구성되었다면 비밀번호를 묻는 메시지 없이 즉시 로그인됩니다. 환영 메시지가 표시되고 명령 프롬프트가 변경되어 Docker 컨테이너 내부에 있음을 나타냅니다.

Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-88-generic x86_64)
...
sshuser@containerid:~$

SSH 세션을 종료하고 호스트 터미널 프롬프트로 돌아가려면 exit를 입력하고 Enter 키를 누릅니다.

exit

비밀번호 없이 성공적으로 로그인하면 호스트와 Docker 컨테이너 간에 키 기반 인증이 올바르게 작동하고 있음을 확인할 수 있습니다. 이 방법은 기존 비밀번호 인증보다 훨씬 안전합니다.

scp 를 사용하여 안전하게 파일 전송

이 단계에서는 **Secure Copy Protocol (scp)**을 사용하여 호스트 간에 안전하게 파일을 전송하는 방법을 배웁니다. scp는 기본 SSH 프로토콜을 활용하므로 이미 구성한 키 기반 인증을 포함한 동일한 암호화 및 인증 메커니즘의 이점을 누릴 수 있습니다.

먼저 전송에 사용할 샘플 파일을 현재 작업 디렉토리인 ~/project에 생성해 보겠습니다. 파일 이름은 source_file.txt로 지정합니다.

echo "This is a test file for scp." > source_file.txt

파일을 나열하여 파일이 생성되었는지 확인할 수 있습니다.

ls -l source_file.txt

출력에는 새로 생성된 파일이 표시되어야 합니다.

-rw-r--r-- 1 labex labex 29 ... source_file.txt

이제 scp를 사용하여 source_file.txt를 Docker 컨테이너의 /tmp 디렉토리로 복사하여 원격 서버로의 안전한 파일 전송을 시연합니다. scp의 기본 구문은 scp -i [private_key] -P [port] [source_file] [user]@[host]:[destination_path]입니다.

-i 플래그를 사용하여 개인 키를 지정하고, -P 플래그를 사용하여 2222 번 포트 (Docker 컨테이너의 SSH 포트) 를 지정하며, 컨테이너의 sshuser 계정으로 파일을 전송합니다.

scp -i ~/.ssh/id_rsa_lab_ssh -P 2222 source_file.txt sshuser@localhost:/tmp/destination_file.txt

파일 전송 진행 상황을 나타내는 출력이 표시되며, 작은 파일의 경우 즉시 완료되어야 합니다.

source_file.txt                                   100%   29     6.7KB/s   00:00

파일이 성공적으로 복사되었는지 확인하려면 Docker 컨테이너에 연결하고 대상 파일을 나열합니다.

sudo docker exec ssh-lab-server ls -l /tmp/destination_file.txt

출력에서 복사된 파일의 존재 여부와 세부 정보를 확인할 수 있습니다.

-rw-r--r-- 1 sshuser sshuser 29 ... /tmp/destination_file.txt

파일 내용이 올바르게 전송되었는지도 확인할 수 있습니다.

sudo docker exec ssh-lab-server cat /tmp/destination_file.txt

다음과 같이 표시되어야 합니다.

This is a test file for scp.

이제 scp를 사용하여 파일을 성공적으로 전송했으며, 네트워크를 통해 시스템 간에 데이터를 이동하는 안전하고 실용적인 방법을 시연했습니다.

ssh -L을 사용하여 포트 포워딩을 위한 SSH 터널 생성

이 단계에서는 SSH 의 가장 강력한 기능 중 하나인 터널링, 즉 포트 포워딩에 대해 배웁니다. 이를 통해 로컬 머신의 포트에서 원격 서버의 포트로 네트워크 트래픽을 안전하게 전달하여, 암호화되지 않은 프로토콜을 안전한 SSH 연결 내에 효과적으로 래핑할 수 있습니다. 여기서는 로컬 포트 포워딩을 실습합니다.

이를 시연하기 위해 연결할 수 있는 포트에서 실행 중인 서비스가 필요합니다. 다행히 Docker 컨테이너에는 이미 Nginx 가 설치 및 구성되어 있습니다. 컨테이너 내부에서 Nginx 서비스를 시작해야 합니다.

먼저 Docker 컨테이너 내부에서 Nginx 서비스를 시작합니다.

sudo docker exec ssh-lab-server service nginx start

컨테이너 내부에서 Nginx 가 올바르게 실행 중인지 확인할 수 있습니다.

sudo docker exec ssh-lab-server service nginx status

출력에는 서비스가 실행 중임을 나타내야 합니다.

 * nginx is running

이제 SSH 터널을 생성해 보겠습니다. 로컬 포트 포워딩을 의미하는 -L 플래그와 함께 ssh 명령을 사용합니다. 구문은 ssh -L [LOCAL_PORT]:[DESTINATION_HOST]:[DESTINATION_PORT] [USER]@[SERVER]입니다.

로컬 머신의 9090 번 포트에서 Docker 컨테이너 내부의 80 번 포트로 트래픽을 전달할 것입니다. -N 플래그는 SSH 에게 원격 명령을 실행하지 않도록 지시하며, 이는 포트만 전달하는 데 이상적입니다. Docker 컨테이너의 SSH 서비스에 연결하기 위해 2222 번 포트를 사용한다는 점에 유의하십시오.

이 명령을 실행합니다. 이 명령은 현재 터미널을 점유하며 프롬프트를 반환하지 않습니다. 터널을 테스트하려면 새 터미널을 열어야 합니다.

ssh -i ~/.ssh/id_rsa_lab_ssh -N -L 9090:localhost:80 -p 2222 sshuser@localhost

이제 터미널 탭 바에서 + 아이콘을 클릭하여 새 터미널을 엽니다. 이 새 터미널에서 curl을 사용하여 터널을 테스트할 수 있습니다. localhost:9090에 액세스하면 요청이 SSH 를 통해 Docker 컨테이너 내부의 80 번 포트로 안전하게 터널링됩니다.

curl http://localhost:9090

기본 Nginx 환영 페이지의 HTML 콘텐츠가 표시되어야 하며, 이는 터널이 작동하고 있음을 확인합니다.

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

호스트 머신에서 Docker 컨테이너 내부에서 실행 중인 서비스로 트래픽을 전달하는 안전한 터널을 성공적으로 생성했습니다. 연결을 닫으려면 첫 번째 터미널(ssh 명령을 실행 중인 터미널) 로 돌아가 Ctrl+C를 누릅니다. 그런 다음 두 번째 터미널을 닫을 수 있습니다.

요약

이 실습에서는 Secure Shell (SSH) 프로토콜을 사용하여 Linux 시스템에서 원격 액세스를 안전하게 설정하는 필수 기술을 배웠습니다. 주요 목표는 키 기반 인증 설정 및 테스트, scp를 사용한 안전한 파일 전송, 포트 포워딩을 위한 SSH 터널 생성 등을 포함했습니다.

먼저 시스템의 패키지 목록을 업데이트하고 openssh-serveropenssh-client 패키지를 모두 설치하는 환경 준비부터 시작했습니다. SSH 서비스가 활성화되었는지 확인한 후, ssh-keygen 명령을 사용하여 안전한 2048 비트 RSA 키 쌍을 생성했습니다. 이 기초 단계는 이후 단계에서 안전하고 비밀번호 없는 연결을 설정하는 데 필요한 공개 키와 개인 키를 생성했습니다.