Chapter 07 정답

보안 그룹 최적화 - 정답 및 해설

Step 1 정답: 현재 보안 그룹 규칙 확인

정답

웹 콘솔 풀이

  1. AWS 콘솔에 로그인합니다.
  2. 상단 검색창에 EC2를 입력하고 EC2 서비스를 선택합니다.
  3. 왼쪽 메뉴에서 Instances를 클릭합니다.
  4. ShopEasy EC2 인스턴스를 선택(체크)합니다.
  5. 하단의 Security 탭을 클릭합니다.
  6. Security groups 항목에서 보안 그룹 이름(링크)을 클릭합니다.
  7. 보안 그룹 상세 페이지에서 Inbound rules 탭을 확인합니다.

확인해야 할 내용

타입프로토콜포트소스판단
SSHTCP220.0.0.0/0변경 필요
Custom TCPTCP50000.0.0.0/0정상 (API 서비스용)

또한 Security Groups 메뉴(왼쪽 Network & Security 섹션)에서 직접 보안 그룹 목록을 확인할 수도 있습니다.

AWS CLI 풀이

bash
# 방법 1: ShopEasy 관련 보안 그룹 조회
aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=ShopEasy*" \
  --query "SecurityGroups[].{Name:GroupName,ID:GroupId,Rules:IpPermissions}" \
  --output json

# 방법 2: EC2 인스턴스에 연결된 보안 그룹 확인
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].{
    ID:InstanceId,
    Name:Tags[?Key=='Name'].Value|[0],
    SG:SecurityGroups[].{Name:GroupName,ID:GroupId}
  }" \
  --output json

# 방법 3: 특정 보안 그룹의 인바운드 규칙 상세 확인
# (보안 그룹 ID를 위에서 확인한 값으로 변경)
aws ec2 describe-security-groups \
  --group-ids sg-xxxxxxxxx \
  --query "SecurityGroups[].IpPermissions[].{
    Protocol:IpProtocol,
    FromPort:FromPort,
    ToPort:ToPort,
    Source:IpRanges[].CidrIp,
    SGSource:UserIdGroupPairs[].GroupId
  }" \
  --output table

예상 출력 (JSON)

json
[
  {
    "Name": "ShopEasy-EC2-SG",
    "ID": "sg-0abc1234def56789",
    "Rules": [
      {
        "FromPort": 22,
        "IpProtocol": "tcp",
        "IpRanges": [
          {
            "CidrIp": "0.0.0.0/0",
            "Description": "SSH access"
          }
        ],
        "ToPort": 22
      },
      {
        "FromPort": 5000,
        "IpProtocol": "tcp",
        "IpRanges": [
          {
            "CidrIp": "0.0.0.0/0",
            "Description": "API server"
          }
        ],
        "ToPort": 5000
      }
    ]
  }
]
해설

보안 점검의 첫 번째 단계는 현재 상태를 정확히 파악하는 것입니다. 보안 그룹 규칙을 확인할 때 다음을 체크합니다:

  • 0.0.0.0/0이 소스인 규칙이 있는지 (전체 인터넷 허용)
  • 각 규칙이 실제로 필요한 것인지 (사용하지 않는 포트가 열려 있지 않은지)
  • 규칙에 설명(Description)이 있는지 (관리 용이성)

SSH(22)가 0.0.0.0/0으로 열려 있는 것은 AWS에서도 경고하는 대표적인 보안 문제입니다. AWS Trusted Advisor나 Security Hub에서도 이 문제를 자동으로 감지하고 알려줍니다.

Step 2 정답: SSH 접근을 내 IP로 제한

정답

웹 콘솔 풀이

  1. EC2 → 왼쪽 메뉴 Security Groups를 클릭합니다.
  2. ShopEasy EC2에 연결된 보안 그룹을 선택합니다.
  3. Inbound rules 탭을 클릭합니다.
  4. Edit inbound rules 버튼을 클릭합니다.
  5. SSH(포트 22) 규칙을 찾습니다.
  6. Source 항목의 드롭다운을 클릭하여 "Custom""My IP"로 변경합니다.
    • 자동으로 현재 공인 IP가 /32와 함께 입력됩니다.
    • 예: 203.0.113.50/32
  7. Save rules를 클릭합니다.
  8. 변경된 규칙을 확인합니다:
    • SSH (22): 소스가 내IP/32로 변경되었는지 확인
    • Custom TCP (5000): 소스가 0.0.0.0/0으로 유지되어 있는지 확인

