VM 인스턴스에 안전하게 연결

이 문서에서는 게스트 속성을 사용 설정하여 호스트 키 저장공개 인터넷에서 VM에 연결하지 못하게 방지 등 Compute Engine 가상 머신(VM) 인스턴스에 안전하게 연결할 수 있는 권장사항을 설명합니다.

시작하기 전에

게스트 속성을 사용 설정하여 호스트 키 저장

호스트 키는 특정 호스트 또는 머신을 식별하는 키 쌍입니다. 원격 호스트에 연결할 때 호스트 키는 의도한 머신에 연결 중인지 확인하는 데 사용됩니다.

gcloud compute ssh를 사용하여 Linux VM에 연결하는 경우 호스트 키를 게스트 속성으로 저장하여 보안을 강화할 수 있습니다.

SSH 호스트 키를 게스트 속성으로 저장하면 MITM(man-in-the-middle) 공격과 같은 취약성으로부터 보호하여 연결 보안을 향상시킵니다. VM을 처음 부팅할 때 게스트 속성이 사용 설정되어 있으면 Compute Engine은 생성된 호스트 키를 게스트 속성으로 저장합니다. 그런 다음 Compute Engine은 저장된 호스트 키를 사용하여 VM에 대한 모든 이후 연결을 확인합니다.

호스트 키는 다음 공개 운영체제 이미지에서 게스트 속성으로 저장할 수 있습니다.

  • Debian
  • Ubuntu
  • RHEL(Red Hat Enterprise Linux)
  • CentOS
  • SLES(SUSE Linux Enterprise Server)

게스트 속성에 호스트 키를 쓰려면 VM을 처음 부팅하기 전에 게스트 속성을 사용 설정해야 합니다. VM 생성 중에 일부 VM에서 또는 전체 프로젝트에서 게스트 속성을 사용 설정할 수 있습니다.

프로젝트 또는 VM에 게스트 속성을 사용 설정하면 게스트 OS 에이전트가 호스트 속성으로 게스트 키를 자동으로 게시합니다. 일반 SSH 클라이언트 대신 gcloud compute ssh를 사용하면 gcloud 도구는 속성을 자동으로 읽어 다음 번에 연결할 때 known_hosts 파일을 업데이트합니다.

게스트 속성으로 호스트 키를 저장하려면 다음 단계를 완료합니다.

  1. VM을 처음 부팅하기 전에 VM 생성 중에 일부 VM에서 또는 전체 프로젝트에서 게스트 속성을 사용 설정합니다.

  2. gcloud compute ssh를 사용하여 VM에 연결합니다.

    1. 최신 버전의 gcloud 명령줄 도구가 있어야 합니다.

      gcloud components update
      
    2. VM에 연결합니다.

      gcloud compute ssh --project=PROJECT_ID \
       --zone=ZONE \
       VM_NAME
      

      다음을 바꿉니다.

      • PROJECT_ID: VM이 포함된 프로젝트의 ID입니다.
      • ZONE: VM이 있는 영역의 이름입니다.
      • VM_NAME: VM의 이름입니다.

      gcloud 명령줄 도구에 기본 속성을 설정해 둔 경우 이 명령어에서 --project 플래그와 --zone 플래그를 생략할 수 있습니다. 예를 들면 다음과 같습니다.

      gcloud compute ssh VM_NAME
      
    3. 스타트업 메시지를 검토합니다. 예를 들어 Debian 운영체제에서는 다음과 같은 메시지를 표시할 수 있습니다.

      Writing 3 keys to YOUR_HOME_DIRECTORY/.ssh/google_compute_known_hosts
      Linux host-key-2 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) x86_64
      

호스트 키가 이 VM의 게스트 속성으로 저장되었는지 확인하려면 호스트 키 값을 검토하여 SSH 키가 VM의 게스트 속성에 기록되었는지 확인하거나(옵션 1) 직렬 포트에 호스트 키가 있는지 검토합니다(옵션 2).

