관리 메뉴

Mini

[Redis] VPC 구성하기 본문

DevOps/Redis

[Redis] VPC 구성하기

Mini_96 2024. 11. 6. 21:54

* 의문 : WAS와 Redis간 통신보안의 best-practice?

  • WAS와 Redis를 같은 VPC에 배치
  • VPC 내부 통신만 허용

네, Redis 보안을 위한 Best Practice는 VPC 구성입니다. VPC를 통한 네트워크 격리가 가장 안전한 방법입니다.

flowchart TD
    subgraph "Public Subnet"
        ALB[Application Load Balancer]
    end

    subgraph "Private Subnet 1"
        WAS1[WAS Instance 1]
        WAS2[WAS Instance 2]
    end

    subgraph "Private Subnet 2"
        Redis[(Redis)]
    end

    Internet[Internet] --> ALB
    ALB --> WAS1
    ALB --> WAS2
    WAS1 --> Redis
    WAS2 --> Redis

    subgraph "Security Groups"
        SG1[ALB SG<br>80, 443]
        SG2[WAS SG<br>8080]
        SG3[Redis SG<br>6379]
    end

    style Redis fill:#f96,stroke:#333,stroke-width:4px
    style WAS1 fill:#99f,stroke:#333,stroke-width:2px
    style WAS2 fill:#99f,stroke:#333,stroke-width:2px

AWS VPC 구성을 위한 Terraform 코드 예시:

/**
 * Redis를 위한 VPC 및 보안 구성
 * @description AWS VPC, 서브넷, 보안 그룹 설정
 */

# VPC 생성
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main"
    Environment = "production"
  }
}

# 프라이빗 서브넷 (Redis용)
resource "aws_subnet" "redis_subnet" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "redis-subnet"
  }
}

# 프라이빗 서브넷 (WAS용)
resource "aws_subnet" "was_subnet" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "was-subnet"
  }
}

# Redis 보안 그룹
resource "aws_security_group" "redis_sg" {
  name        = "redis-security-group"
  description = "Security group for Redis"
  vpc_id      = aws_vpc.main.id

  # WAS 서브넷에서만 Redis 포트 접근 허용
  ingress {
    from_port       = 6379
    to_port         = 6379
    protocol        = "tcp"
    security_groups = [aws_security_group.was_sg.id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "redis-sg"
  }
}

# WAS 보안 그룹
resource "aws_security_group" "was_sg" {
  name        = "was-security-group"
  description = "Security group for WAS"
  vpc_id      = aws_vpc.main.id

  # 로드밸런서에서만 WAS 포트 접근 허용
  ingress {
    from_port       = 8080
    to_port         = 8080
    protocol        = "tcp"
    security_groups = [aws_security_group.alb_sg.id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "was-sg"
  }
}

# VPC Endpoint 설정 (AWS 서비스 접근용)
resource "aws_vpc_endpoint" "s3" {
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.ap-northeast-2.s3"
}

Best Practice 세부 설명:

  1. 네트워크 격리:
  2. network_isolation: vpc: - 전용 VPC 구성 - Private 서브넷 사용 - VPC Endpoint 활용 subnet: - Redis용 전용 서브넷 - WAS용 전용 서브넷 - 가용영역 분리
  3. 보안 그룹 설정:
  4. security_groups: redis_sg: - WAS 보안그룹에서만 접근 허용 - 6379 포트만 개방 - 아웃바운드 제한 was_sg: - ALB에서만 접근 허용 - 필요한 포트만 개방
  5. 접근 제어:
  6. access_control: network: - NACL 설정 - 라우팅 테이블 설정 - Flow Log 활성화 application: - IAM 역할 설정 - 암호화 통신
  7. 모니터링:
  8. monitoring: - VPC Flow Logs - CloudWatch 설정 - AWS Config 규칙 - GuardDuty 활성화

이러한 VPC 기반 구성의 장점:

  1. 보안:
    • 외부 접근 완전 차단
    • 네트워크 수준 격리
    • 세분화된 접근 제어
  2. 관리:
    • 중앙화된 관리
    • 자동화된 설정
    • 감사 용이성
  3. 확장성:
    • 유연한 리소스 확장
    • 서브넷 추가 용이
    • 멀티 AZ 구성 가능

주의사항:

  1. 비용 고려
  2. 복잡성 증가
  3. 초기 설정 시간 필요

추가 고려사항:

  1. 현재 어플리케이션의 규모는?
  2. 예상되는 트래픽 패턴은?
  3. 컴플라이언스 요구사항이 있나요?

이러한 정보를 추가로 알려주시면, 더 최적화된 VPC 구성을 제안드릴 수 있습니다.

* 의문2 : was, redis가 각각 공인 ip를 발급받아야 하는가?

아니요, 웹 서버를 제외한 나머지 서버들은 공인 IP가 필요하지 않습니다. 보안과 비용 측면에서 private 서브넷에 위치시키는 것이 Best Practice입니다.

flowchart TD
    subgraph "VPC"
        subgraph "Public Subnet"
            Bastion[Bastion Host<br>공인 IP]
            WebServer[Web Server<br>공인 IP]
        end

        subgraph "Private Subnet - Application Tier"
            WAS[WAS Server<br>사설 IP]
        end

        subgraph "Private Subnet - Data Tier"
            Redis[Redis Server<br>사설 IP]
        end
    end

    Internet[Internet] --> Bastion
    Internet --> WebServer
    Bastion -.-> WAS
    Bastion -.-> Redis
    WebServer --> WAS
    WAS --> Redis

    style WebServer fill:#f96,stroke:#333,stroke-width:4px
    style WAS fill:#99f,stroke:#333,stroke-width:2px
    style Redis fill:#9f9,stroke:#333,stroke-width:2px

각 서버별 네트워크 구성을 코드로 보여드리겠습니다:

/**
 * 클라우드 인프라 네트워크 구성
 * @description AWS VPC, 서브넷, 라우팅 설정
 */

# VPC 설정
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "main-vpc"
  }
}

