따라서 VPC 내부에서 IPv4 주소로 보내는 모든 트래픽은 인터넷 게이트웨이로 보내라는 뜻이다.
모순적인 부분이 있다.
10.0.0.0/16으로 보내는 트래픽을 local로 보내라고 하지만, 0.0.0.0/0은 모든 IPv4 주소의 모든 트래픽을 인터넷 게이트웨이로 보내라고 한다.
그런데 두 조건을 둘 다 만족하는 IP 주소일 경우(ex. 10.0.0.5)에는 0.0.0.0/0의 주소보다 10.0.0.0/16의 주소가 더 구체적이기 때문에, 10.0.0.5로 트래픽을 보내는 경우에는 local로 보내게 된다.
여기까지 완료했다면VPC의 서브넷에 배치되어 있는 AWS 리소스가 외부 인터넷과 통신을 할 수 있을 것이다.
여기까지 세팅했다면 아래와 같은 인프라 아키텍쳐가 된다.
NAT 게이트웨이
프라이빗 서브넷에서는 퍼블릭 서브넷과 달리 인터넷 게이트웨이를 셋팅하면 안 된다.
왜냐하면 인터넷 게이트웨이는 VPC와 외부 인터넷 간에 통신할 수 있게 해주는 장치이기 때문이다. 프라이빗 서브넷은 보안을 위해 외부에서 접근이 불가능하게 만들어야 한다.
따라서프라이빗 서브넷은 인터넷 게이트웨이 대신에 NAT 게이트웨이를 셋팅해야 한다.
NAT 게이트웨이는 내부에서 외부로만 나갈 수 있는 출입구라고 생각하면 이해하기 편하다.
NAT 게이트웨이는외부 인터넷에서 서브넷으로 접근할 수는 없지만 서브넷에서 외부 인터넷으로 접근할 수 있게 해주는 장치다.
인터넷 게이트웨이는 외부 인터넷 → 서브넷의 방향으로도 통신이 가능했고, 서브넷 → 외부 인터넷의 방향으로도 통신이 가능하다.
반면NAT 게이트웨이는 서브넷 → 외부 인터넷의 방향으로만 통신이 가능하다는 뜻이다.
외부 인터넷 → 서브넷 방향의 통신
서브넷에 포함된 EC2 인스턴스의 백엔드 서버로 API 요청
서브넷에 포함된 EC2 인스턴스에 SSH로 접속
서브넷 → 외부 인터넷 방향의 통신
서브넷에 포함된 EC2 인스턴스에서 외부 API(ex. 날씨 API, OpenAI API 등) 호출
서브넷에 포함된 EC2 인스턴스에서 소프트웨어(ex. Nginx, git 등) 설치
NAT 게이트웨이는 VPC에 연결하는 것도 아니고, 프라이빗 서브넷에 연결하는 것도 아니다. NAT 게이트웨이는 퍼블릭 서브넷에 연결을 한다.
NAT 게이트웨이 생성
위 그림까지 아키텍쳐가 구성되었다고 가정.
1.NAT 게이트웨이 생성 페이지로 이동하기
2.NAT 게이트웨이 생성하기
연결 유형 : 외부 인터넷과 통신할 수 있게 만들기 위해 퍼블릭을 선택
NAT 게이트웨이는 생성되는 데 1~2분 정도의 시간이 걸리니 조금만 기다리면 된다.
3.라우팅 테이블 생성하기
라우팅 테이블을 만들어서트래픽이 프라이빗 서브넷 → NAT 게이트웨이의 방향으로 이동할 수 있게 경로를 설정해야한다.
4.라우팅 테이블에 서브넷 연결하기
5.라우팅 편집하기
이 페이지가 ‘어떤 경로로 트래픽을 전송해야 하는 지’를 직접 정의해야 하는 페이지다.
VPC 내부에서 10.0.0.0/16로 보내는 트래픽은 local로 보내라는 뜻이다. local로 보낸다는 건 Private IP를 활용해 내부에서 통신을 하겠다는 의미이다.
0.0.0.0/0은 “모든 IPv4 주소”를 의미한다. 따라서 ‘VPC 내부에서 IPv4 주소로 보내는 모든 트래픽은 NAT 게이트웨이로 보내라는 뜻이다.
그리고 AWS 공식 문서에 따르면 ‘IP 주소 범위가 더 구체적인 조건을 우선 적용한다’고 적혀 있다.
즉, 0.0.0.0/0의 주소보다 10.0.0.0/16의 주소가 더 구체적이기 때문에, 10.0.0.5로 트래픽을 보내는 경우에는 local로 보내게 된다.
또한 10.0.0.0/16에 해당하지 않는 IP 주소로 요청을 보내면 NAT 게이트웨이로 트래픽을 보낸다.
프라이빗 서브넷에 EC2 배치
1. EC2 인스턴스 생성 페이지로 이동
2. EC2 인스턴스 옵션 선택하기
3. 키 페어 생성하기
4. 나머지 EC2 인스턴스 옵션 설정하기
5. EC2 인스턴스에 접속하기
위 캡쳐 화면에서 퍼블릭 IPv4가 할당되지 않았고, 인스턴스가 퍼블릭 서브넷에 없어서 접속이 안 된다고 경고한다.
집에 있는 컴퓨터로 EC2 인스턴스에 접속하는 것도 ‘외부 인터넷 → 서브넷’ 방향의 요청이기 때문에 접속이 안 된다.
즉, 프라이빗 서브넷이 제 역할을 하고 있다는 뜻이기도 하다.
이제 아래와 같이 아키텍쳐가 구성되었다.
현재 구성에서 인터넷에서 프라이빗 서브넷에 있는 EC2 인스턴스로 접근할 수 있는 경로 자체가 없다. 이 때문에 외부에서 접속할 수가 없다.
프라이빗 서브넷의 EC2에 접속
프라이빗 서브넷(Private Subnet)은 외부에서 접근이 불가능하다.
하지만 같은 VPC 내부에서는 퍼블릭 서브넷의 리소스와 프라이빗 서브넷의 리소스가 자유자재로 통신이 가능하다.
1. 로컬 컴퓨터에서 퍼블릭 서브넷에 존재하는 EC2 인스턴스에 접속
$ cd [키 페어 파일이 존재하는 경로]
$ chmod 400 "web-server.pem" # 키 페어 파일 보안을 위한 권한 설정
$ ssh -i "web-server.pem" ubuntu@[EC2 인스턴스의 Public IP]
2. 퍼블릭 서브넷에 위치한 EC2 인스턴스로 키 페어 파일 보내기
퍼블릭 서브넷에 위치한 EC2 인스턴스(web-server)에서 프라이빗 서브넷에 위치한 EC2 인스턴스(instagram-server)로 접속할 것이다. web-server 인스턴스에서 instagram-server 인스턴스로 접속하는 게 가능한 이유는 같은 VPC에 존재하기 때문이다.
web-server 인스턴스에 접속할 때 web-server의 키 페어가 필요했던 것처럼, instagram-server 인스턴스에 접속할 때는 instagram-server의 키 페어가 필요하다. 따라서 instagram-server의 키 페어를 web-server 인스턴스로 전송해야 한다.
$ cd [키 페어 파일이 존재하는 경로]
# scp -i [EC2 접근을 위한 키 페어 파일] [전송할 파일명] [서버 username]@[EC2 인스턴스의 Public IP]:[전송 받을 파일 위치]
$ scp -i web-server.pem instagram-server.pem ubuntu@[EC2 인스턴스의 Public IP]:~/
3. web-server 인스턴스로 키 페어 파일이 잘 전송됐는지 확인
4. instagram-server로 접속해보기
$ cd [키 페어 파일이 존재하는 경로]
$ chmod 400 "instagram-server.pem" # 키 페어 파일 보안을 위한 권한 설정
$ ssh -i "instagram-server.pem" ubuntu@[EC2 인스턴스의 프라이빗 IP]
ubuntu@ 뒤에 보면 각 인스턴스의 Private IP가 작성되어 있다. @ 뒤에 적혀있는 부분이 각 컴퓨터에 붙여놓은 닉네임을 뜻한다.
이걸 보고 리눅스에서는 hostname이라고 부른다. instagram-server에 접속하기 전후의 hostname을 비교해보니 잘 접속이 됐다는 걸 확실하게 확인할 수 있다.
Bastion Host 프라이빗 서브넷에 있는 AWS 리소스인 EC2 인스턴스에 접근하기 위해, 퍼블릭 서브넷에 있는 EC2 인스턴스를 활용했다. 이와 같이 프라이빗 서브넷의 AWS 리소스에 접근하기 위해 앞단에 배치한 EC2(퍼블릭 서브넷에 위치한 EC2)를 보고 Bastion Host라고 부른다. Bastion Host를 활용해 외부에서 접근할 수 있는 경로는 딱 하나만 만들면 외부에서 접근할 수 있는 경로는 단 하나이기 때문에 보안적인 조치를 하기도 쉽고 관리도 쉬워진다.