옵션 1: 호스트 키 값 검토

gcloud 명령줄 도구를 사용하여 SSH 키가 게스트 속성에 기록되는지 확인할 수 있습니다.

gcloud compute instances get-guest-attributes VM_NAME \
  --query-path="hostkeys/" \
  --zone=ZONE

다음을 바꿉니다.

  • VM_NAME: VM의 이름입니다.
  • ZONE: VM이 있는 영역의 이름입니다.

출력은 다음과 비슷합니다.

NAMESPACE  KEY                  VALUE
hostkeys   ecdsa-sha2-nistp256  AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBJAGpTm
                                V3mFxBTHK1NIu9a7kVQWaHsZVaFUsqF8cLxQRQ+N96/Djiiuz1tucHQ8vBTJI=
hostkeys   ssh-ed25519          AAAAC3NzaC1lZDI1NTE5AAAAIM/WYBn3jIEW5t3BZumx0X/Htm61J6S9FcU8L
hostkeys   ssh-rsa              AAAAB3NzaC1yc2EAAAADAQABAAABAQDU3jReR/MoSttlWYfauW6qEqS2dhe5
                                Zdd3guYk2H7ZyxblNuP56nOl/IMuniVmsFa9v8W6MExViu6G5Cy4iIesot09
                                1hsgkG0U7sbWrXM10PQ8pnpI3B5arplCiEMhRtXy64rlW3Nx156bLdcxv5l+
                                7Unu4IviKlY43uqqwSyTv+V8q4ThpQ9dNbk1Gg838+KzazljzHahtbIaE1rm
                                I0L1lUqKiKLSLKuBgrI2Y/WSuqvqGEz+bMH7Ri4ht+7sAwykph6FbOgKqoBI
                                hVWBo38/Na/gEuvtmgULUwK+xy9zWg9k8k/Qtihc6El9GD9y

옵션 2: 직렬 포트 검토

  1. 직렬 포트 출력을 확인합니다.
  2. 직렬 포트 1을 선택합니다.
  3. 다음 메시지를 검색합니다.

    INFO Wrote ssh-rsa host key to guest attributes

    지원되는 운영체제가 이미지에서 사용되지만 첫 번째 VM 부팅 전에 게스트 속성 설정을 사용하도록 설정하지 않은 경우 다음 메시지가 표시될 수 있습니다.

    Unable to write ssh-rsa host key to guest attributes

    즉, 호스트 키가 이 VM에 게스트 속성으로 저장되지 않았습니다. 만들려는 추가 VM의 호스트 키를 저장하려면 VM을 처음 부팅하기 전에 게스트 속성을 사용 설정합니다.

공개 인터넷에서 VM에 연결하지 못하도록 방지

Compute Engine에서 프로젝트를 개발할 때 공개 인터넷에서 VM을 연결하여 유지하려는 다양한 시나리오가 있습니다.

  • 웹 서비스는 아직 개발 중이며 기능이 불완전하거나 아직 HTTPS로 구성되지 않았기 때문에 외부 사용자에게 노출될 준비가 되어 있지 않습니다.
  • VM에서 프로젝트의 다른 VM에서만 사용하도록 설계된 서비스를 제공할 수 있습니다.
  • VM은 회사 사무실 또는 데이터 센터의 Dedicated Interconnect 옵션을 통해서만 연결되어야 합니다.

서비스가 의도적으로 인터넷 연결을 사용하는 경우에도 서비스와의 통신을 대상 사용자 그룹으로 제한하고 민감한 정보를 보호하기 위해 SSH 또는 HTTPS와 같은 보안 채널을 통해 이루어지도록 하는 것이 중요합니다.

이 문서에서는 외부 IP 주소가 있는 VM외부 IP 주소가 없는 VM과 통신하기 위한 몇 가지 방법을 설명합니다.

