Internet Protocol (2) — VLSM·CIDR, Route Aggregation, 라우터 내부, IP Forwarding, NAT

1편은 IPv4 헤더와 단편화, classful 주소 체계와 서브네팅에서 끝났다. 서브네팅은 한 조직 내부를 나누는 기법이었지만 두 가지 제약이 남는다. 모든 서브넷이 같은 크기여야 하고, 인터넷 코어는 여전히 클래스 단위로 주소를 봤다. 이 제약을 차례로 깨는 것이 VLSM과 CIDR이다.

VLSM (Variable-Length Subnet Mask)

기본 서브넷 마스크는 모든 서브네트워크가 같은 수의 호스트를 갖도록 강제한다. site-wide subnet mask를 255.255.255.0으로 잡으면 256개 서브넷이 각각 254개 호스트를 수용하는 식으로 균일하게 쪼개진다. 그런데 현실의 조직은 그렇지 않다. 어떤 부서는 호스트가 100대고 어떤 링크는 라우터 둘만 연결한다. 균일 분할은 주소를 낭비한다.

VLSM(가변 길이 서브넷 마스크) [RFC 1878]은 서브넷마다 다른 길이의 마스크를 허용한다. 큰 서브넷은 짧은 마스크(/24)로, 라우터 간 점대점 링크는 긴 마스크(/30)로 잘게 쪼갠다.

VLSM 예시 토폴로지 — 서브넷마다 다른 prefix length

위 예시는 128.32.0.0/16 사이트를 하나의 마스크로 균일하게 나누지 않는다. 호스트가 많은 LAN은 128.32.1.0/24, 128.32.2.0/24로 두고, 내부 라우터 뒤의 작은 세그먼트는 128.32.230.128/26, 128.32.2.128/25처럼 서로 다른 prefix length를 부여한다. 외부 인터넷은 여전히 128.32.0.0/16 하나만 보지만, 내부에서는 필요한 크기에 맞춰 주소를 재단한다.

CIDR (Classless Inter-Domain Routing)

VLSM은 ‘site-local’ 네트워크 안에서의 유연성이다. 1990년대 초까지도 인터넷 코어 라우팅은 여전히 classful이었다. 라우터는 주소의 첫 비트로 클래스를 판별하고 그에 따라 고정된 마스크를 적용했다.

CIDR(Classless Inter-Domain Routing) [RFC 4632]은 인터넷 라우팅 시스템에서 클래스 개념 자체를 제거한다. 대신 CIDR 마스크를 명시해 prefix를 추출한다. 클래스 A/B/C라는 고정 경계가 사라지고, 마스크 길이를 임의로(/0부터 /32까지) 지정할 수 있다. 핵심은 이 마스크가 이제 전역 라우팅 시스템에 노출되어 처리된다는 점이다.

Prefix Address Range
0.0.0.0/0 0.0.0.0 – 255.255.255.255
128.0.0.0/1 128.0.0.0 – 255.255.255.255
128.0.0.0/24 128.0.0.0 – 128.0.0.255
198.128.128.192/27 198.128.128.192 – 198.128.128.223
165.195.130.107/32 165.195.130.107

classless의 의미는 이렇게 정리된다. 주소만으로는 그 주소가 속한 블록을 알 수 없다. 예를 들어 230.8.24.56은 prefix length에 따라 전혀 다른 블록에 속한다.

Prefix length Block
16 230.8.0.0 – 230.8.255.255
20 230.8.16.0 – 230.8.31.255
26 230.8.24.0 – 230.8.24.63
29 230.8.24.56 – 230.8.24.63
31 230.8.24.56 – 230.8.24.57

같은 주소라도 마스크 길이가 함께 주어져야 비로소 어느 블록인지 확정된다. 그래서 classful 시절과 달리 마스크가 라우팅 정보의 일부로 항상 따라다닌다.

주소 할당 예제

CIDR에서 주소 블록을 나누는 감각을 예제로 잡는다.

예제 1. 조직이 130.34.12.64/26 블록을 받았고, 호스트 수가 같은 4개 서브넷이 필요하다.

전체 주소 수는 $N = 2^{32-26} = 64$개다. 첫 주소는 130.34.12.64, 마지막은 130.34.12.127이다. 4개로 균등 분할하려면 서브넷당 16개씩 준다($64/16 = 4$, 2의 거듭제곱이라 가능). 서브넷 마스크는

\[n_i = n + \log_2(N/N_i) = 26 + \log_2 4 = 28\]