변경 후 SSH 접속 테스트

규칙 변경 후 반드시 SSH 접속이 정상 동작하는지 확인합니다:

bash
# SSH 접속 테스트 (로컬 터미널에서)
ssh -i "ShopEasy-Key.pem" ec2-user@EC2_PUBLIC_IP

# 접속 성공 시: [ec2-user@ip-10-0-1-xxx ~]$ 프롬프트 표시
# 접속 실패 시: Connection timed out (IP가 다르거나, 보안 그룹 규칙이 잘못된 경우)

AWS CLI 풀이

bash
# 1. EC2 보안 그룹 ID 확인
SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)
echo "EC2 보안 그룹 ID: ${SG_ID}"

# 2. 기존 SSH 규칙 제거 (0.0.0.0/0)
aws ec2 revoke-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0

echo "기존 SSH 규칙(0.0.0.0/0) 제거 완료"

# 3. 내 공인 IP 확인
MY_IP=$(curl -s https://checkip.amazonaws.com)
echo "내 공인 IP: ${MY_IP}"

# 4. 새 SSH 규칙 추가 (내 IP만 허용)
aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp \
  --port 22 \
  --cidr ${MY_IP}/32

echo "새 SSH 규칙 추가 완료: ${MY_IP}/32"

# 5. 변경된 규칙 확인
echo ""
echo "=== 변경 후 인바운드 규칙 ==="
aws ec2 describe-security-groups \
  --group-ids ${SG_ID} \
  --query "SecurityGroups[].IpPermissions[].{
    Protocol:IpProtocol,
    FromPort:FromPort,
    ToPort:ToPort,
    Source:IpRanges[].CidrIp
  }" \
  --output table

SSH 접속 테스트

bash
# EC2 퍼블릭 IP 확인
EC2_IP=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].PublicIpAddress" \
  --output text)

# SSH 접속 테스트
ssh -i "ShopEasy-Key.pem" -o ConnectTimeout=5 ec2-user@${EC2_IP}
# 접속 성공하면 보안 그룹 변경이 올바르게 적용된 것입니다
해설

이 단계가 이번 챕터의 핵심입니다. SSH 접근을 내 IP로만 제한하면:

  • 인터넷의 자동화된 봇이 SSH를 통해 침입을 시도할 수 없습니다
  • 키 파일이 유출되더라도 다른 IP에서는 접속할 수 없습니다 (이중 방어)
  • AWS Security Hub, Trusted Advisor의 SSH 관련 경고가 해소됩니다

CLI에서 주의할 점:

  • revoke-security-group-ingress: 기존 규칙을 제거합니다. 반드시 제거할 규칙의 조건(포트, 프로토콜, CIDR)을 정확히 지정해야 합니다.
  • authorize-security-group-ingress: 새 규칙을 추가합니다.
  • checkip.amazonaws.com: AWS가 제공하는 공인 IP 확인 서비스입니다. curl -s https://checkip.amazonaws.com으로 현재 공인 IP를 확인할 수 있습니다.

순서가 중요합니다! CLI에서는 기존 0.0.0.0/0 규칙을 먼저 제거(revoke)하고, 내 IP 규칙을 추가(authorize)합니다. 만약 순서를 바꾸면 잠시 SSH가 두 규칙(0.0.0.0/0과 내 IP)으로 중복 열리는 상태가 됩니다.

Step 3 정답: RDS 보안 그룹 확인

정답

웹 콘솔 풀이

  1. EC2 → 왼쪽 메뉴 Security Groups를 클릭합니다.
  2. RDS에 연결된 보안 그룹을 찾습니다.
    • 보안 그룹 이름에 "RDS", "database", "db" 등이 포함된 것을 찾습니다.
    • 또는 RDS 콘솔 → Databases → ShopEasy DB 클릭 → Connectivity & security 탭에서 VPC security groups를 확인합니다.
  3. RDS 보안 그룹을 선택하고 Inbound rules 탭을 확인합니다.
  4. 다음을 확인합니다:
    • 타입: MySQL/Aurora
    • 포트: 3306
    • 소스: sg-xxxxxxxxx (EC2 보안 그룹 ID) ← 이것이 올바른 설정!

만약 소스가 0.0.0.0/0이라면 (수정 방법)

  1. Edit inbound rules를 클릭합니다.
  2. MySQL/Aurora (3306) 규칙의 Source를 "Custom"으로 변경합니다.
  3. 검색창에 EC2 보안 그룹 ID(sg-)를 입력하여 선택합니다.
  4. Save rules를 클릭합니다.