외부 IP 주소가 있는 머신의 서비스 보호

VM에 공개 IP 주소가 있는 경우 노출하려는 서비스와 트래픽만 연결할 수 있어야 하며 노출된 서비스와 트래픽의 민감한 정보가 전송 중에 보호되어야 합니다. 이 문서에서는 방화벽, HTTPS 및 SSL, SSH를 통한 포트 전달, SSH를 통한 SOCKS 프록시 등 외부 IP 주소가 있는 VM의 서비스를 보호하는 여러 가지 방법을 설명합니다.

방화벽

첫 번째 방어선은 방화벽을 사용하여 VM에 연결할 수 있는 대상을 제한하는 것입니다. 방화벽 규칙을 만들면 특정 포트 집합의 네트워크 또는 대상 머신에 대한 모든 트래픽을 특정 소스 IP 주소로 제한할 수 있습니다.

방화벽은 독립형 솔루션이 아닙니다. 특정 소스 IP에 대한 트래픽을 제한한다고 해서 로그인 사용자 인증 정보, 리소스나 파일을 만들거나 폐기하는 명령어, 로그와 같은 민감한 정보가 보호되지는 않습니다. 외부 IP가 있는 Compute Engine VM과 같은 공개적으로 액세스 가능한 머신에서 웹 서비스를 실행할 경우 적절한 보안을 위해 호스트와 배포된 VM 간의 모든 통신을 암호화해야 합니다.

또한 방화벽이 항상 적절한 솔루션이라고 할 수는 없습니다. 예를 들어 방화벽은 로밍 노트북과 같이 정적 IP 주소가 없는 개발 환경에 적합하지 않습니다.

HTTPS 및 SSL

프로덕션 웹 시스템의 경우 HTTPS/SSL을 구성해야 합니다. HTTPS를 종료하도록 VM을 설정하거나 HTTPS 부하 분산을 구성하여 HTTPS/SSL을 설정할 수 있습니다. HTTPS/SSL은 초기에 몇 가지가 복잡하기 때문에 다음 작업을 수행해야 합니다.

  • 도메인 이름 등록
  • 인증 기관에서 SSL 인증서 얻기
  • 인증서를 HTTPS 부하 분산기 및 연결된 VM에 등록하거나 Compute Engine VM 하나 이상에서 SSL로 종료되는 웹 서버나 프록시를 구성합니다.

SSH를 통한 포트 전달

gcloud 명령줄 도구를 사용하여 SSH 연결을 통해 원격 호스트에 모든 트래픽을 전달하는 서버를 특정 로컬 포트에서 시작할 수 있습니다.

먼저 보안 연결을 설정하려는 서비스를 제공하는 VM과 포트를 기록해둡니다. 다음 명령어를 실행합니다.

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT

다음을 바꿉니다.

  • VM_NAME은 연결하려는 VM의 이름입니다.
  • PROJECT_IDGoogle Cloud 프로젝트 ID입니다.
  • ZONE: VM이 실행 중인 영역입니다(예: us-central1-a).
  • LOCAL_PORT: 수신 중인 로컬 포트입니다. 예를 들면 2222입니다.
  • REMOTE_PORT: 연결할 원격 포트입니다(예: 8888).

예를 들어 로컬 포트 '2222'와 원격 포트 '8888'을 지정하고 브라우저에서 http://localhost:2222/를 열면 HTTP 연결은 원격 호스트에 만든 SSH 터널을 사용하여 SSH를 통해 지정된 VM에 연결합니다. 그러면 HTTP 연결이 SSH 터널을 사용하여 동일한 머신의 포트 8888에 연결되지만 암호화된 보안 SSH 연결을 통해 연결됩니다.

gcloud 명령어는 SSH 세션이 활성화된 상태에서 SSH 연결을 만들고 유지보수합니다. SSH 세션을 종료하는 즉시 http://VM_NAME:LOCAL_PORT를 사용하는 포트 전달 작동이 중지됩니다.