따라서 각 서브넷은 /28이고, 시작 주소는 130.34.12.64, 130.34.12.80, 130.34.12.96, 130.34.12.112가 된다. 각 서브넷의 시작 주소는 그 서브넷의 주소 수로 나누어떨어진다는 규칙을 기억하면 검산이 쉽다.

예제 2. 14.24.74.0/24 블록(256개 주소)을 120, 60, 10개짜리 세 서브블록으로 나눈다.

요청 수가 2의 거듭제곱이 아니어도, 이상의 가장 가까운 2의 거듭제곱을 할당한다.

  • 120개 요청 → 128개 할당 → /2514.24.74.0/25
  • 60개 요청 → 64개 할당 → /2614.24.74.128/26
  • 10개 요청 → 16개 할당 → /2814.24.74.192/28

합이 208개이므로 48개가 예비로 남는다(14.24.74.208 ~ 14.24.74.255).

Route Aggregation

CIDR이 진짜 위력을 발휘하는 지점은 라우팅 테이블 축소다. 발상은 계층적 라우팅(hierarchical routing)에서 왔다. 네트워크 토폴로지가 트리 모양이고 주소가 그 토폴로지에 맞게(topology-sensitive) 배정되면, 최단 경로를 유지하면서도 라우팅 테이블을 아주 작게 유지할 수 있다.

RFC 2008은 이렇게 못 박는다. “Hierarchical routing is … the only proven mechanism for scaling routing to the current size of the Internet.” 계층적 라우팅은 현재 규모의 인터넷을 지탱하는 유일하게 검증된 확장 메커니즘이다.

Route aggregation은 수치적으로 인접한(numerically adjacent) 여러 IP prefix를 하나의 더 짧은 prefix(aggregate 또는 summary)로 합쳐 더 넓은 주소 공간을 커버하는 것이다.

Route aggregation — 인접 prefix를 하나의 짧은 prefix로 합친다

예를 들어 R2가 200.10.0.0/19, 200.10.32.0/19, 200.10.64.0/19, 200.10.96.0/19 네 블록을 R1에게 광고할 때, R1은 이를 200.10.0.0/17 하나로 묶어 상위 네트워크에 광고한다. R3 쪽의 네 블록도 200.10.128.0/17로 묶이고, 최종적으로 R1은 바깥세상에 200.10.0.0/16 하나만 알린다. 수백 개의 세부 경로가 하나의 entry로 압축되는 셈이다. 이렇게 여러 네트워크를 하나의 더 큰 prefix로 광고하는 것을 supernetting이라 부른다.

What’s Inside a Router

주소 체계를 정리했으니, 그 주소를 보고 실제로 패킷을 옮기는 장치 내부를 본다.

라우터 구조 — control plane(software)과 data plane(hardware)

라우터는 크게 네 부분이다.

  • 입력 포트(input ports): 들어오는 링크를 종단하고, 헤더를 보고 어느 출력 포트로 보낼지 결정한다.
  • 스위칭 패브릭(switching fabric): 입력 포트에서 출력 포트로 패킷을 실제로 옮기는 내부 연결망.
  • 출력 포트(output ports): 나가는 링크로 패킷을 전송한다.
  • 라우팅 프로세서(routing processor): 라우팅 프로토콜을 돌리고 포워딩 테이블을 관리한다.

여기서 시간 척도가 둘로 갈린다. 라우팅 프로세서가 담당하는 제어 평면(control plane)은 소프트웨어로 동작하며 밀리초 단위로 움직인다. 반면 입력/출력 포트와 패브릭이 담당하는 포워딩 데이터 평면(forwarding data plane)은 하드웨어로 동작하며 나노초 단위로 패킷을 처리해야 한다. 라우팅은 느려도 되지만 포워딩은 ‘line speed’를 따라가야 한다.

Input Port와 Decentralized Switching

입력 포트는 물리 계층(bit-level 수신) → 링크 계층(예: 이더넷) → lookup/forwarding 순으로 처리한다. 마지막 단계가 분산 스위칭(decentralized switching)이다.

  • 헤더 필드 값으로 입력 포트 메모리 안의 포워딩 테이블을 조회해 출력 포트를 찾는다(“match plus action”).
  • 목표는 입력 포트 처리를 line speed로 완료하는 것이다.
  • 패킷이 패브릭으로 빠지는 속도보다 빨리 도착하면 입력 포트 큐잉(input port queuing)이 발생한다.