# 퍼블릭 서브넷 설정
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true
  availability_zone       = "ap-northeast-2a"

  tags = {
    Name = "public-subnet"
  }
}

# 프라이빗 서브넷 - 애플리케이션 계층
resource "aws_subnet" "private_app" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "private-subnet-app"
  }
}

# 프라이빗 서브넷 - 데이터 계층
resource "aws_subnet" "private_data" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.3.0/24"
  availability_zone = "ap-northeast-2a"

  tags = {
    Name = "private-subnet-data"
  }
}

# 인터넷 게이트웨이
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name = "main-igw"
  }
}

# NAT 게이트웨이
resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "main-nat"
  }
}

# 탄력적 IP for NAT
resource "aws_eip" "nat" {
  domain = "vpc"
}

# 퍼블릭 라우팅 테이블
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }

  tags = {
    Name = "public-rt"
  }
}

# 프라이빗 라우팅 테이블
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
  }

  tags = {
    Name = "private-rt"
  }
}

# 보안 그룹 설정
resource "aws_security_group" "bastion" {
  name        = "bastion-sg"
  description = "Security group for Bastion host"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["관리자 IP/32"]
  }
}

resource "aws_security_group" "web" {
  name        = "web-sg"
  description = "Security group for Web servers"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

각 서버 유형별 특징과 권장 사항:

  1. 공인 IP가 필요한 서버:
  • 웹 서버 (또는 로드 밸런서)
    • 외부 접근 필요
    • HTTPS 통신
  • 배스천 호스트
    • 관리 접근용
    • SSH 접근만 허용
  1. 공인 IP가 필요없는 서버:
  • WAS 서버
    • 내부 통신만 필요
    • 보안 강화
  • Redis 서버
    • 데이터 보안
    • 내부 접근만 허용

Best Practices:

  1. 네트워크 구성:
  2. network_layout: public_subnet: - 웹 서버/로드밸런서 - 배스천 호스트 private_subnet: - WAS 서버 - Redis 서버 - 기타 내부 서비스
  3. 보안 설정:
  4. security_config: public_instances: - 최소한의 포트만 개방 - WAF 적용 - DDoS 보호 private_instances: - 내부 통신만 허용 - VPC 내부 통신 - 보안그룹 체이닝
  5. 접근 관리:
  6. access_management: bastion: - SSH 키 관리 - IP 화이트리스팅 - 세션 로깅 applications: - IAM 역할 사용 - 최소 권한 원칙

장점:

  1. 보안 강화
    • 직접적인 외부 접근 차단
    • 네트워크 격리
    • 접근 통제 용이
  2. 비용 절감
    • 공인 IP 비용 절감
    • 트래픽 비용 최적화
    • 관리 비용 감소
  3. 관리 용이성
    • 중앙화된 접근 관리
    • 단순화된 네트워크 구조
    • 명확한 책임 분리

주의사항:

  1. NAT 게이트웨이 비용 고려
  2. 배스천 호스트 관리 필요
  3. 네트워크 구성 복잡성

추가 고려사항:

  1. 서버 관리 방식은 어떻게 되나요?
  2. CI/CD 파이프라인 구성이 필요한가요?
  3. 장애 복구 계획은 어떻게 되나요?

이러한 정보를 추가로 알려주시면, 더 최적화된 네트워크 구성을 제안드릴 수 있습니다.

* 배스천 호스트란?

배스천 호스트(Bastion Host)는 외부에서 private 서브넷의 리소스에 안전하게 접근하기 위한 중간 서버/게이트웨이입니다. 흔히 "점프 서버"라고도 부릅니다.

flowchart TD
    Admin[관리자] -->|SSH| Bastion[Bastion Host<br>공인 IP<br>포트 22]

    subgraph VPC[VPC]
        subgraph "Public Subnet"
            Bastion
        end

        subgraph "Private Subnet"
            WAS[WAS Server<br>private IP]
            Redis[Redis Server<br>private IP]
            RDS[RDS<br>private IP]
        end
    end

    Bastion -->|SSH| WAS
    Bastion -->|SSH| Redis
    Bastion -->|SSH| RDS

    style Bastion fill:#f96,stroke:#333,stroke-width:4px
    style WAS fill:#99f,stroke:#333,stroke-width:2px
    style Redis fill:#99f,stroke:#333,stroke-width:2px
    style RDS fill:#99f,stroke:#333,stroke-width:2px

배스천 호스트 구성을 위한 코드 예시:

/**
 * 배스천 호스트 인프라 구성
 * @description AWS 배스천 호스트 및 보안 설정
 */

# 배스천 호스트 보안 그룹
resource "aws_security_group" "bastion" {
  name        = "bastion-sg"
  description = "Security group for Bastion Host"
  vpc_id      = aws_vpc.main.id

  # SSH 접근 제한
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["관리자_IP/32"] # 특정 IP만 허용
  }

  # 아웃바운드 규칙
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "bastion-sg"
  }
}