2개 이상의 포트 전달 규칙을 만들려면 플래그를 반복하여 단일 명령 줄에 여러 규칙을 지정하면 됩니다.

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT \
    -- -NL LOCAL_PORT:localhost:REMOTE_PORT

또는 매번 새 gcloud 명령어를 실행하여 별도의 터널을 만들 수 있습니다. 처음부터 연결을 종료하고 다시 설정하지 않고는 기존 연결에서 포트 전달을 추가하거나 삭제할 수 없습니다.

SSH를 통한 SOCKS 프록시

클라우드 배포에서 여러 호스트에 연결하려는 경우 브라우저에서 직접 네트워크를 통해 조회하는 것이 가장 쉬운 방법입니다. 이 접근 방식을 사용하면 각 호스트의 IP 주소를 검색하거나, 각 서비스의 포트를 열거나, 각 호스트/포트 쌍에 대한 SSH 터널을 만드는 대신 호스트의 닉네임을 사용할 수 있습니다.

여기에서 사용하는 접근 방식은 다음과 같습니다.

  1. 네트워크 상의 호스트 중 하나에 단일 SSH 터널을 설정하고 해당 호스트에 SOCKS 프록시를 만듭니다.
  2. 해당 SOCKS 프록시 호스트를 통해 모든 조회를 수행하도록 브라우저 구성을 변경합니다.

해당 호스트를 통해 모든 트래픽을 터널링하기 때문에 해당 브라우저 또는 특정 프로필을 사용하여 웹을 탐색하지 않아도 됩니다. 이때는 클라우드 서비스에 전용 대역폭을 할당해야 합니다. 일반적으로 별도의 브라우저 프로필을 사용하고 필요할 때 전환할 수 있습니다.

SOCKS 프록시 시작

SOCKS 프록시를 시작하려면 다음 명령어를 실행하세요.

gcloud compute ssh VM_NAME \
    --project PROJECT_ID \
    --zone ZONE
    --ssh-flag="-D" \
    --ssh-flag="LOCAL_PORT" \
    --ssh-flag="-N"

다음을 바꿉니다.

  • VM_NAME: 연결하려는 VM의 이름입니다.
  • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
  • ZONE: VM이 실행 중인 영역입니다(예: us-central1-a).
  • LOCAL_PORT: 수신 중인 로컬 포트입니다. 예를 들면 1080입니다.

이 경우 원격 포트를 지정할 필요가 없습니다. SOCKS 프록시는 특정 원격 포트에 결합되지 않으므로 SOCKS 프록시를 통한 모든 연결은 연결된 호스트 기준으로 결정됩니다.

SOCKS 프록시를 사용하면 VM의 닉네임을 사용하여 Compute Engine 네트워크를 프록시 VM과 공유하는 모든 VM에 연결할 수 있습니다. 또한 특정 VM의 모든 포트에 연결할 수 있습니다.

이 접근 방식은 단순한 포트 전달 방법보다 훨씬 유연하지만 프록시를 사용하기 위해 웹브라우저의 설정을 변경해야 합니다.

다음으로, 프록시를 사용하도록 Chrome 또는 Firefox를 구성합니다.

크롬

Chrome은 기본적으로 시스템 전체의 프록시 설정을 사용하므로 명령줄 플래그를 사용하여 다른 프록시를 지정해야 합니다. Chrome을 실행하면 기본적으로 이미 실행 중인 프로필의 VM이 생성되므로 Chrome 사본 여러 개(하나는 프록시를 사용하며 나머지는 사용하지 않음)를 동시에 실행하려면 새 프로필이 필요합니다.

새 프로필을 사용하여 Chrome을 시작합니다. 프로필이 없으면 자동으로 생성됩니다.

Linux:

/usr/bin/google-chrome \
    --user-data-dir="$HOME/chrome-proxy-profile" \
    --proxy-server="socks5://localhost:1080"