포워딩 방식은 둘로 나뉜다. destination-based forwarding은 목적지 IP 주소만 보고 포워딩하는 전통적 방식이고, generalized forwarding은 임의의 헤더 필드 집합을 보고 포워딩한다(SDN의 기반).

Longest Prefix Matching

destination-based 포워딩 테이블을 주소 범위(range)로 표현하면, 범위가 깔끔하게 나뉘지 않을 때 문제가 생긴다. 그래서 실제로는 prefix로 표현하고 longest prefix matching(최장 prefix 일치)을 쓴다.

주어진 목적지 주소에 대해 포워딩 테이블 entry를 찾을 때, 일치하는 가장 긴 prefix를 사용한다.

Destination Address Range Link interface
11001000 00010111 00010*** ******** 0
11001000 00010111 00011000 ******** 1
11001000 00010111 00011*** ******** 2
otherwise 3

목적지가 11001000 00010111 00011000 10101010이라 하자. 이 주소는 interface 2의 prefix(...00011***)에도 맞고 interface 1의 prefix(...00011000)에도 맞는다. 둘 다 일치하지만 더 긴 interface 1의 prefix를 택한다. 반면 ...00010110 10100001은 interface 0의 prefix에만 맞으므로 0으로 간다.

longest prefix matching은 라우팅 테이블이 클 때 비싼 연산이다. 그래서 고성능 라우터는 TCAM(Ternary Content Addressable Memory)으로 처리한다. 주소를 제시하면 테이블 크기와 무관하게 한 클럭 사이클에 매칭 결과를 얻는다. Cisco Catalyst는 약 100만 개의 라우팅 테이블 entry를 TCAM에 담는다.

IP Forwarding

이제 호스트와 라우터 관점에서 포워딩이 어떻게 일어나는지 본다.

호스트에서의 전달: Direct vs Indirect

  • 직접 전달(Direct Delivery): 목적지가 링크 계층에서 직접 연결되어 있으면, IP 데이터그램을 목적지로 바로 보낸다. 라우터가 전혀 필요 없다.
  • 간접 전달(Indirect Delivery): 그 외의 경우, 호스트는 데이터그램을 하나의 라우터로 보내고 그 라우터가 전달을 책임지게 한다. 목적지에 대한 next-hop 라우터가 포워딩 테이블에 있으면 그쪽으로, 없으면 default 라우터가 받는다.

Forwarding 기법 — 테이블을 줄이는 방법들

라우팅 테이블을 작게 유지하기 위해 교과서는 여러 기법을 소개한다.

  • Next-hop Method: 전체 경로 대신 다음 홉 주소만 저장한다. A는 “Host B로 가려면 R1로”만 알면 되고, 전체 경로 R1, R2, Host B를 들고 있을 필요가 없다.
  • Network-Specific Method: 같은 물리 네트워크에 연결된 호스트마다 entry를 두지 않고, 목적지 네트워크 주소 하나로 묶는다. N2의 A, B, C, D를 각각 적는 대신 “N2 → R1” 한 줄로 충분하다.
  • Host-Specific Method: 반대로 특정 호스트 주소를 테이블에 명시한다. 비효율적이지만 관리자가 라우팅을 세밀하게 제어하고 싶을 때 쓴다.
  • Default Method: 인터넷의 모든 네트워크를 나열하는 대신 default(보통 0.0.0.0) entry 하나로 나머지를 처리한다.

라우터에서의 수신

라우터의 포워딩 테이블은 보통 Destination, Mask, Next-hop, Interface 컬럼을 갖는다. 포워딩은 longest prefix matching으로 수행하고, 여러 entry가 일치하면 대부분 첫 entry를 쓴다(일부 구현은 부하 분산을 시도한다).

핵심은 IP 포워딩이 hop-by-hop으로 이뤄진다는 점이다. 즉 어떤 라우터도 전체 경로 정보를 갖지 않는다. 각 라우터는 자기 다음 홉만 결정하고, 전체 경로의 정합성은 RIP·OSPF·BGP·IS-IS 같은 라우팅 프로토콜이 보장한다. 다만 가정용 무선 공유기는 보통 라우팅 프로토콜을 전혀 돌리지 않는다.

Unix 계열의 (커널 IP) 라우팅 테이블은 현대 교과서에서 forwarding table이라 부르고, RFC에서는 FIB(Forward Information Base)라 한다.

Multi-homed 호스트와 Host Model