AWS CLI 풀이

bash
# 1. RDS 관련 보안 그룹 조회
aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=*RDS*" \
  --query "SecurityGroups[].{
    Name:GroupName,
    ID:GroupId,
    InboundRules:IpPermissions[].{
      Port:FromPort,
      Protocol:IpProtocol,
      IPSource:IpRanges[].CidrIp,
      SGSource:UserIdGroupPairs[].GroupId
    }
  }" \
  --output json

# 2. RDS 인스턴스에서 보안 그룹 확인 (RDS 콘솔 경유)
aws rds describe-db-instances \
  --query "DBInstances[?starts_with(DBInstanceIdentifier,'shopeasy')].{
    DB:DBInstanceIdentifier,
    SG:VpcSecurityGroups[].{
      ID:VpcSecurityGroupId,
      Status:Status
    }
  }" \
  --output json

소스가 0.0.0.0/0인 경우 수정하기

bash
# EC2 보안 그룹 ID 확인
EC2_SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)
echo "EC2 보안 그룹 ID: ${EC2_SG_ID}"

# RDS 보안 그룹 ID 확인
RDS_SG_ID=$(aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=*RDS*" \
  --query "SecurityGroups[0].GroupId" \
  --output text)
echo "RDS 보안 그룹 ID: ${RDS_SG_ID}"

# 만약 0.0.0.0/0 규칙이 있다면 제거
aws ec2 revoke-security-group-ingress \
  --group-id ${RDS_SG_ID} \
  --protocol tcp \
  --port 3306 \
  --cidr 0.0.0.0/0

# EC2 보안 그룹을 소스로 추가
aws ec2 authorize-security-group-ingress \
  --group-id ${RDS_SG_ID} \
  --protocol tcp \
  --port 3306 \
  --source-group ${EC2_SG_ID}

echo "RDS 보안 그룹 수정 완료!"

# 변경 결과 확인
aws ec2 describe-security-groups \
  --group-ids ${RDS_SG_ID} \
  --query "SecurityGroups[].IpPermissions[]" \
  --output json
해설

RDS 보안 그룹에서 보안 그룹 ID를 소스로 사용하는 것은 AWS 보안 모범 사례입니다.

IP 주소 대신 보안 그룹 ID를 사용하는 장점:

  • IP 변경에 강건: EC2 인스턴스를 중지/시작하면 퍼블릭 IP가 변경되지만(Elastic IP 미사용 시), 보안 그룹 ID는 변하지 않습니다. 프라이빗 서브넷의 프라이빗 IP도 변경될 수 있습니다.
  • Auto Scaling 대응: 같은 보안 그룹에 속한 새 인스턴스가 추가되면 자동으로 접근이 허용됩니다.
  • 관리 편의: IP를 일일이 관리하지 않아도 됩니다.

Chapter 03에서 올바르게 설정했다면 이미 EC2 보안 그룹 ID가 소스로 되어 있을 것입니다. 이 단계는 확인(검증)이 목적입니다. 만약 0.0.0.0/0으로 되어 있다면 즉시 수정해야 합니다.

Step 4 정답: 불필요한 아웃바운드 규칙 검토

정답

웹 콘솔 풀이

  1. EC2Security Groups → EC2 보안 그룹 선택
  2. Outbound rules 탭을 클릭합니다.
  3. 기본 아웃바운드 규칙을 확인합니다:
타입프로토콜포트대상
All trafficAllAll0.0.0.0/0

이 기본 규칙은 수정하지 않습니다. 현재 상태를 확인만 하면 됩니다.

아웃바운드로 나가는 트래픽 목록 (참고)

현재 EC2에서 외부로 나가는 트래픽:

대상포트용도
RDS (프라이빗 서브넷)3306MySQL 데이터베이스 연결
DynamoDB (AWS 엔드포인트)443리뷰 데이터 CRUD
S3 (AWS 엔드포인트)443리뷰 이미지 업로드/다운로드
인터넷443, 80npm/yum 패키지 다운로드

AWS CLI 풀이

bash
# EC2 보안 그룹 ID 확인
SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)

# 아웃바운드 규칙 확인
echo "=== EC2 보안 그룹 아웃바운드 규칙 ==="
aws ec2 describe-security-groups \
  --group-ids ${SG_ID} \
  --query "SecurityGroups[].IpPermissionsEgress[].{
    Protocol:IpProtocol,
    FromPort:FromPort,
    ToPort:ToPort,
    Destination:IpRanges[].CidrIp
  }" \
  --output table

