서브넷은 VPC에서 생성할 수 있는 논리적인 네트워크 공간이다. 서브넷의 네트워크는 VPC의 CIDR을 쪼개서 사용한다.
VPC 네트워크 환경을 구성하다 보면 퍼블릭/프라이빗 서브넷을 나누는 경우를 자주 보았을 것이다.
그런데 생성된 서브넷을 보다보면 이 서브넷이 퍼블릭인지 프라이빗인지 구분되어 있지 않다.
물론, Name 태그에 이 서브넷이 퍼블릭인지 프라이빗인지 적혀있는 경우도 많다.
하지만 Name 태그는 언제든지 바꿀 수 있는 값이기 때문에 이를 서브넷을 구분하는데 사용하는 것은 문제가 발생할 수 있다.
그렇다면, 퍼블릭/프라이빗 서브넷을 나누는 기준은 무엇일까?
어떻게 나누는지 알기 전, 굳이 서브넷을 나누는 이유가 무엇인지 짚고 넘어가자.
여러가지 이유가 있겠지만 필자가 생각하는 대표적인 이유는 2가지라고 생각한다.
VPC의 IP 대역 또한 우리가 VPC를 생성할 때 지정한다. CIDR을 이용하여 대역을 지정할 수 있다.
그런데 이렇게 생성된 VPC의 IP 주소를 마구잡이로 가져다 쓰면 문제가 발생 할 것이다.
우리가 CIDR을 사용하는 이유가 IP 주소를 좀 더 효율적으로 사용하고자 함인데, 생성된 VPC의 주소를 이렇게 막 써버리면 IP 대역을 지정한 의미가 없지 않은가?
그래서 하나의 큰 VPC를 여러개의 작은 서브넷으로 쪼개어 사용하고, 각 서브넷 별로 용도를 정해놓고 사용한다면 좀 더 효율적으로 IP 주소를 관리할 수 있을 것이다.
망분리
네트워크 망 간의 물리적/논리적 분리
일반적으로 인터넷과 같은 외부 네트워크와 기밀성이 높은 데이터가 저장되어 있는 내부 네트워크를 분리하여 내부 네트워크의 정보 유출을 방지
2012년 8월 정보통신망법 개정으로, 일정 규모 이상의 인터넷 사업자는 민감 정보 관리를 위한 망분리를 필수적으로 수행해야 한다.
네트워크 보안에 대해서 좀 공부를 해봤다면 망분리가 얼마나 중요한지는 알고 있을 것이다.
괜히 군대에서 인터넷망, 국방망, 전장망의 망분리를 철저히 수행하고 있는것이 아니다.(물론 군대는 AWS에서 퍼블릭/프라이빗 서브넷을 나누는 정도보다 훨씬 엄격히 나누고 있다.)
AWS에서는 이러한 망분리를 서로 다른 VPC를 사용하는 것, 그리고 서브넷을 나누어 사용하는 것을 통해 제공하고 있다.
퍼블릭/프라이빗 서브넷을 나누는 기준은 다음과 같다.
퍼블릭 : 인터넷망과 직접적인 통신이 가능하며, 외부에서 접근이 가능하다.
프라이빗 : 외부 인터넷망과 직접적인 통신이 불가능하며, 외부에서 접근할 수 없다.
//그림
VPC 내외부간 인터넷 통신을 위해 인터넷 게이트웨이(이하 IGW)가 사용된다.
VPC에는 기본적으로 하나의 IGW가 연결되어 있다.
주의할 점은 IGW는 서브넷과 연결된 것이 아닌 VPC에 연결되어있다는 것이다.
그렇다는건 서브넷은 설정 여하에 따라 인터넷과의 통신이 가능할지 결정되며, 서브넷의 생성 단계에서부터 원천 차단되는것이 아니라는 뜻이다.
어쨌든 서브넷은 VPC에 속해있으며, IGW는 VPC에 연결되어 있기 때문이다.
그렇다면, 우리가 퍼블릭/프라이빗 서브넷을 나누기 위한 설정은 무엇일까?
그것은 바로 보안그룹과 NACL, 그리고 라우팅테이블이다.
보안그룹과 NACL에 대한 설명은 이전 포스트에서 했기 때문에 생략한다.
우리는 보안그룹과 NACL의 규칙을 통해 여러 소스로부터 오는 트래픽에 대한 접근제어를 수행할 수 있는것을 알고 있다.
이를 이용해 프라이빗 서브넷에서 내부망 대역이 아니면 트래픽을 차단하도록 설정한다면 외부 인터넷망에서 프라이빗 서브넷으로 직접적인 접근이 불가능 할 것이다.
하지만, 이것만으로는 완전한 망분리를 수행할 수 없다.
보안그룹과 NACL에서 지정한 규칙을 만족하는 트래픽이라면 외부 인터넷망과 통신할 수 있을 것이다.
그래서 인터넷망과 프라이빗 서브넷간 통신을 시도하는 트래픽 자체가 원천적으로 차단되어야 할 것이다.
이때 사용하는 것이 라우팅 테이블이다.
라우팅
네트워크 상의 주소를 이용, 목적지까지 경로를 체계적으로 결정하는 경로선택 과정
네트워크를 배운 사람이라면 라우팅이라는 용어가 익숙할 것이며 이게 무엇을 의미하는지 잘 알고 있을 것이다.
라우팅 테이블을 통해 네트워크 트래픽이 어디로 전송될 지 결정한다.
AWS VPC 환경, 그리고 서브넷에서도 트래픽의 흐름을 라우팅 테이블을 기반으로 결정한다. 만약 라우팅 테이블에 적절한 정보가 없다면 트래픽이 어디로 전송될지 결정할 수 없기 때문에 드랍된다.
이 '정보가 없으면 드랍'. 이것이 AWS 서브넷에서의 망분리의 핵심이다.
이를 확인하기 위해 예시로 VPC 하나를 생성했다. VPC의 CIDR은 10.0.0.0/16 이다.
현재 TEST-vpc에는 2개의 서브넷, 각각 퍼블릭과 프라이빗 서브넷이 존재하고 각 서브넷별로 하나씩 라우팅 테이블이 연결되어 있다.
그리고 퍼블릭 서브넷을 담당하는 라우팅 테이블에는 IGW가 하나 연결되어 있다.
남은 하나의 라우팅 테이블은 원해 VPC 생성시 기본적으로 생성되기 때문에 현재 예시에서는 무시하여도 무방하다.
이제 각 라우팅 테이블의 정보를 한번 살펴보자.
우선 퍼블릭 서브넷의 라우팅 테이블이다.
10.0.0.0/16 대역인 VPC 내부가 목적지라면 다른데로 보내지 않고 local 트래픽이라고 지정되어 있다.
하지만, 그 외의 트래픽인 0.0.0.0/0 이 목적지라면 해당 트래픽은 IGW로 보내도록 설정되어 있다.
즉, VPC 내부가 목적지인 트래픽이 아니라면 IGW로 전송되며 해당 트래픽은 IGW를 거쳐 외부 인터넷망으로 전송된다는 뜻이다.
다음으로 프라이빗 서브넷의 라우팅 테이블이다.
10.0.0.0/16 대역인 VPC 내부가 목적지라면 다른데로 보내지 않고 local 트래픽이라고 지정되어 있다.
하지만, 그 뿐이다. VPC 내부 대역이 목적지가 아닌 트래픽은 라우팅 테이블에 선언되어 있지 않다.
따라서, VPC 대역이 목적지가 아닌 트래픽은 전부 드랍된다.
즉, 외부 인터넷망이 목적지인 트래픽은 전부 이 라우팅 테이블 선에서 드랍되어 원천 차단되는 것이다.
이렇게 적절한 라우팅 테이블을 서브넷에 연결하는 것을 통해 우리는 좀 더 안전한 AWS 네트워크 환경을 구성할 수 있다.
그리고 퍼블릭/프라이빗 서브넷을 구분하는 주요 요소는 서브넷 자체가 아니라 서브넷에 연결된 라우팅 테이블이 담당하는 것을 알 수 있다.
만약 위 예시의 퍼블릭 서브넷과 프라이빗 서브넷의 라우팅 테이블을 서로 바꾼다면, 두 서브넷의 역할이 바뀔 것이다.
위에서 IGW에 대한 언급이 있었다. 그에 대한 정의를 짚고 넘어가지 않았는데 한번 알아보자.
인터넷 게이트웨이(Internet Gateway)
수평 확장되고 가용성이 높은 VPC 구성 요소로, VPC와 인터넷 간에 통신할 수 있게 해줍니다. IPv4 트래픽 및 IPv6 트래픽을 지원합니다. 네트워크 트래픽에 가용성 위험이나 대역폭 제약이 발생하지 않습니다.
즉, 간단히 말하면 그냥 VPC가 인터넷과의 통신을 위해서는 IGW가 있어야 된다고만 이해해도 크게 문제될 건 없다.
IGW와 라우팅테이블 설정으로 인터넷망과 퍼블릭 서브넷의 통신을 가능하게 하고, 인터넷망과 프라이빗 서브넷의 통신을 차단하면 이제 만사형통인듯 하다.
하지만 다음 상황을 생각해보자.
VPC에는 퍼블릭 서브넷과 프라이빗 서브넷이 존재한다.
각 서브넷에는 하나씩 인스턴스가 생성되어 있다.
퍼블릭 서브넷의 라우팅 테이블에는 IGW와의 통신을 위한 규칙이 설정되어 있지만, 프라이빗 서브넷의 라우팅 테이블에는 없다.
인스턴스에는 각각 응용프로그램이 하나씩 작동 중이다.
당신은 각 인스턴스에서 구동중인 응용프로그램을 업데이트 해야한다.
업데이트는 인터넷의 업데이트 서버에 접속하여 수행된다.
퍼블릭 서브넷은 업데이트 하는데 문제 없지만, 프라이빗 서브넷은 인터넷에 접속이 불가능 하기 때문에 업데이트가 불가능하다.
이 경우 당신은 이 문제를 어떻게 해결할 것인가?
골치 아픈 상황이다.
이거 뭐 프라이빗 서브넷의 라우팅 테이블을 업데이트 할때만 바꿀수도 없는 노릇이고, 프라이빗 서브넷의 인스턴스를 퍼블릭으로 옮긴 다음에 업데이트를 수행하고 다시 원위치 시키는것도 좀 이상하다.
백번 양보해서 진짜 이런식으로 업데이트를 한다 치자.
그럼 만약, 주기적으로 업데이트를 해야 하고 업데이트할 인스턴스가 엄청 많으면?
그럼 그때마다 일일이 라우팅 규칙을 바꿔가며 업데이트를 수행해야 하는게 이거는 Elastic하지 못하다.
이를 해결할 수 있는것이 바로 'NAT 게이트웨이' 이다.
만약 NAT라는것이 무엇인지 모른다면 이 링크를 한번 읽어보고 오자.
NAT 게이트웨이
NAT(네트워크 주소 변환) 서비스이다.
프라이빗 서브넷의 인스턴스가 VPC 외부의 서비스에 연결할 수 있지만 외부 서비스에서 이러한 인스턴스와의 연결을 시작할 수 없도록 NAT 게이트웨이를 사용할 수 있다.
NAT 게이트웨이(이하 NAT GW)를 사용한다면 어떻게 이 문제를 해결할 수 있는지 한번 예시를 통해 알아보자.
위에서 예시로 생성한 VPC와 동일한 구조로 새로 VPC를 생성해보겠다. 다만, 여기에 NAT GW만 하나 추가하는 것이다.
이전 예시에서는 없던 NAT GW 하나가 프라이빗 서브넷의 라우팅 테이블에 연결되어 있는것을 확인할 수 있다.
그렇다면 프라이빗 서브넷의 라우팅 테이블 규칙을 한번 확인해보자.
아까는 없던 0.0.0.0/0이 목적지인 패킷에 대한 라우팅 규칙이 생겼고 이를 NAT GW로 전달하고 있다.
그렇다면 이 NAT GW는 어디에 생성되어 있을까?
이 NAT GW는 퍼블릭 서브넷에 생성되어 있다. 퍼블릭 서브넷의 라우팅 규칙은 이전과 동일하다.
이를 정리해보면 다음과 같다.
프라이빗 서브넷에서 외부망으로 나가는 트래픽은 프라이빗 서브넷의 라우팅 테이블에 의거하여 우선 NAT GW로 전달된다.
NAT GW는 퍼블릭 서브넷에 소속되어 있다. 이후, NAT GW는 전달받은 트래픽을 NAT 주소변환을 통해 출발지 주소가 본인에게 할당된 EIP(Elastic IP) 주소로 변경한다.
그리고 해당 트래픽은 다시 퍼블릭 서브넷의 라우팅 테이블에 의거하여 IGW로 전달되고, 외부 인터넷망으로 패킷이 전달된다.
이렇게 NAT GW를 통해 문제를 해결했다.
이해를 위해 VPC 구조도를 보며 몇가지 상황을 살펴보자.
보안그룹과 NACL은 적절히 설정되어 있다 가정한다.
클라이언트가 웹서버에 요청을 보냈고, 해당 요청을 처리하기 위해 DB 접근이 필요한 경우
클라이언트의 요청은 IGW를 통해 VPC 내부로 전달된다.
요청은 라우팅 테이블에 의거하여 Web 인스턴스에 도달한다.
Web 인스턴스는 해당 요청을 처리하기 위해 DB에 접근해야 하고 DB 인스턴스로 트래픽을 전송한다.
같은 VPC 내부이기 때문에 해당 트래픽은 DB 인스턴스로 전달되며 DB 쿼리에 대한 응답이 다시 Web 인스턴스로 전달된다.
이후, Web 인스턴스는 처리된 요청을 다시 클라이언트에 응답한다.
응답 트래픽의 목적지는 VPC의 외부이기 때문에 라우팅 테이블에 의거하여 트래픽은 IGW로 전달되며 클라이언트에게 응답이 전달된다.
클라이언트가 직접 DB에 접속을 시도하는 경우
프라이빗 서브넷에 있는 인스턴스는 Public IP를 가질 이유가 없다. 그렇기 때문에 외부에서 직접 요청은 불가능하다.
이와 더불어 보안그룹과 NACL의 규칙에서도 해당 요청은 차단될 것이다.
즉, 외부에서 직접 DB 인스턴스로 요청을 보낼 방법은 없다.
DB 인스턴스의 소프트웨어를 인터넷을 통해 업데이트 해야하는 경우
DB 인스턴스는 소프트웨어 업데이트를 통해 VPC 외부에 있는 업데이트 서버로 트래픽을 전송한다.
해당 트래픽은 프라이빗 서브넷의 라우팅 테이블에 의거하여 우선 퍼블릭 서브넷에 있는 NAT GW로 전달된다.
NAT GW에 전달된 트래픽은 NAT 주소 변환에 의거하여 출발지 주소가 NAT GW에 할당된 EIP 주소로 변경된다.
그 후, 트래픽을 다시 전달한다. 퍼블릭 서브넷의 라우팅 테이블에 의거하여 트래픽은 IGW로 전달되며 외부망의 업데이트 서버에 전달된다.