인터페이스가 여러 개인 multi-homed 호스트에서는 데이터그램 처리가 미묘해진다. [RFC 1122]는 두 가지 모델을 정의한다.

  • Strong host model: 데이터그램을 수신/송신할 때 {목적지, 출발지} IP 주소가 그 인터페이스와 유효하게 대응해야 한다. 보안상 이점이 있다.
  • Weak host model: 목적지 IP가 호스트의 아무 인터페이스와 일치하기만 하면 수신을 받아들인다.

OS마다 기본값이 다르다. Linux는 weak host model, 현대 Windows는 strong host model이 기본이다.

NAT (Network Address Translation)

IPv4 주소는 32비트라 약 43억 개뿐이고, 일찍부터 고갈이 예견됐다. NAT는 이 문제에 대한 실용적 대응이다.

NAT: 외부 세계가 보기에, 로컬 네트워크의 모든 장치가 단 하나의 IPv4 주소를 공유한다.

로컬 네트워크의 장치들은 사설 IP 주소 공간(10/8, 172.16/12, 192.168/16)을 쓴다. 이 주소는 로컬 안에서만 유효하다. NAT 라우터는 바깥으로 나갈 때 하나의 공인 주소로 바꿔 내보낸다.

NAT 동작 — translation table로 (주소, 포트)를 변환한다

동작은 NAT translation table을 중심으로 돈다.

  1. 내부 호스트 10.0.0.1:3345128.119.40.186:80으로 데이터그램을 보낸다.
  2. NAT 라우터는 출발지를 138.76.29.7:5001(NAT 공인 주소 + 새 포트)로 바꾸고, 이 변환 쌍을 테이블에 기록한다.
  3. 응답이 138.76.29.7:5001을 목적지로 도착한다.
  4. NAT 라우터는 테이블을 조회해 목적지를 원래의 10.0.0.1:3345로 되돌려 내부로 전달한다.

여기서 포트 번호가 핵심이다. 모든 나가는 데이터그램이 같은 출발지 IP를 갖지만 서로 다른 출발지 포트를 부여받기 때문에, 응답이 돌아올 때 어느 내부 호스트의 것인지 구분할 수 있다.

NAT의 장점은 분명하다. ISP로부터 공인 주소 하나만 받으면 되고, 내부 주소를 바꿔도 외부에 알릴 필요가 없으며, ISP를 바꿔도 내부 장치 주소를 그대로 둔다. 보안 측면에서도 내부 장치가 외부에서 직접 주소 지정되지 않는다.

물론 논쟁도 있다. 라우터는 계층 3까지만 처리해야 하는데 NAT는 포트(계층 4)를 건드린다. 주소 부족은 IPv6로 풀어야 한다는 주장, end-to-end 원칙 위배, NAT 뒤의 서버에 접속하려는 NAT traversal 문제 등이 지적된다. 그럼에도 NAT는 가정·기관 네트워크와 4G/5G 셀룰러망에서 광범위하게 쓰이며 사라지지 않는다.

IPv6와 터널링

NAT가 임시방편이라면 근본 해법은 IPv6다. 처음 동기는 32비트 IPv4 주소 공간 고갈이었고, 부차적으로 40바이트 고정 헤더로 처리 속도를 높이고 ‘flow’ 단위의 차별화된 처리를 가능하게 했다.

IPv6 데이터그램은 IPv4 대비 다음을 없앴다.

  • checksum 없음: 라우터 처리 속도 향상.
  • fragmentation/reassembly 없음: 중간 라우터에서 단편화 불가.
  • options 없음: 필요하면 next-header로 연결되는 확장 헤더로 처리.

Transition: Tunneling

문제는 모든 라우터를 동시에 업그레이드할 수 없다는 것이다(‘flag day’가 없다). IPv4와 IPv6 라우터가 섞인 망을 어떻게 운영하는가. 답은 터널링(tunneling)이다.

터널링: IPv6 데이터그램을 IPv4 데이터그램의 payload로 실어 나른다(“packet within a packet”).

IPv6 터널링 — IPv4 구간을 IPv6 데이터그램이 payload로 통과한다