macOS:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
    --user-data-dir="$HOME/chrome-proxy-profile" \
    --proxy-server="socks5://localhost:1080"

Windows:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" ^
    --user-data-dir="%USERPROFILE%\chrome-proxy-profile" ^
    --proxy-server="socks5://localhost:1080"

localhost 포트를 이전 gcloud 명령어에서 사용한 값(이 예시에서는 1080)과 동일하게 설정합니다.

Firefox

이러한 설정을 변경하기 전에 새 Firefox 프로필을 만드는 것이 좋습니다. 그렇지 않으면 Firefox의 모든 VM이 해당 호스트를 프록시로 사용하게 되며 이는 원하는 동작이 아닐 수 있습니다.

별도의 프로필로 Firefox를 실행한 후 SOCKS 프록시를 설정할 수 있습니다.

  1. 환경설정을 엽니다.
  2. 고급 > 네트워크 > 설정을 클릭하여 연결 설정 대화상자를 엽니다.
  3. 수동 프록시 구성 옵션을 선택합니다.
    1. SOCKS 호스트 섹션에서 localhost를 호스트로 입력하고 이전에 gcloud 명령어를 실행할 때 선택한 포트를 입력합니다.
    2. SOCKS v5를 선택합니다.
    3. 원격 DNS 상자를 선택합니다.
    4. 다른 모든 항목은 비워 둡니다.
  4. 확인을 클릭하고 환경설정 대화상자를 닫습니다.

외부 IP 주소가 없는 VM에 연결

VM에 외부 IP 주소가 없는 경우(HTTPS 및 SSL 부하 분산기의 백엔드인 VM 포함) VM은 네트워크의 다른 VM, IAP(Identity-Aware Proxy)의 TCP 전달 기능 또는 관리형 VPN 게이트웨이를 통해서만 연결될 수 있습니다. 인바운드 연결에 신뢰할 수 있는 릴레이 역할을 하도록(배스천 호스트라고도 함) 네트워크에서 VM을 프로비저닝할 수 있습니다. 또한 네트워크 이그레스에 Cloud NAT를 구성하거나 대화형 직렬 콘솔을 설정하여 외부 IP 주소가 없는 VM을 유지보수하거나 문제를 해결할 수 있습니다.

요새 호스트

배스천 호스트는 다음 다이어그램에 표시된 것처럼 비공개 네트워크 인스턴스가 포함된 네트워크에서 외부 진입점 역할을 합니다.

비공개 인스턴스의 네트워크에 대한 외부 진입점 역할을 하는 배스천 호스트의 아키텍처

이 호스트는 단일 배스천 지점 또는 감사 지점이 될 수 있으며, 이 호스트를 시작 또는 중지시켜 인바운드 SSH를 사용 설정 또는 중지할 수 있습니다. 배스천 호스트를 사용하면 외부 IP 주소가 없는 VM에 연결할 수 있습니다. 예를 들어 이 접근 방식을 사용하면 추가 방화벽 규칙을 구성하지 않고도 개발 환경에 연결하거나 외부 애플리케이션의 데이터베이스 인스턴스를 관리할 수 있습니다.

배스천 호스트의 완벽한 강화는 이 문서의 범위를 벗어나지만 다음을 비롯한 몇 가지 초기 조치를 취할 수 있습니다.

  • 배스천과 통신할 수 있는 소스 IP의 CIDR 범위를 제한합니다.
  • 배스천 호스트에서만 사설 VM에 대한 SSH 트래픽을 허용하도록 방화벽 규칙을 구성합니다.

