본문 바로가기

Computer Science/네트워크

네트워크 계층 - IP, CIDR, NAT

본 포스팅은 이석복 교수님의 네트워크 수업성공과 실패를 결정하는 상위 1%의 네트워크 원리를 참고하여 작성한 포스팅입니다.

 

우리가 네트워크에서 요청을 보내면 HTTP 요청이 작성이 되어서 네트워크를 구성하는 계층들을 거쳐 Multiplexing, De-multiplexing이 일어나면서 데이터를 주고받게 됩니다. 이번 포스팅에서 어플리케이션 계층인 HTTP 프로토콜과 Transport 계층인 TCP 프로토콜에 대한 자세한 내용은 생략하겠습니다.

대략적으로 TCP 프로토콜의 도움으로 데이터의 신뢰성 있는 전송, 네트워크 혼잡 제어, 네트워크 흐름 제어 등이 가능해졌습니다. 사용자의 입장에서 네트워크 속으로 패킷을 보내면 신뢰성있게 잘 전달되고 응답이 잘 돌아온다는 것은 이해했는데, 상대의 호스트까지 어떻게 패킷이 도달하게 되는지 구체적인 동작 원리를 잘 이해하기 위해 이번 포스팅에서 IP 프로토콜에 대한 내용을 살펴보겠습니다.

 

 

IP 패킷의 구조

 

메시지를 보낸다고 하면, 전송 계층에서 내려받은 TCP 세그먼트에 IP 헤더를 붙여 아래와 같은 IP 패킷을 완성하게 됩니다. IP 헤더에는 추가적으로 소스 IP 주소, 목적지 IP 주소와 TTL 정보, 수신자를 위한 상위 계층의 정보(TCP or UDP), 체크섬 등의 데이터를 포함하고 있습니다. 구체적으로 각 요소들을 살펴보겠습니다.

 

 

IP 주소(IPv4)

 

네트워크를 모르는 분이라도 IP주소는 들어보셨을 것입니다. IPv4 체계의 IP 주소는 32bit로 이루어진 네트워크 인터페이스를 식별할 수 있는 주소입니다.

 

 

IP 주소가 동작하는 원리

 

우리 인터넷은 무수히 많은 서브넷(Sub-Network)으로 이루어져 있습니다. 기본적으로 패킷이 전달되기 위해서는 라우터에서 다음 라우터로 패킷이 전송되고, 다음 라우터는 그 다음 라우터로 패킷을 전송하여 최종적으로 목적지까지 도달하게 됩니다. 라우터는 아래 그림처럼 대충 라우팅 테이블이라는 것을 가지고 있어 IP 주소를 어느 서브넷으로 보낼지 이 정보를 참조하여 결정합니다.

자, 그렇다면 위에서 인터넷이 무수히 많은 서브넷으로 이루어져 있다고 했는데, 만약 고작 몇 개의 네트워크에 모든 호스트가 있다면 어떻게 될까요? 라우팅 테이블에 매우 많은 정보가 들어가야 할 것입니다. 이러한 것은 전송의 측면에서 효율적이지 못하기 때문에 계층 구조를 활용합니다.

 

패킷의 전송을 우편을 보낼 때에 비유를 많이 하곤합니다만, 우편물에 상대의 IP 주소, 그리고 보내는 사람의 IP 주소가 적혀있다고 생각해보겠습니다. 그렇다면 주소 체계가 단순히 1번지부터 1000번지까지 이루어져있다고 생각하면 라우팅 테이블에는 많은 데이터가 필요합니다. 모든 도착지에 대한 라우팅 정보를 기록해야하기 때문입니다. 반면, 현 주소체계처럼 AA구 BB동 CC번지로 보낸다고 하면, 여러 화물센터를 거쳐 BB동에 보낼 화물끼리 모아서 처리할 수 있겠죠. 그리고 중간 화물 센터에서는 AA구로 보내는 화물은 이쪽 화물센터로, BB구로 보내는 화물은 저쪽 화물센터로 보내고 만약 AA구 화물센터에 도착한다면 이번에는 동별로 라우팅을 실시하여 최종적으로 목적지에 도달하게 할 수도 있습니다.

 

IP 주소에는 이러한 Scalability가 반영되어 있습니다. 바로 IP prefix와 Subnet Mask라는 개념을 통해서입니다.

IP Prefix는 IP주소를 서브넷의 인터페이스를 식별하는 network prefix와 서브넷 내의 각 Host를 식별하는 부분으로 나눕니다. 아래 그림의 예에서는 12.34.158.0/24라고 한다면, 24-bit 크기의 prefix를 가지고, 그 서브넷은 12.34.158의 prefix만으로 식별되며 하위에 어떤 IP 주소가 와도 그 서브넷에 속하는 호스트라고 판단할 수 있게 되는 것입니다. 마치 위의 AA동에 포함시키는 것과 비슷하죠.

 

