라우팅의 기본 개념
경로를 정하는 라우팅과 패킷마다 다음 홉으로 내보내는 포워딩을 구분하고, 라우터가 패킷 하나를 넘기며 하는 일을 단계별로 정리합니다. 라우팅 표의 항목과 RIB와 FIB, 최장 접두어 일치를 모델로 확인하고, 정적 경로와 동적 경로, 기본 경로, 경로 출처의 선호도를 살펴봅니다.
앞 장에서 IP 주소가 목적지를 가리킨다는 것을 보았지만, 패킷이 그 목적지까지 어느 이웃을 거쳐 가야 하는지는 다른 문제입니다. 서울의 PC가 미국의 서버에 패킷을 보낼 때, 어느 라우터 하나가 처음부터 끝까지의 길을 정해 주는 것이 아닙니다. 라우터마다 자기 표를 보고 "이번에는 이 이웃에게 넘긴다"는 작은 결정을 내리고, 그 결정이 여러 번 이어져 패킷이 목적지에 닿습니다.
이때 두 가지 일을 나누어 생각해야 합니다. 라우팅(routing)은 경로의 정보를 모으고 그 가운데 쓸 경로를 고르는 일로, 라우터의 제어 평면(control plane)이 합니다. 포워딩(forwarding)은 들어온 패킷마다 고른 경로에 따라 다음 홉으로 내보내는 일로, 데이터 평면(data plane)이 합니다.
라우터가 패킷 하나를 넘기는 과정
라우터(router)는 서로 다른 IP 네트워크를 잇고, 목적지 IP 주소를 보고 패킷을 내보낼 인터페이스와 다음 홉을 정하는 장비입니다. 이더넷으로 들어온 IPv4 패킷 하나를 넘길 때 라우터는 대체로 다음 일을 합니다.
| 단계 | 하는 일 |
|---|---|
| 받기 | 프레임의 목적지 MAC 주소가 자기 것인지 보고, FCS를 검사한 뒤 링크 헤더를 벗긴다 |
| 검사 | IP 헤더의 오류와 TTL을 확인하고, 설정된 필터가 있으면 통과시킬지 정한다 |
| 경로 찾기 | 포워딩 표에서 목적지와 가장 구체적으로 일치하는 경로를 찾아 다음 홉을 정한다 |
| TTL | TTL을 1 줄이고, 0이 되면 버린 뒤 ICMP Time Exceeded를 돌려준다. 체크섬도 고친다 |
| 새 프레임 | 필요하면 ARP로 다음 홉의 MAC 주소를 알아내 새 링크 헤더를 붙인다 |
| 내보내기 | 나가는 인터페이스의 MTU와 대기열, 정책에 따라 내보낸다 |
2장 4편에서 본 것처럼, NAT나 터널이 없다면 IP의 출발지와 목적지는 처음부터 끝까지 그대로이고, 링크 헤더는 링크마다 새로 만들어집니다. 첫 링크에서 프레임의 목적지는 첫 라우터의 MAC 주소이고, 다음 링크에서는 두 번째 라우터의 MAC 주소입니다. 서버의 IP 주소가 다음 홉의 IP 주소로 바뀌는 것이 아니라, 목적지가 같은 패킷을 새 프레임에 담아 보내는 것입니다.
라우팅 표에 든 것
라우터 안에는 여러 출처에서 배운 경로를 모아 두는 RIB(routing information base)와, 그 가운데 실제로 쓸 경로만 골라 패킷을 빨리 넘기기 좋게 정리한 FIB(forwarding information base)가 있습니다. 경로 하나에는 다음 정보가 들어 있습니다.
| 항목 | 뜻 |
|---|---|
| 목적지 프리픽스 | 10.0.0.0/8, 192.168.1.0/24처럼 이 경로가 맡는 주소의 범위 |
| 다음 홉 | 직접 연결된 네트워크가 아니라면, 패킷을 넘길 이웃 라우터의 IP 주소 |
| 나가는 인터페이스 | 패킷이 나갈 물리적이거나 논리적인 인터페이스 |
| 출처 | 직접 연결(connected), 관리자가 넣은 정적 경로(static), OSPF나 BGP 같은 프로토콜 |
| 선호도와 메트릭 | 같은 프리픽스의 경로가 여럿일 때 하나를 고르는 기준 |
Linux의 ip route가 보여 주는 것은 커널이 포워딩에 쓰는 표이며, 라우팅 프로그램이 안에 따로 가진 RIB와는 다릅니다. 장비마다 RIB를 보여 주는 명령과 하드웨어의 FIB를 보여 주는 명령이 따로 있습니다.
가장 긴 프리픽스가 이긴다
포워딩 표에서 경로를 찾는 기본 규칙은 최장 접두어 일치(longest prefix match)입니다. 이 이름의 접두어는 앞에서 본 프리픽스(prefix)를 우리말로 옮긴 말입니다. 목적지 주소와 일치하는 경로가 여럿이면, 더 많은 비트가 일치하는 더 구체적인 경로를 고릅니다. RFC 1812는 IPv4 라우터가 이 규칙으로 경로를 고르도록 정합니다.
FORWARDING LOOKUP · MATCH / MOST SPECIFIC
목적지에 일치하는 후보 중 가장 긴 프리픽스를 고른다
원문 Python 경로 목록에서 세 목적지의 선택 결과를 계산한 표입니다. /24는 /16보다 구체적이고, /0은 더 구체적인 일치 경로가 없을 때 선택됩니다. 실제 관측 경로나 설치 가능한 장비 설정은 아닙니다.
| 목적지 | 일치하는 후보 | 선택 경로 · 다음 홉 |
|---|---|---|
| 172.16.5.100 | /24 · /16 · /0 | 172.16.5.0/24 · 192.168.1.4 |
| 172.16.10.1 | /16 · /0 | 172.16.0.0/16 · 192.168.1.3 |
| 8.8.8.8 | /0 | 0.0.0.0/0 · 192.168.1.1 |
- 172.16.5.100
- 일치하는 후보: /24 · /16 · /0선택 경로 · 다음 홉: 172.16.5.0/24 · 192.168.1.4
- 172.16.10.1
- 일치하는 후보: /16 · /0선택 경로 · 다음 홉: 172.16.0.0/16 · 192.168.1.3
- 8.8.8.8
- 일치하는 후보: /0선택 경로 · 다음 홉: 0.0.0.0/0 · 192.168.1.1
포워딩 조회와 같은 프리픽스의 후보 선택을 구분
목적지와 일치하는 FIB 경로 조회: 최장 프리픽스 우선
같은 프리픽스의 경로 후보 설치: 선호도·프로토콜 메트릭·정책 등을 평가
이 함수는 다음 홉 도달성을 검사하지 않습니다. /24 경로의 eth1 연결 정보가 없어 실제 다음 홉 도달성도 이 입력만으로 검증할 수 없습니다.
다음 코드는 작은 라우팅 표에서 이 규칙으로 경로를 찾습니다.
import ipaddress
routes = [ # (목적지 프리픽스, 다음 홉, 나가는 인터페이스)
("192.168.1.0/24", "직접 연결", "eth0"),
("10.0.0.0/30", "직접 연결", "eth1"),
("172.16.0.0/16", "192.168.1.3", "eth0"),
("172.16.5.0/24", "10.0.0.2", "eth1"),
("0.0.0.0/0", "192.168.1.1", "eth0"),
]
def lookup(dest):
ip = ipaddress.ip_address(dest)
matches = [(ipaddress.ip_network(p), hop, dev) for p, hop, dev in routes if ip in ipaddress.ip_network(p)]
return max(matches, key=lambda m: m[0].prefixlen) # 가장 긴 프리픽스를 고른다
for dest in ("172.16.5.100", "172.16.10.1", "192.168.1.77", "8.8.8.8"):
net, hop, dev = lookup(dest)
print(f"{dest:<13} -> {str(net):<15} 다음 홉 {hop}, {dev}")172.16.5.100 -> 172.16.5.0/24 다음 홉 10.0.0.2, eth1
172.16.10.1 -> 172.16.0.0/16 다음 홉 192.168.1.3, eth0
192.168.1.77 -> 192.168.1.0/24 다음 홉 직접 연결, eth0
8.8.8.8 -> 0.0.0.0/0 다음 홉 192.168.1.1, eth0172.16.5.100은 /16, /24, /0과 모두 일치하지만, 앞의 24비트까지 일치하는 172.16.5.0/24가 가장 구체적이므로 그 경로를 따릅니다. 172.16.10.1은 세 번째 바이트가 10이라 그 /24와 맞지 않아 /16을 따르고, 8.8.8.8은 구체적인 경로가 하나도 맞지 않아 모든 주소와 일치하는 /0, 곧 기본 경로를 따릅니다. 실제 장비는 이렇게 모든 경로를 하나씩 비교하지 않고, 소프트웨어 라우터는 기수 트리(radix tree) 같은 자료구조를, 하드웨어 라우터는 TCAM이라는 특수한 메모리를 써서 한 번에 찾습니다. 같은 길이의 프리픽스가 여럿이면 이 코드는 먼저 나온 것을 고르지만, 실제 라우터는 아래의 선호도와 메트릭으로 고릅니다.
정적 경로와 동적 경로
라우팅 표의 경로는 관리자가 직접 넣을 수도 있고, 라우팅 프로토콜이 이웃 라우터와 정보를 주고받아 만들 수도 있습니다.
| 방식 | 경로를 정하는 방법 | 어울리는 곳 |
|---|---|---|
| 정적 경로 | 관리자가 프리픽스와 다음 홉을 직접 넣는다. 링크가 끊겨도 저절로 바뀌지 않는다 | 작고 잘 바뀌지 않는 네트워크, 기본 경로, 예비 경로 |
| 동적 경로 | OSPF, IS-IS, BGP 같은 프로토콜이 이웃과 경로를 주고받고, 고장이 나면 다른 경로로 바꾼다 | 라우터와 회선이 많은 네트워크 |
동적 경로는 고장에 스스로 대응하지만, 라우터의 CPU와 메모리, 회선의 대역폭을 쓰고, 이웃을 인증하고 받은 경로를 걸러 내는 관리가 필요합니다. 실무에서는 둘을 함께 써서, 동적 경로 위에 특정 목적지의 정적 경로를 더하거나, 동적 경로가 사라졌을 때만 쓰이도록 선호도를 낮게 정한 예비 정적 경로(floating static route)를 두기도 합니다.
기본 경로
기본 경로(default route)는 더 구체적인 경로가 하나도 맞지 않을 때 쓰는 마지막 후보로, IPv4에서는 0.0.0.0/0, IPv6에서는 ::/0입니다. 집의 PC는 인터넷의 수십만 개 경로를 알 필요가 없습니다. 자기 LAN의 경로와 공유기를 가리키는 기본 경로만 있으면, 모르는 목적지는 모두 공유기로 넘기고, 공유기도 통신사의 라우터로 넘기는 식으로 이어지기 때문입니다. 기본 경로도 없고 맞는 경로도 없으면 패킷은 보낼 곳이 없으므로 버려지고, 보낸 쪽에는 ICMP Destination Unreachable이 돌아갑니다.
내 컴퓨터의 라우팅 표 보기
ip route show # 전체 경로
ip route get 8.8.8.8 # 이 목적지로 갈 때 실제로 고르는 출발지 주소, 게이트웨이, 인터페이스
sudo ip route add 10.10.0.0/16 via 192.168.1.2 dev eth0 # 정적 경로 더하기(실습용)
sudo ip route del 10.10.0.0/16 # 지우기route print (Windows: 라우팅 표)
netstat -rn (Windows와 macOS: 라우팅 표)ip route get은 표를 직접 읽지 않아도 커널이 그 목적지에 어떤 경로를 고르는지 알려 주므로, 경로가 예상과 다른지 확인할 때 가장 먼저 쓰기 좋습니다. Windows의 라우팅 표에서 게이트웨이가 On-link인 경로는, 그 네트워크가 인터페이스에 직접 연결되어 게이트웨이를 거치지 않는다는 뜻입니다.
PC도 패킷을 보낼 때마다 이 표를 봅니다. 고른 경로가 직접 연결된 네트워크라면 ARP로 목적지의 MAC 주소를 알아내 바로 보내고, 게이트웨이를 거치는 경로라면 게이트웨이의 MAC 주소로 보냅니다. VPN을 켜면 회사 네트워크의 더 구체적인 경로가 표에 더해져, 그 목적지만 VPN으로 가게 되는 것도 최장 접두어 일치 덕분입니다.
더 깊이: Linux에는 라우팅 표가 여러 개 있다
ip route가 보여 주는 표는 Linux가 가진 여러 라우팅 표 가운데 main 하나입니다. Linux는 패킷마다 어느 표를 찾아볼지를 정책 라우팅 데이터베이스(routing policy database, RPDB)의 규칙으로 먼저 정합니다. ip-rule(8)에 따르면 시작할 때 규칙이 셋 있는데, 우선순위 0은 자기 주소와 브로드캐스트 주소의 경로를 담은 local 표를, 32766은 보통의 경로를 담은 main 표를, 32767은 비어 있는 default 표를 찾게 합니다. 숫자가 작은 규칙부터 차례로 보고 경로를 찾으면 거기서 멈추므로, 자기 주소로 가는 패킷은 main을 보기 전에 local 표에서 처리됩니다.
규칙은 목적지만이 아니라 출발지 주소, 들어온 인터페이스, 방화벽이 패킷에 붙인 표시(fwmark), 프로세스의 사용자 ID 같은 조건으로도 고를 수 있습니다. 그래서 회선이 둘인 서버라면 출발지 주소마다 다른 표를 쓰게 해, 응답이 그 주소에 맞는 회선으로 나가게 할 수 있습니다. 이런 규칙이 있는 컴퓨터에서 ip route의 출력만 보고 경로를 짐작하면 틀리기 쉬우므로, 실제로 고르는 경로는 규칙까지 거쳐 커널이 찾아 주는 ip route get으로 확인합니다.
경로 출처의 선호도
같은 프리픽스의 경로를 여러 출처에서 배웠다면 하나를 골라야 합니다. Cisco 장비는 이를 관리 거리(administrative distance, AD)라는 값으로 정하며, 값이 낮을수록 더 믿습니다.
| 출처 | Cisco의 기본 AD |
|---|---|
| 직접 연결 | 0 |
| 정적 경로 | 1 |
| eBGP(다른 AS에서 배운 BGP) | 20 |
| OSPF | 110 |
| RIP | 120 |
| iBGP(같은 AS에서 배운 BGP) | 200 |
이 값은 인터넷 표준이 정한 것이 아니라 제조사마다 다르게 정한 선호도이며, 다른 제조사는 다른 이름과 값을 씁니다. 순서도 중요합니다. 라우터는 먼저 목적지와 가장 길게 일치하는 프리픽스를 고르고, AD와 메트릭은 길이가 같은 프리픽스의 후보들 가운데에서만 비교합니다. 그래서 AD가 낮은 정적 기본 경로가 있어도, OSPF로 배운 더 구체적인 경로가 있으면 그 목적지는 OSPF의 경로를 따릅니다.
정리
- 라우팅은 경로를 모으고 고르는 제어 평면의 일이고, 포워딩은 패킷마다 다음 홉으로 내보내는 데이터 평면의 일입니다.
- 라우터는 받은 프레임의 링크 헤더를 벗기고, 경로를 찾고, TTL을 줄이고, 다음 홉의 MAC 주소로 새 프레임을 만들어 내보냅니다.
- 라우팅 표의 경로는 프리픽스, 다음 홉, 인터페이스, 출처, 선호도로 이루어지며, 포워딩은 최장 접두어 일치로 경로를 고릅니다.
- 정적 경로는 관리자가 넣고 동적 경로는 프로토콜이 주고받으며, 기본 경로는 맞는 경로가 없을 때의 마지막 후보입니다.
- AD와 메트릭은 길이가 같은 프리픽스의 후보 사이에서만 비교하며, 더 구체적인 경로가 언제나 먼저입니다.
연습 문제
1. /25 경로를 더하면
본문의 표에 172.16.5.128/25 경로를 더했고, 그 다음 홉은 따로 확인해 닿을 수 있습니다. 목적지 172.16.5.170은 어느 경로를 따르나요? 그 뒤 이 /25 경로만 지우면 어떻게 되나요?
해설 보기
172.16.5.128/25는 172.16.5.128부터 172.16.5.255까지를 맡으므로 .170과 일치합니다. /24, /16, /0도 일치하지만 가장 긴 /25를 따릅니다. /25를 지우면 남은 후보 가운데 가장 긴 172.16.5.0/24를 따라 10.0.0.2로, eth1을 통해 나갑니다. 길이가 다른 프리픽스를 비교할 때는 기본 경로의 메트릭이 아무리 낮아도 상관이 없습니다.
2. 정적 기본 경로와 OSPF 경로
라우터에 정적 기본 경로 0.0.0.0/0(AD 1)이 있고, OSPF로 10.20.0.0/16(AD 110)을 배웠습니다. 목적지 10.20.3.4로 가는 패킷은 어느 경로를 따르나요? "AD가 낮은 정적 경로가 언제나 이긴다"는 말은 맞나요?
해설 보기
10.20.3.4는 /0과 /16 모두와 일치하는데, 최장 접두어 일치에 따라 더 구체적인 OSPF의 10.20.0.0/16을 따릅니다. AD는 같은 프리픽스, 예를 들어 10.20.0.0/16을 정적 경로와 OSPF가 함께 알려 줄 때 둘 가운데 하나를 고르는 기준이므로, 프리픽스의 길이가 다르면 비교하지 않습니다. 그래서 "AD가 낮은 경로가 언제나 이긴다"는 말은 틀렸고, 정확히는 "같은 프리픽스 안에서는 AD가 낮은 경로가 이긴다"입니다.
3. VPN을 켰더니
재택 근무자가 VPN을 켜자 회사의 내부 사이트(10.0.0.0/8)는 잘 열리는데, 일반 인터넷 사이트도 회사를 거쳐 가서 느려졌습니다. ip route를 보니 VPN 인터페이스로 가는 0.0.0.0/1과 128.0.0.0/1 경로가 더해져 있습니다. 왜 인터넷 트래픽까지 VPN으로 가며, 회사의 사이트만 VPN으로 보내려면 어떻게 해야 하나요?
해설 보기
0.0.0.0/1과 128.0.0.0/1은 둘이 합쳐 모든 IPv4 주소를 덮으면서, 둘 다 원래의 기본 경로 0.0.0.0/0보다 프리픽스가 깁니다. 그래서 최장 접두어 일치에 따라 모든 목적지가 원래의 기본 경로 대신 VPN의 경로를 따르며, 기본 경로를 지우지 않고도 모든 트래픽을 VPN으로 보내는 흔한 방법입니다. 회사의 사이트만 VPN으로 보내려면 이 두 경로 대신 10.0.0.0/8 같은 회사 네트워크의 경로만 VPN 인터페이스로 넣는 분할 터널링(split tunneling)을 쓰면 됩니다. 다만 회사의 보안 정책이 모든 트래픽을 회사를 거쳐 검사하도록 요구할 수도 있으므로, 설정을 바꾸기 전에 정책을 확인해야 합니다.
다음 글 동적 라우팅 프로토콜에서는 라우터들이 서로 경로를 주고받는 RIP, OSPF, BGP의 동작 원리를 살펴봅니다.