데이터의 심장인 DB를 외부 공격으로부터 보호하기 위해 네트워크 장벽을 세우는 방법입니다.
1. 네트워크 격리: Public vs Private Subnet
VPC 내에서 서브넷을 용도에 따라 엄격히 분리해야 한다.
- Public Subnet (공개 영역)
- 외부 인터넷과 직접 통신이 가능한 영역이다.
- 배치 리소스: 로드밸런서(ALB), 배스천 호스트(Bastion Host), NAT 게이트웨이
- Private Subnet (비공개 영역)
- 외부 인터넷에서 직접 들어올 수 없는 안전한 영역이다.
- 배치 리소스: API 서버(EC2/ECS), 데이터베이스(RDS), 캐시(ElastiCache)
- 핵심 원칙: DB는 절대로 Public Subnet에 두지 않는다. “Publicly Accessible”옵션을 무조건
No로 설정해야 한다.
2. 보안 그룹(Security Group) 설계: 최소 허용
보안 그룹은 서버 바로 앞을 지키는 가상 방화벽이다. 여기서 가장 큰 실수는 DB 포트를 모두에게 공개하는 것이다.
보안 그룹 체이닝 (Best Practice)
IP 주소를 직접 입력하는 대신 ‘보안 그룹 ID’를 소스(Source)로 지정하는 방식을 사용한다.
- 웹 서버 보안 그룹 (Web-SG):
- Inbound: 80/443 포트 허용 (Source:
0.0.0.0/0 또는 ALB-SG)
- DB 보안 그룹 (DB-SG):
- Inbound: 3306 포트 허용 (Source: Web-SG의 ID)
- 이렇게 설정하면 Web-SG를 가진 서버들만 DB에 접속할 수 있으며, 서버의 IP가 바뀌어도 설정을 수정할 필요가 없다.
3. 배스천 호스트(Bastion Host) 운용
DB가 Private Subnet에 있으면 개발자도 집에서 직접 접속할 수 없다. 이때 통로 역할을 하는 서버가 필요하다.
- 작동 원리: Public Subnet에 아주 작은 EC2를 하나 띄우고 개발자는 이 서버에 먼저 SSH로 접속한 뒤 거기서 다시 DB로 접속하는 것이다.
- 최신 트랜드: 최근에는 배스천 호스트 대신 AWS System Manager (SSM) Session Manager를 권장한다. 22번 포트를 열지 않고도 브라우저나 CLI를 통해 안전하게 서버에 접속할 수 있다.
4. 데이터 암호화 (Encryption)
네트워크 장벽을 뚫고 데이터가 유출되더라도 읽을 수 없게 만들어야 한다.
- 저장 시 암호화 (At-Rest): RDS 생성 시 AWS KMS 키를 사용하여 디스크 자체를 암호화한다. (생성 후에는 변경이 매우 어려우니 잘 설정해야 한다)
- 전송 시 암호화 (In-Transit): 애플리케이션과 DB가 통신할 때 SSL/TLS 연결을 강제하여 네트워크 패킷 스내핑을 방지한다.
5. 체크리스트
- DB 접근성: RDS의 퍼블릭 액세스 가능성 설정이
No인가?
- 보안 그룹 소스 제한: DB 보안 그룹의 소스가 특정 IP가 아닌 애플리케이션 서버의 보안 그룹 ID로 되어있는가?
- 불필요한 포트 폐쇄: 사용하지 않는 포트가 인바운드 규칙에 남아있지 않은가?
- 관리자 계정 보호: DB의
admin, root 계정은 아무에게나 알려지지 않으며 애플리케이션은 별도의 권한이 제한된 계정을 사용하고 있는가?
- VPC 엔드포인트: S3나 Secrets Manager 등에 접근할 때 인터넷을 거치지 않고 VPC 내부방을 통하도록 VPC 엔드포인트를 설정했는가? (보안 및 비용 최적화)