기본적으로 VM의 SSH는 비공개 키를 사용하여 인증되도록 구성됩니다. 배스천 호스트를 사용할 때는 우선 배스천 호스트에 로그인한 다음 대상 비공개 VM에 로그인합니다. 이러한 2단계 로그인으로 인해 배스천 호스트를 '점프 서버'라고도 하며, 대상 머신에 연결하기 위해 대상 머신의 비공개 키를 배스천 호스트에 저장하는 대신 ssh 전달을 사용해야 합니다. 배스천은 키 쌍의 절반인 공개 부분에만 직접 액세스할 수 있으므로 배스천과 대상 VM 모두에 동일한 키 쌍을 사용하더라도 이 작업을 수행해야 합니다.

배스천 호스트 인스턴스를 사용하여 Google Cloud 네트워크의 다른 VM에 연결하는 방법은 배스천 호스트를 통해 연결을 참조하세요.

ssh 전달을 사용하는 방법과 외부 IP 주소가 없는 VM에 연결하는 다른 방법은 외부 IP 주소가 없는 VM에 연결을 참조하세요.

TCP 전달을 위한 IAP

IAP의 TCP 전달 기능과 함께 SSH를 사용하면 SSH 연결이 HTTPS 안에 래핑됩니다. 그런 다음 IAP의 TCP 전달 기능이 원격 VM으로 연결을 보냅니다.

IAP로 원격 VM에 연결하는 방법은 TCP 전달에 IAP 사용을 참조하세요.

VPN

Cloud VPN을 사용하면 VPN 게이트웨이 기기에 IPsec 연결을 사용하여 기존 네트워크를 Google Cloud 네트워크에 연결할 수 있습니다. 이를 통해 프레미스에서 Compute Engine VM의 비공개 IP 인터페이스로 트래픽을 직접 라우팅할 수 있습니다. 트래픽은 공개 링크를 통해 Google로 전송될 때 암호화됩니다.

Compute Engine을 사용하여 VPN을 설정, 구성, 사용하는 방법에 대한 자세한 내용은 Cloud VPN 문서를 참조하세요.

VM의 외부 IP 주소가 아닌 기존 VPN을 통해 Google Cloud 네트워크의 VM에 연결하는 방법은 외부 IP 주소가 없는 VM에 연결을 참조하세요.

Cloud NAT를 사용한 트래픽 이그레스

VM에 할당된 외부 IP 주소가 없으면 다른 Google Cloud 서비스를 포함한 외부 서비스에 직접 연결할 수 없습니다. 이러한 VM이 공개 인터넷의 서비스에 연결하도록 허용하려면 네트워크의 모든 VM을 대신하여 트래픽을 라우팅할 수 있는 Cloud NAT를 설정하고 구성하면 됩니다. 단일 VM의 가용성은 높지 않아 여러 VM에서 발생하는 높은 트래픽 처리량을 지원하지 못합니다.

대화형 직렬 콘솔 액세스

VM에 외부 IP 주소가 없으면 여전히 문제 해결이나 유지보수를 위해 VM과 상호작용해야 할 수도 있습니다. 앞서 설명한 것처럼 배스천 호스트 설정이 하나의 옵션이지만 필요한 것보다 더 많은 설정이 필요할 수 있습니다. 외부 IP 주소가 없는 VM 문제를 해결하려면 직렬 콘솔에서 대화형 액세스를 사용 설정하는 것이 좋습니다. 이렇게 하면 SSH를 사용하여 VM의 직렬 콘솔과 상호작용하고 직렬 콘솔에서 명령어를 실행할 수 있습니다.

자세한 내용은 직렬 콘솔과 상호작용을 참조하세요.

HTTPS 및 SSL 프록시 부하 분산기

HTTPS 및 SSL 프록시 부하 분산기의 백엔드인 VM은 외부 IP 주소가 없어도 부하 분산기를 통해 액세스할 수 있습니다. 이러한 리소스에 직접 액세스하려면 외부 IP 주소가 없는 VM에 연결 섹션에 나와 있는 방법을 사용해야 합니다.

자세한 내용은 해당 부하 분산기의 부하 분산 문서를 참조하세요.