# 예상 출력:
# Protocol: -1 (All), FromPort: None, ToPort: None, Destination: 0.0.0.0/0
# 이것은 기본 아웃바운드 규칙 (모든 트래픽 허용)입니다
해설

아웃바운드 규칙의 기본값은 "All traffic - 0.0.0.0/0"으로 모든 나가는 트래픽을 허용합니다. 이번 실습에서는 이 기본값을 유지합니다.

실무에서 아웃바운드를 제한하는 경우:

  • PCI-DSS, HIPAA 등 보안 컴플라이언스 요구사항이 있는 경우
  • 데이터 유출(Data Exfiltration)을 방지해야 하는 경우
  • 특정 AWS 서비스(S3, DynamoDB 등)로만 통신을 제한해야 하는 경우

아웃바운드를 제한할 때 주의할 점:

  • RDS 연결(3306), DynamoDB/S3 API 호출(443) 등 모든 필요한 포트를 허용해야 합니다
  • 소프트웨어 업데이트(yum/npm)를 위한 HTTP(80)/HTTPS(443)도 필요합니다
  • 하나라도 빠뜨리면 서비스가 중단됩니다

강사 참고: 아웃바운드 제한은 고급 주제입니다. 학생들에게 "지금은 확인만 하고, 실무에서는 필요에 따라 제한할 수 있다"고 안내하세요.

트러블슈팅 가이드

자주 발생하는 문제와 해결 방법

문제 1: SSH 접근을 내 IP로 변경한 후 SSH 접속이 안 됨

원인: 보안 그룹에 등록된 IP와 현재 공인 IP가 다릅니다. 카페, 학교, 회사 등 네트워크 환경이 바뀌면 공인 IP가 변경됩니다. 또한 같은 네트워크에서도 공유기가 재시작되면 IP가 바뀔 수 있습니다.

해결:

bash
# 1. 현재 내 공인 IP 확인
curl -s https://checkip.amazonaws.com
# 예: 203.0.113.75

# 2. 보안 그룹에 등록된 IP 확인
SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)

aws ec2 describe-security-groups \
  --group-ids ${SG_ID} \
  --query "SecurityGroups[].IpPermissions[?FromPort==\`22\`].IpRanges[].CidrIp" \
  --output text
# 예: 203.0.113.50/32  <-- 이전 IP!

# 3. IP가 다르다면 규칙 업데이트
# 이전 IP 규칙 제거
aws ec2 revoke-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp \
  --port 22 \
  --cidr 203.0.113.50/32

# 새 IP 규칙 추가
MY_IP=$(curl -s https://checkip.amazonaws.com)
aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp \
  --port 22 \
  --cidr ${MY_IP}/32

echo "SSH 규칙 업데이트 완료: ${MY_IP}/32"

또는 웹 콘솔에서 간단하게 수정할 수 있습니다:

  1. EC2 → Security Groups → EC2 보안 그룹 선택
  2. Inbound rules → Edit inbound rules
  3. SSH 규칙의 Source를 "My IP"로 다시 변경
  4. Save rules
문제 2: SSH 규칙 변경 후 API(포트 5000)도 접속이 안 됨

원인: SSH 규칙을 변경할 때 실수로 포트 5000 규칙을 삭제하거나 변경했을 수 있습니다.

해결:

bash
# 현재 인바운드 규칙 확인
SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)

aws ec2 describe-security-groups \
  --group-ids ${SG_ID} \
  --query "SecurityGroups[].IpPermissions[].{
    Port:FromPort,
    Source:IpRanges[].CidrIp
  }" \
  --output table

# 포트 5000 규칙이 없다면 추가
aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp \
  --port 5000 \
  --cidr 0.0.0.0/0

echo "포트 5000 인바운드 규칙 복원 완료"
보안 그룹 규칙 편집 시 주의

Edit inbound rules 화면에서 SSH 규칙만 수정해야 합니다. 다른 규칙을 실수로 삭제하지 않도록 주의하세요. 실수로 규칙을 삭제한 경우, 위 CLI 명령어로 복원할 수 있습니다.

문제 3: RDS 보안 그룹 수정 후 데이터베이스 연결이 끊어짐

원인: RDS 보안 그룹의 소스를 변경할 때 EC2 보안 그룹 ID를 잘못 입력했거나, 규칙을 실수로 삭제했습니다.