# 배스천 호스트 EC2 인스턴스
resource "aws_instance" "bastion" {
  ami           = "ami-0c55b159cbfafe1f0" # Amazon Linux 2
  instance_type = "t3.micro"
  subnet_id     = aws_subnet.public.id
  key_name      = aws_key_pair.bastion.key_name

  vpc_security_group_ids = [aws_security_group.bastion.id]

  # 사용자 데이터 스크립트
  user_data = <<-EOF
              #!/bin/bash
              # 보안 업데이트
              yum update -y

              # SSH 설정 강화
              sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
              sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

              # 감사 로깅 설정
              echo "*.* @log-server:514" >> /etc/rsyslog.conf

              # SSM Agent 설치
              yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
              systemctl enable amazon-ssm-agent
              systemctl start amazon-ssm-agent
              EOF

  tags = {
    Name = "bastion-host"
  }
}

# SSH 키 페어
resource "aws_key_pair" "bastion" {
  key_name   = "bastion-key"
  public_key = file("~/.ssh/id_rsa.pub")
}

# Systems Manager 역할
resource "aws_iam_role" "bastion" {
  name = "bastion-ssm-role"

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

배스천 호스트 사용 방법:

  1. SSH config 설정:
    # ~/.ssh/config
    Host bastion
     HostName {BASTION_PUBLIC_IP}
     User ec2-user
     IdentityFile ~/.ssh/bastion-key.pem
    

Host private-server
HostName {PRIVATE_IP}
User ec2-user
IdentityFile ~/.ssh/private-key.pem
ProxyCommand ssh bastion -W %h:%p


2. SSH 접속 명령어:
```bash
# 배스천 호스트 직접 접속
ssh bastion

# private 서버에 배스천 호스트를 통해 접속
ssh private-server

Best Practices:

  1. 보안 설정:
  2. security_measures: network: - 특정 IP만 접근 허용 - 최소 포트만 개방 (22) - VPC 내부통신만 허용 system: - 정기적 패치 적용 - 루트 로그인 비활성화 - 키 기반 인증만 허용 monitoring: - 접속 로그 기록 - CloudWatch 경보 설정 - SSM 세션 관리
  3. 관리 방안:
  4. management: access: - IAM 역할 사용 - MFA 적용 - 세션 타임아웃 설정 maintenance: - 자동 업데이트 - 백업 정책 - 장애 복구 계획

장점:

  1. 보안 강화
    • 단일 접근 포인트
    • 접근 로그 중앙화
    • 인프라 보호
  2. 관리 용이성
    • 중앙화된 접근 관리
    • 간편한 감사
    • 표준화된 접근 방식
  3. 비용 효율성
    • 단일 공인 IP 사용
    • 작은 인스턴스 사용 가능
    • 관리 비용 절감

주의사항:

  1. 단일 실패 지점이 될 수 있음
  2. 정기적인 보안 업데이트 필요
  3. 접근 키 관리 중요

대안:

  1. AWS Systems Manager Session Manager
  2. AWS Direct Connect
  3. VPN 연결

추가 고려사항:

  1. 몇 명의 관리자가 접근하나요?
  2. 어떤 종류의 관리 작업이 필요한가요?
  3. 컴플라이언스 요구사항이 있나요?

이러한 정보를 추가로 알려주시면, 더 최적화된 배스천 호스트 구성을 제안드릴 수 있습니다.

'DevOps > Redis' 카테고리의 다른 글

24.11.6. 개발일지 // cloud에 redis 설치, private subnet  (0) 2024.11.07