서브넷 마스크는 이러한 prefix의 크기를 직관적으로 나타내는 개념입니다. 1 bit에 해당하는 숫자가 네트워크 영역임을 명시적으로 표시해줍니다.

 

따라서 이러한 Scalability로 위의 예시를 아래처럼 바꿀 수 있습니다.

1.2.3.0/24의 IP는 왼쪽 Subnet으로 가도록 라우팅하고, 5.6.7.0/24의 IP는 오른쪽 subnet으로 가도록 라우팅합니다. 이렇게 구성했을 때 라우팅 테이블에 단 두가지 데이터만 추가하면 되기 때문에 훨씬 효율적입니다. 뿐만 아니라, 확장성도 뛰어납니다. 추가로 오른쪽에 5.6.7.213이라는 호스트를 추가한다고 했을 때도 라우팅 테이블을 수정할 필요가 없게 됩니다.

 

그렇다면, 요런 IP 주소는 어떻게 할당되는 것일까요?

 

 

IP 주소의 할당

 

먼저, 90년대 이전의 전통의 IP 주소 할당 방식에 대해서 살펴보겠습니다. 흔히 많이들 알고 있는, 클래스 방식입니다.

 

이렇게 할당되었다고 합니다만, 이 클래스 방식을 사용했을 때, 고정된 호스트 수를 할당 받기 때문에 원하는 호스트 수에 비해서 턱없이 많은 호스트를 할당받는 경우가 생깁니다. 만약 1000개의 호스트를 사용하고 싶다면 위 표에서 1000개를 쓰기 위해서 65536개를 구입하지는 않기 때문에 클래스 B를 4개정도 구입하여 사용하게 될 것입니다. 그러한 경우, 만약 네트워크(서브넷)의 구분을 클래스로 하게 된다면, 라우팅 테이블에 불필요하게 서브넷이 4개가 생기기 때문에 낭비로 연결됩니다.

 

따라서 이 클래스 라우팅의 대안으로 CIDR이라는 개념이 등장했습니다.

 

 

CIDR(Classless Inter-Domain Routing)

 

CIDR은 클래스 없이 IP Address와 마스킹만으로 도메인 간 라우팅하는 기법입니다. CIDR은 특정 길이의 Network Prefix를 서브넷으로 간주한다고 볼 수 있습니다. 아래 그림처럼, 12.4.0.0/15라고 했을 때 네트워크의 식별을 앞의 15비트의 prefix로 기존 클래스 대비 유연하게 할 수 있습니다.

 

그리고 라우팅 시에는 아래의 그림처럼 찾아가게 되는 것입니다. 결국 위에서 언급했던 IP의 계층적 구조때문에 prefix 비트 사이즈에 따른 계층적 라우팅이 가능해집니다. 이후에 언급하겠지만 라우팅 테이블의 규칙에는 Longest Prefix Match Forwarding이라는 규칙이 존재하는데, 테이블에 여러 개의 주소와 매칭이 된다면 가장 구체적인 주소에 라우팅한다는 규칙입니다.

 

서브넷이란?
같은 IP Prefix를 가지는 네트워크 인터페이스를 서브넷이라고 합니다. 서브넷 안의 호스트 간에는 라우터를 안거치고 통신이 가능합니다.

 

 

NAT(Network Address Translation)의 등장

하지만 IPv4에서는 한가지 문제가 있었습니다. 바로, 32bit의 IP 주소가 전 세계의 호스트를 다루기에는 부족했다는 것입니다. 실제로 1990년대에는 IPv4를 발전시킨 IPv6에 대해서도 논의가 되었었는데요, 그런데도 아직까지 지금의 네트워크는 IPv4만으로 통신하고 있습니다. 256비트에 해당하는 40억개의 주소를 훨씬 초과했을텐데 어떻게 이런 일이 가능한걸까요?

 

바로 NAT의 도입으로 가능해졌습니다. NAT란 서브넷 내에서는 private IP라는 서브넷 간에 겹칠 수 있는 IP를 할당하고, 서브넷에서 나가거나 들어올 때, NAT를 통해 Address를 라우터에서 public IP로 바꾸어주는 방법입니다. 이 방법을 통해서 서브넷 내의 많은 호스트가 단일한 IP를 사용하는 것처럼 보이게 됩니다.

 

이 방법을 통해서 문제를 쉽게 해결할 수 있었습니다.

 

그렇지만 NAT를 사용하는 것의 단점도 있었습니다.

1. 라우터에서 private IP와 public IP를 변환하는 테이블의 정보를 추가로 저장해야합니다.

2. TCP 헤더의 포트, IP의 헤더의 IP 주소를 수정하는 오버헤드

3. L3에서 상위계층인 L4의 헤더를 수정하는 레이어 간 독립성을 위반

4. 포트를 호스트의 식별자로 사용하기 때문에, 포트의 원래 기능(프로세스 간 식별)을 사용하지 못하게 되었음