논리적으로는 IPv6 라우터 B와 E가 직접 연결된 것처럼 보이지만, 물리적으로는 그 사이에 IPv4 라우터 C, D가 있다. B는 A로부터 받은 IPv6 데이터그램(src: A, dest: F)을 통째로 IPv4 데이터그램(src: B, dest: E)의 payload에 넣는다. C와 D는 이를 평범한 IPv4 패킷으로 보고 E까지 전달하고, E가 IPv4 껍질을 벗겨 안의 IPv6 데이터그램을 꺼내 F로 보낸다. 원본 IPv6의 출발지/목적지 주소(A, F)는 터널 내내 보존된다. 터널링은 IPv6 전환뿐 아니라 4G/5G 등 다른 맥락에서도 폭넓게 쓰인다.

IPv6는 1990년대 중반부터 25년 넘게 배포 중이지만 전환은 느리다. 2023년 기준 Google 클라이언트의 약 40%가 IPv6로 접속하는 수준이다. 같은 기간 응용 계층은 WWW·소셜미디어·스트리밍으로 송두리째 바뀐 것과 대조된다. 네트워크 계층을 바꾸는 일이 그만큼 어렵다는 방증이다.

라우터 큐잉과 패킷 스케줄링

마지막으로 라우터 내부에서 패킷이 어떻게 줄을 서고 선택되는지 본다. 이는 지연·손실과 직결된다.

Input Port Queuing과 HOL Blocking

스위칭 패브릭이 입력 포트들의 합산 속도보다 느리면 입력 큐에 패킷이 쌓인다. 여기서 고약한 현상이 HOL(Head-of-the-Line) blocking이다.

HOL blocking — 큐 맨 앞 패킷이 뒤를 막는다

같은 출력 포트를 두 입력이 동시에 노리면 하나만 통과하고 다른 하나는 막힌다(output port contention). 문제는 막힌 패킷 뒤에 줄 선 패킷이다. 그 뒤 패킷의 목적지 출력 포트가 비어 있어도, 앞 패킷이 막혀 있으면 함께 멈춘다. 큐 맨 앞(head-of-line) 패킷이 뒤 전체를 가로막는 것이다.

Output Port Queuing

패브릭에서 출력 링크 전송 속도보다 빨리 패킷이 도착하면 출력 포트 버퍼가 필요하다. 버퍼가 가득 차면 drop policy에 따라 패킷을 버린다(혼잡·버퍼 부족으로 인한 손실). 얼마나 버퍼링해야 하는가. RFC 3439의 경험칙은 평균 버퍼를 “전형적 RTT(약 250ms) × 링크 용량 $C$”로 잡는다. $N$개 flow가 있으면 더 정교하게

\[\text{buffer} = \frac{\text{RTT} \cdot C}{\sqrt{N}}\]

를 권장한다. 다만 버퍼가 지나치게 크면 지연이 늘어 실시간 앱 성능이 나빠지고 TCP 반응이 둔해진다(“bufferbloat”).

패킷 스케줄링

출력 큐에서 다음에 보낼 패킷을 고르는 규칙이 스케줄링이다.

  • FCFS (FIFO): 도착 순서대로 전송. 가장 단순하다.
  • Priority: 트래픽을 클래스로 분류해 큐에 나눠 담고, 버퍼된 패킷이 있는 최고 우선순위 큐부터 전송한다. 같은 클래스 안에서는 FCFS.
  • Round Robin: 클래스 큐를 순환하며 각 클래스에서 한 패킷씩 돌아가며 보낸다.
  • Weighted Fair Queuing (WFQ): round robin의 일반화. 클래스 $i$에 가중치 $w_i$를 주고 매 사이클에서 $\frac{w_i}{\sum_j w_j}$만큼의 서비스를 배분한다. 클래스별 최소 대역폭 보장이 가능하다.

이런 스케줄링·버퍼 관리 메커니즘은 곧 망 중립성(network neutrality)의 기술적 토대가 된다. ISP가 자원을 어떻게 배분하느냐(누구를 우선할 것인가)는 기술 문제이자 사회·경제·법 문제다.

정리

classful 주소의 두 한계 — 균일 서브넷, 클래스 단위 라우팅 — 는 각각 VLSM과 CIDR로 풀렸다. CIDR은 prefix 길이를 자유롭게 하면서 route aggregation으로 라우팅 테이블을 압축했고, 라우터는 longest prefix matching(TCAM)으로 이를 빠르게 조회한다. IP 포워딩은 hop-by-hop이며 어떤 라우터도 전체 경로를 모른다. 주소 고갈에는 NAT가 실용적으로, IPv6가 근본적으로 대응하되 전환에는 터널링이 다리를 놓는다. 그리고 라우터 내부의 큐잉과 스케줄링이 지연·손실, 나아가 망 중립성까지 결정한다.