해결:

bash
# EC2 보안 그룹 ID 확인
EC2_SG_ID=$(aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].SecurityGroups[0].GroupId" \
  --output text)
echo "EC2 보안 그룹: ${EC2_SG_ID}"

# RDS 보안 그룹 ID 확인
RDS_SG_ID=$(aws ec2 describe-security-groups \
  --filters "Name=group-name,Values=*RDS*" \
  --query "SecurityGroups[0].GroupId" \
  --output text)
echo "RDS 보안 그룹: ${RDS_SG_ID}"

# RDS 보안 그룹에 EC2 보안 그룹 소스 규칙 추가
aws ec2 authorize-security-group-ingress \
  --group-id ${RDS_SG_ID} \
  --protocol tcp \
  --port 3306 \
  --source-group ${EC2_SG_ID}

echo "RDS 보안 그룹 규칙 복원 완료"

# EC2에서 RDS 연결 테스트
# (EC2에 SSH 접속 후)
# mysql -h RDS_ENDPOINT -u admin -p
문제 4: 내 공인 IP 주소를 확인하는 방법

해결: 여러 방법으로 확인할 수 있습니다.

bash
# 방법 1: AWS 제공 서비스 (가장 권장)
curl -s https://checkip.amazonaws.com

# 방법 2: 다른 서비스
curl -s https://ifconfig.me
curl -s https://icanhazip.com
curl -s https://api.ipify.org

# 방법 3: AWS 콘솔에서 자동 입력
# Security Group 편집 시 Source를 "My IP"로 선택하면 자동으로 입력됩니다
가장 간편한 방법

AWS 콘솔에서 보안 그룹을 편집할 때 Source 드롭다운에서 "My IP"를 선택하면 IP를 직접 찾을 필요 없이 자동으로 입력됩니다. 이 방법을 가장 권장합니다.

문제 5: 잘못된 보안 그룹(기본 보안 그룹)을 수정함

원인: VPC에는 기본 보안 그룹(default)이 있습니다. ShopEasy EC2에 연결된 보안 그룹이 아닌 기본 보안 그룹을 수정한 경우입니다.

해결:

  1. 먼저 EC2 인스턴스에 연결된 정확한 보안 그룹 ID를 확인합니다.
  2. EC2 → Instances → ShopEasy 인스턴스 → Security 탭에서 보안 그룹 확인
  3. 해당 보안 그룹으로 이동하여 규칙을 수정합니다.
bash
# EC2에 연결된 정확한 보안 그룹 확인
aws ec2 describe-instances \
  --filters "Name=tag:Name,Values=ShopEasy*" \
  --query "Reservations[].Instances[].{
    Name:Tags[?Key=='Name'].Value|[0],
    SecurityGroups:SecurityGroups[].{Name:GroupName,ID:GroupId}
  }" \
  --output json
강사 참고: 학생 확인 체크포인트

각 학생의 보안 그룹이 올바르게 설정되었는지 다음을 확인하세요:

  1. EC2 보안 그룹 인바운드:
    • SSH (22): 소스가 학생의 IP/32 (0.0.0.0/0이 아닌지 확인)
    • Custom TCP (5000): 소스가 0.0.0.0/0 (서비스용)
  2. RDS 보안 그룹 인바운드:
    • MySQL/Aurora (3306): 소스가 EC2 보안 그룹 ID (0.0.0.0/0이 아닌지 확인)
  3. EC2 보안 그룹 아웃바운드:
    • All traffic: 0.0.0.0/0 (기본값 유지)
  4. SSH 접속 테스트: 변경 후 SSH 접속이 되는지 확인
  5. 서비스 테스트: S3 웹사이트에서 상품 조회, 리뷰 기능이 정상 동작하는지 확인
강사 참고: 보안 그룹 모범 사례 요약

학생들에게 다음 보안 그룹 모범 사례를 안내하세요:

  • 최소 권한 원칙: 필요한 포트만, 필요한 소스에서만 허용
  • SSH는 절대 0.0.0.0/0 금지: 내 IP 또는 VPN/Bastion Host를 통해서만 접근
  • 보안 그룹 ID를 소스로 활용: IP 대신 보안 그룹 참조로 유연하고 안전한 설정
  • 설명(Description) 작성: 각 규칙에 설명을 추가하여 관리 용이성 확보
  • 정기적인 검토: 사용하지 않는 규칙이 있는지 주기적으로 점검