Skip to content
Play Builder
Go back

서버 접속의 진화: Bastion Host에서 AWS SSM까지

EC2 서버에 접속하는 방법은 AWS 인프라의 발전과 함께 진화해왔습니다. 이 글에서는 서버 접속 방식의 변천사를 살펴보고, 현재 권장되는 AWS Systems Manager(SSM) 기반 접속 방식의 구현 방법을 정리합니다.

Table of contents

Open Table of contents

서버 접속 방식의 진화

1세대: Bastion Host에 키 저장

가장 초창기에 사용하던 방식으로, 현재는 보안상 권장되지 않는 패턴입니다.

1세대: Bastion Host에 키 저장 구조

작동 방식:

# 1. 로컬 -> Bastion 접속
local$ ssh -i my-bastion-key.pem ec2-user@<BASTION_PUBLIC_IP>

# 2. Bastion -> Private EC2 접속 (Bastion 안에 키가 있어야 함)
bastion$ ssh -i ~/.ssh/private-key.pem ec2-user@<PRIVATE_IP>

문제점:

문제설명
키 집중Bastion이 침해되면 모든 서버의 키가 노출됨
키 복제개발자들이 키 파일을 복사해서 공유하게 됨
추적 불가퇴사자가 키를 가지고 있어도 알 수 없음

2세대: SSH Agent Forwarding

키 파일을 서버에 올리는 위험을 제거하기 위해 등장한 방식입니다.

2세대: SSH Agent Forwarding 구조

작동 방식:

# 1. 로컬에 키 등록
ssh-add -K my-private-key.pem

# 2. Agent Forwarding으로 접속
ssh -A ec2-user@<BASTION_PUBLIC_IP>

# 3. Bastion에서 Private EC2로 접속 (키 파일 없이 가능)
bastion$ ssh ec2-user@<PRIVATE_IP>

또는 **ProxyJump 옵션**으로 한 번에 접속할 수 있습니다.

ssh -J ec2-user@<BASTION_PUBLIC_IP> ec2-user@<PRIVATE_IP>

개선된 점:

여전한 한계:


3세대: AWS Systems Manager (SSM)

현재 AWS 환경에서 권장되는 방식입니다. SSH가 아닌 HTTPS(443) 통신을 사용하며, 인증은 IAM 기반으로 이루어집니다.

3세대: AWS SSM 구조

핵심 특징:

항목Bastion 방식SSM 방식
인증SSH 키 파일IAM Role/User
포트22 (SSH)443 (HTTPS)
중간 서버Bastion 필요불필요
세션 로깅수동 구성자동 지원
권한 회수키 파일 회수 필요IAM 정책 변경으로 즉시

SSM 접속 구성 가이드

필수 구성 요소

SSM 접속이 작동하려면 세 가지가 필요합니다.

1. SSM Agent

대부분의 최신 AWS AMI(Amazon Linux 2/2023, Ubuntu 16.04+)에는 기본 설치되어 있습니다.

# 설치 확인
sudo systemctl status amazon-ssm-agent
# Active: active (running) 이면 정상

수동 설치가 필요한 경우 — Ubuntu x86_64 (Intel/AMD) 아키텍처 기준 설치 방법:

cd /tmp
wget https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb
sudo dpkg -i amazon-ssm-agent.deb
sudo systemctl enable amazon-ssm-agent
sudo systemctl start amazon-ssm-agent

Terraform user_data로 자동화:

resource "aws_launch_template" "app" {
  name_prefix   = "app-"
  image_id      = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  user_data = base64encode(<<-EOF
    #!/bin/bash
    cd /tmp
    wget https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb
    dpkg -i amazon-ssm-agent.deb
    systemctl enable amazon-ssm-agent
    systemctl start amazon-ssm-agent
  EOF
  )

  iam_instance_profile {
    name = aws_iam_instance_profile.ec2_ssm.name
  }
}

2. IAM Role (가장 중요)

EC2에 AmazonSSMManagedInstanceCore 정책이 연결되어 있어야 합니다. 이 설정이 없으면 SSM은 작동하지 않습니다.

# IAM Role
resource "aws_iam_role" "ec2_ssm" {
  name = "ec2-ssm-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "ec2.amazonaws.com"
      }
    }]
  })
}

# SSM 정책 연결
resource "aws_iam_role_policy_attachment" "ssm" {
  role       = aws_iam_role.ec2_ssm.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

# Instance Profile
resource "aws_iam_instance_profile" "ec2_ssm" {
  name = "ec2-ssm-profile"
  role = aws_iam_role.ec2_ssm.name
}

AWS 콘솔에서 EC2를 생성할 경우, [고급 세부 정보] 탭에서 IAM 인스턴스 프로파일을 직접 선택해야 합니다.

3. 네트워크 경로

Private EC2가 SSM 서비스(AWS API)와 통신할 수 있어야 합니다.

방법 A: NAT Gateway

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public.id
}

resource "aws_route_table" "private" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.main.id
  }
}

방법 B: VPC Endpoint (NAT Gateway 없이 가능)

# SSM 관련 VPC Endpoint 3개 필요
locals {
  ssm_endpoints = ["ssm", "ssmmessages", "ec2messages"]
}

resource "aws_vpc_endpoint" "ssm" {
  for_each = toset(local.ssm_endpoints)

  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.ap-northeast-2.${each.key}"
  vpc_endpoint_type   = "Interface"
  subnet_ids          = [aws_subnet.private.id]
  security_group_ids  = [aws_security_group.vpc_endpoint.id]
  private_dns_enabled = true
}

resource "aws_security_group" "vpc_endpoint" {
  name   = "vpc-endpoint-sg"
  vpc_id = aws_vpc.main.id

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_vpc.main.cidr_block]
  }
}

접속 방법

방법 1: AWS 콘솔

  1. EC2 콘솔 → 인스턴스 선택
  2. [연결(Connect)] 클릭
  3. [Session Manager] 탭 → [연결]

웹 브라우저에서 바로 터미널이 열립니다.

방법 2: AWS CLI

로컬에 session-manager-plugin 설치 후 사용합니다.

# macOS 설치
brew install session-manager-plugin

# 접속
aws ssm start-session --target i-0123456789abcdef0

방법 3: SSH처럼 사용 (ProxyCommand)

기존 SSH 워크플로우(scp, rsync 등)를 유지하려면 SSH config를 설정합니다.

# ~/.ssh/config
Host i-* mi-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
    User ec2-user
# 사용
ssh i-0123456789abcdef0
scp ./file.txt i-0123456789abcdef0:/home/ec2-user/

세션 로깅 설정

SSM의 장점 중 하나는 모든 세션 활동을 자동으로 로깅할 수 있다는 점입니다.

# 로그 저장용 S3 버킷
resource "aws_s3_bucket" "ssm_logs" {
  bucket = "company-ssm-session-logs"
}

# SSM Document로 세션 설정
resource "aws_ssm_document" "session_prefs" {
  name            = "SSM-SessionManagerRunShell"
  document_type   = "Session"
  document_format = "JSON"

  content = jsonencode({
    schemaVersion = "1.0"
    description   = "Session Manager Settings"
    sessionType   = "Standard_Stream"
    inputs = {
      s3BucketName           = aws_s3_bucket.ssm_logs.id
      s3KeyPrefix            = "session-logs"
      s3EncryptionEnabled    = true
      idleSessionTimeout     = "30"
      maxSessionDuration     = "120"
    }
  })
}

IAM 기반 접근 제어

태그 기반으로 “누가 어떤 서버에 접속할 수 있는지” 제어할 수 있습니다.

# 개발 서버만 접속 가능한 정책
resource "aws_iam_policy" "ssm_dev_only" {
  name = "ssm-dev-server-access"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect   = "Allow"
        Action   = ["ssm:StartSession"]
        Resource = ["arn:aws:ec2:ap-northeast-2:*:instance/*"]
        Condition = {
          StringEquals = {
            "ssm:resourceTag/Environment" = "dev"
          }
        }
      },
      {
        Effect   = "Allow"
        Action   = ["ssm:TerminateSession", "ssm:ResumeSession"]
        Resource = ["arn:aws:ssm:*:*:session/$${aws:username}-*"]
      }
    ]
  })
}

트러블슈팅 체크리스트

SSM 접속이 되지 않을 때 확인할 항목입니다.

순서확인 항목확인 방법
1SSM Agent 실행 중?systemctl status amazon-ssm-agent
2IAM Role 연결됨?EC2 콘솔에서 IAM role 확인
3정책 포함됨?AmazonSSMManagedInstanceCore 확인
4네트워크 경로?NAT Gateway 또는 VPC Endpoint 확인
5Agent 로그tail -f /var/log/amazon/ssm/amazon-ssm-agent.log

가장 흔한 실수는 IAM Role을 연결하지 않는 것입니다. Launch Template에서 iam_instance_profile을 빠뜨리는 경우가 많습니다.


정리

방식키 파일22번 포트Bastion세션 로깅권한 관리
1세대 (키 저장)서버에 보관필요필요수동수동
2세대 (Agent Fwd)로컬에만필요필요수동수동
3세대 (SSM)불필요불필요불필요자동IAM 통합

Share this post:

Previous Post
SSH Key는 이제 그만: Session Manager로 Bastion 없는 보안 접속 환경 구축
Next Post
169.254.169.254의 정체: Link-Local Address