OSPF
고친 사람 github-actions[bot]
OSPF 는 한 조직의 망 안에서 라우터들이 망 전체의 지도를 똑같이 나눠 갖게 합니다. 라우터는 그 지도를 보고 목적지마다 가장 싼 길을 스스로 계산합니다. 회선 하나가 끊기면 그 소식이 곧 모든 라우터에 퍼집니다. 라우터들은 고친 지도로 다시 계산해 다른 길로 갈아탑니다.
쉽고 빠른 이해
OSPF 는 회사나 데이터센터 망 안의 라우터들이 "나는 누구와 얼마짜리 회선으로 이어져 있다"를 서로 알리게 하는 규칙입니다. 이 소식을 모두 모으면 라우터마다 망 전체의 지도가 생깁니다. 회사와 회사 사이의 길은 OSPF 가 아니라 다른 프로토콜이 맡습니다.
이게 없으면 사람이 라우터마다 길을 손으로 적어야 합니다. 회선이 끊길 때마다 여러 장비를 고쳐야 합니다. 고치는 동안 데이터는 끊긴 회선 쪽으로 가서 버려집니다.
어떻게 도나:
- 옆 라우터와 주기적으로 인사를 나눠 살아 있는지 확인합니다
- 자기 회선 목록을 망 안의 모든 라우터에게 퍼뜨립니다
- 모인 목록으로 망 전체 지도를 그립니다
- 자기를 출발점으로 목적지마다 가장 싼 길을 계산합니다
대가도 있습니다. 라우터마다 지도 전체를 들고 계산하느라 메모리와 계산이 더 듭니다. 망이 크면 여러 영역으로 나눠 설계해야 합니다. 조용히 멈춘 이웃은 인사가 한동안 끊긴 뒤에야 알아챕니다.
상세
OSPF(Open Shortest Path First, 개방형 최단 경로 우선)는 한 조직의 망 안에서 라우터끼리 길 정보를 주고받는 라우팅 프로토콜입니다. 라우팅 프로토콜은 라우터들이 목적지마다 넘길 곳을 사람 손 없이 알아내게 하는 대화 규칙입니다.
라우터는 망과 망 사이에서 패킷을 다음 장비로 넘겨주는 장비입니다. 패킷은 망에서 데이터가 오가는 한 덩어리입니다. 라우터는 패킷마다 목적지를 보고 어느 쪽으로 넘길지 정합니다.
「Open」은 규칙이 공개돼 있어 어느 회사든 구현할 수 있다는 뜻입니다. 「Shortest Path First」는 라우터가 길을 고를 때 쓰는 계산, 곧 가장 짧은 길부터 확정해 나가는 계산을 가리킵니다.
이 절은 라우터 넷이 이어진 작은 망 하나를 들고 갑니다. 먼저 OSPF 가 무엇을 알리고 그것으로 어떻게 길을 고르는지 봅니다. 이어서 이웃을 찾고 지도를 맞추는 순서, 망이 커질 때 쓰는 장치 둘, 이 설계의 대가를 차례로 봅니다.
망 안쪽을 맡는 프로토콜
인터넷은 통신사, 클라우드 회사, 대학, 기업이 저마다 운영하는 망을 이어 붙인 것입니다. 한 조직이 한 방침으로 운영하는 망 덩어리를 자율 시스템(AS, Autonomous System)이라고 합니다.
OSPF 는 자율 시스템 하나의 안쪽을 맡습니다. 안쪽에서는 한 조직이 모든 라우터를 쥐고 있습니다. 그래서 회사 사이의 계약이나 방침을 따질 필요 없이 가장 싼 길을 고르면 됩니다. OSPF 는 이 목표 하나에 맞춰 만들어졌습니다.
안쪽을 맡는 프로토콜을 묶어 IGP(Interior Gateway Protocol, 내부 게이트웨이 프로토콜)라고 부릅니다. OSPF 는 그 가운데 하나입니다.
자율 시스템과 자율 시스템 사이의 길은 OSPF 가 맡지 않습니다. 이 일은 BGP(Border Gateway Protocol, 경계 게이트웨이 프로토콜)의 몫입니다. BGP 는 가장 싼 길보다 조직 사이의 계약과 방침을 따져 길을 고릅니다.
회선마다 매기는 비용
OSPF 는 거치는 라우터 수로 길을 재지 않습니다. 회선마다 비용이라는 숫자를 매깁니다. 그리고 길 위 회선 비용의 합으로 잽니다. 합이 가장 작은 길이 가장 싼 길입니다.
비용은 운영자가 회선마다 정합니다. 따로 정하지 않으면 장비가 회선 속도에서 계산한 값을 흔히 씁니다. 속도가 높은 회선일수록 비용이 작게 나옵니다. 손대지 않아도 속도가 높은 회선 쪽 길을 고르게 됩니다.
아래 그림이 이 절 끝까지 들고 갈 망입니다. 라우터 넷을 A · B · C · D 로 부릅니다. D 뒤에는 사무실 망이 붙어 있습니다.
선 위 숫자가 그 회선의 비용입니다. A 와 B 사이 회선만 속도가 낮아서 비용이 10 입니다. 나머지 회선은 비용이 1 입니다.
flowchart TD
A["A"] ---|"비용 10"| B["B"]
A ---|"비용 1"| C["C"]
C ---|"비용 1"| D["D"]
B ---|"비용 1"| D
D --- N["사무실 망"]
망 전체 지도를 나눠 갖는 방식
OSPF 라우터는 이웃에게 "목적지까지 몇 걸음"을 알리지 않습니다. 대신 자기에게 붙은 회선의 목록을 알립니다. 그림의 A 라면 "나는 B 와 비용 10 짜리 회선으로, C 와 비용 1 짜리 회선으로 이어져 있다"를 알립니다.
이 소식이 LSA(Link State Advertisement, 링크 상태 알림)입니다. 링크는 라우터에 붙은 회선을 가리킵니다. 링크 상태는 그 회선이 누구와 이어져 있고 비용이 얼마인지를 가리킵니다.
LSA 에는 누가 만들었는지가 붙어야 합니다. 그래서 라우터마다 망 안에서 겹치지 않는 이름을 하나씩 둡니다. 이 이름이 라우터 ID입니다.
라우터 ID 는 1.1.1.1 처럼 숫자 넷을 점으로 이어 적습니다. 장비의 주소인 IP 주소(Internet Protocol address, 인터넷 프로토콜 주소)와 적는 꼴이 같습니다. 그래도 주소로 쓰지 않고 라우터를 가리키는 이름으로만 씁니다.
LSA 한 통에는 만든 라우터, 몇 번째로 고쳐 낸 것인지를 뜻하는 순번, 회선 목록이 실립니다. 아래는 A 가 만든 LSA 를 줄마다 풀어 적은 것입니다.
A 가 만든 LSA
만든 라우터 1.1.1.1 // A 의 ID
순번 3 // 클수록 새것
링크 B · 10 // B 와 비용 10
링크 C · 1 // C 와 비용 1
LSA 는 이웃에게서 멈추지 않고 망 안의 모든 라우터에게 퍼집니다. 각 라우터는 받은 LSA 를 모두 모아 둡니다. 이 모음이 링크 상태 데이터베이스(LSDB, Link State Database)입니다. 모든 라우터의 LSDB 가 같아지면 모두가 같은 지도를 들고 있는 셈입니다.
지도를 나눠 갖고 각자 계산하는 이 방식이 링크 상태 라우팅입니다. 라우터마다 망 전체를 내려다보고 길을 스스로 고릅니다.
반대편에는 거리 벡터 라우팅이 있습니다. 이 방식의 라우터는 지도 없이 이웃이 알려 준 목적지별 거리만 믿고 계산합니다. RIP(Routing Information Protocol, 라우팅 정보 프로토콜)가 그쪽의 대표입니다.
다익스트라 알고리즘으로 길을 고르는 계산
지도가 모이면 라우터는 다익스트라 알고리즘을 돌립니다. 다익스트라 알고리즘은 한 지점에서 나머지 모든 지점까지 비용 합이 가장 작은 길을 찾는 계산 방법입니다. 가까운 곳부터 하나씩 확정해 나갑니다.
라우터는 자기를 출발점으로 놓고 이 계산을 돌립니다. 위 망에서 A 가 계산한 결과는 아래와 같습니다. 마지막 칸의 다음 홉은 그 길로 가려면 A 가 패킷을 먼저 넘겨줄 바로 옆 라우터입니다.
| 목적지 | 가장 싼 길 | 비용 합 | 다음 홉 |
|---|---|---|---|
| C | A → C | 1 | C |
| D · 사무실 망 | A → C → D | 2 | C |
| B | A → C → D → B | 3 | C |
B 와 바로 이어진 회선이 있는데도 A 는 B 로 가는 패킷을 C 쪽으로 보냅니다. 직접 회선은 비용이 10 입니다. 돌아가는 길은 회선 셋을 거쳐도 합이 3 입니다. 거치는 라우터 수가 아니라 비용 합이 길을 정합니다.
계산 결과에서 라우터가 쓰는 것은 마지막 칸입니다. 라우터는 "이 목적지는 이 다음 홉으로"를 경로표에 적습니다. 경로표는 패킷이 들어올 때마다 라우터가 들여다보는 표입니다.
OSPF 가 하는 일은 경로표를 채우는 데까지입니다. 길을 알아내 경로표를 채우는 일을 제어 평면이라고 부릅니다.
패킷을 넘기는 일은 따로 있습니다. 들어온 패킷마다 경로표를 찾아 다음 홉 쪽으로 내보내는 일입니다. 이 일은 데이터 평면의 몫입니다.
Hello 로 이웃을 찾고 살피는 방법
지도를 나누려면 먼저 옆에 누가 있는지 알아야 합니다. OSPF 라우터는 회선마다 Hello 라는 짧은 패킷을 주기적으로 보냅니다.
Hello 는 멀티캐스트 주소 224.0.0.5 로 보냅니다. 멀티캐스트는 한 번 보내서 그 주소를 듣겠다고 한 장비들에게만 전하는 방식입니다. OSPF 라우터는 모두 이 주소를 듣습니다. 그래서 이웃의 주소를 몰라도 Hello 가 닿습니다.
Hello 에는 보낸 라우터의 ID 와, 그 회선에서 최근에 Hello 를 들은 이웃의 ID 목록이 실립니다. 상대의 Hello 에 자기 ID 가 적혀 있으면 두 라우터가 서로를 본 것입니다. 이 상태가 2-Way 입니다.
Hello 는 살아 있다는 신호이기도 합니다. 한 건물 안에서 스위치로 이어진 근거리 망에서는 흔히 10초마다 보냅니다. 그 네 배인 40초 동안 Hello 가 하나도 안 오면 이웃이 죽었다고 봅니다. 이 기다리는 시간이 데드 인터벌(dead interval)입니다.
Hello 간격과 데드 인터벌은 한 회선에 붙은 라우터들이 같은 값을 써야 합니다. 값이 다르면 서로의 Hello 를 버려서 이웃이 되지 않습니다. 설정 한 줄이 어긋나 이웃이 안 맺히는 흔한 원인이 이것입니다.
TCP 없이 IP 에 바로 실리는 패킷
OSPF 패킷은 TCP(Transmission Control Protocol, 전송 제어 프로토콜)나 UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜)를 거치지 않습니다. IP 패킷에 바로 실립니다. IP 패킷 머리에는 안에 무엇이 실렸는지 적는 번호 칸이 있습니다. OSPF 의 번호는 89 입니다.
OSPF 에는 포트 번호가 없습니다. 방화벽에서 OSPF 를 열거나 막을 때도 포트가 아니라 이 번호로 가립니다. TCP 179번 포트 위에서 도는 BGP 와 다른 점입니다.
TCP 를 안 쓰니 빠진 패킷을 다시 보내 주는 장치도 없습니다. OSPF 는 확인 응답과 재전송을 스스로 합니다. LSA 를 받은 라우터는 받았다는 답을 보냅니다. 답이 안 오면 보낸 쪽이 같은 LSA 를 다시 보냅니다.
이웃과 지도를 맞추는 순서
2-Way 가 된 두 라우터는 서로의 LSDB 를 맞춥니다. 처음부터 LSA 를 전부 보내지 않습니다. 목차를 먼저 주고받은 뒤 없는 것만 달라고 합니다. 이미 가진 LSA 를 다시 받으면 회선만 낭비하기 때문입니다.
이 과정에 쓰는 패킷은 Hello 를 포함해 다섯 가지입니다.
| 패킷 | 하는 일 |
|---|---|
| Hello | 이웃을 찾고 살아 있는지 확인한다 |
| DBD(Database Description, 데이터베이스 설명) | 가진 LSA 의 목차를 보낸다 |
| LSR(Link State Request, 링크 상태 요청) | 목차에서 없는 LSA 를 달라고 한다 |
| LSU(Link State Update, 링크 상태 갱신) | LSA 내용을 싣는다 |
| LSAck(Link State Acknowledgment, 링크 상태 확인) | LSU 를 받았다고 답한다 |
다섯이 어떤 순서로 오가는지는 A 와 C 가 처음 만나는 장면으로 보면 잡힙니다. 끝은 두 LSDB 가 같아진 상태입니다. 이렇게 된 이웃 관계가 Full 입니다.
sequenceDiagram
participant A
participant C
A->>C: Hello · 들은 이웃 없음
C->>A: Hello · 들은 이웃 A
A->>C: Hello · 들은 이웃 C
Note over A,C: 서로를 봤다 · 2-Way
A->>C: DBD · 내 LSA 목차
C->>A: DBD · 내 LSA 목차
A->>C: LSR · 없는 LSA 를 달라
C->>A: LSU · 요청한 LSA
A->>C: LSAck · 받았다
Note over A,C: LSDB 가 같아졌다 · Full
목차를 맞춘 뒤에는 양쪽 모두 자기에게 없는 LSA 를 요청합니다. 그림은 A 쪽 요청만 그렸습니다.
바뀐 소식을 퍼뜨리는 플러딩
회선 하나가 끊기면 그 회선에 붙은 라우터가 LSA 를 새로 만듭니다. 끊긴 회선을 뺀 목록에 순번을 하나 올려 싣습니다. 그리고 모든 이웃에게 LSU 로 보냅니다.
받은 라우터는 자기 LSDB 에 있는 같은 라우터의 LSA 와 순번을 견줍니다. 새것이면 LSDB 를 고칩니다. 그다음 받아 온 쪽을 뺀 나머지 이웃에게 다시 보냅니다. 같거나 옛것이면 버립니다.
이렇게 이웃에서 이웃으로 번져 망 전체에 닿는 방식을 플러딩(flooding)이라고 부릅니다. 순번 덕분에 같은 소식이 여러 길로 돌아와도 한 번만 반영됩니다. 고리처럼 이어진 망에서도 소식이 끝없이 돌지 않습니다.
LSDB 가 바뀐 라우터는 다익스트라 알고리즘을 다시 돌려 경로표를 고칩니다. 모든 라우터가 새 지도로 계산을 마쳐 서로 어긋남이 없어진 상태를 수렴이라고 합니다. 소식은 이웃의 계산을 기다리지 않고 곧장 번집니다. 거리 벡터 방식보다 수렴이 빠른 까닭입니다.
바뀐 것이 없어도 LSA 는 영원히 남지 않습니다. 라우터는 자기 LSA 를 30분마다 새 순번으로 다시 퍼뜨립니다. LSA 마다 나이가 붙어 있습니다. 나이가 한 시간에 이른 LSA 는 계산에서 빼고 지웁니다. 사라진 라우터의 LSA 가 지도에 영영 남는 일을 이 장치가 막습니다.
한 망에 라우터가 많을 때의 지정 라우터
스위치 하나에 라우터 여럿이 물린 망을 생각해 봅시다. 이더넷 스위치로 이어진 근거리 망이 그런 예입니다. 이런 망에서는 모든 라우터가 서로 바로 옆에 있습니다.
모두가 모두와 지도를 맞추면 이웃 관계가 너무 많아집니다. 라우터가 열 대면 쌍이 마흔다섯 개입니다. 회선에 변화가 하나 생겨도 같은 LSA 가 여러 쌍 사이를 오갑니다.
이런 망에서는 라우터 하나를 대표로 뽑습니다. 이 대표가 지정 라우터(DR, Designated Router)입니다. 나머지 라우터는 지정 라우터와만 지도를 맞춥니다. 지정 라우터는 받은 소식을 모두에게 전합니다.
지정 라우터가 죽을 때를 대비해 예비도 하나 뽑습니다. 이 예비가 BDR(Backup Designated Router, 예비 지정 라우터)입니다. 라우터 열 대라면 지도를 맞추는 관계가 마흔다섯에서 열일곱으로 줍니다. 지정 라우터와 맺는 아홉에 예비와 맺는 여덟을 더한 수입니다.
아래 그림은 스위치 하나에 물린 라우터 다섯 대로 줄여 그렸습니다. 앞의 네 라우터 망과는 다른 망입니다. 선은 회선이 아니라 지도를 맞추는 관계입니다. C · D · E 는 서로 2-Way 에서 멈추고 지도를 맞추지 않습니다.
flowchart TD
DR["A · 지정 라우터"]
BDR["B · 예비 지정 라우터"]
DR --- BDR
DR --- C["C"]
DR --- D["D"]
DR --- E["E"]
BDR --- C
BDR --- D
BDR --- E
누가 대표가 될지는 Hello 에 실린 우선순위로 정합니다. 우선순위가 같으면 라우터 ID 가 큰 쪽이 됩니다. 지정 라우터와 예비 지정 라우터는 멀티캐스트 주소 224.0.0.6 도 듣습니다. 나머지 라우터는 바뀐 소식을 대표에게 보낼 때 이 주소를 씁니다.
영역으로 망을 나누는 까닭
망이 커지면 링크 상태 방식의 약점이 드러납니다. 라우터마다 망 전체의 LSDB 를 들고 있어야 합니다. 회선 하나가 흔들릴 때마다 모든 라우터가 계산을 다시 돌립니다.
OSPF 는 망을 여러 영역(area)으로 나눠 이 부담을 줄입니다. 영역은 LSA 가 퍼지는 범위를 자르는 울타리입니다. 회선 목록이 담긴 자세한 LSA 는 제 영역 안에서만 퍼집니다.
영역 가운데 하나는 중심이 됩니다. 번호가 0 인 백본 영역입니다. 다른 영역은 모두 백본 영역에 이어져야 합니다. 영역과 영역 사이의 소식은 백본 영역을 거쳐 오갑니다.
두 영역에 걸쳐 놓인 라우터를 영역 경계 라우터(ABR, Area Border Router)라고 부릅니다. 영역 경계 라우터는 한 영역의 자세한 지도를 다른 영역에 넘기지 않습니다. "이 주소 묶음은 나를 거쳐 비용 얼마에 갈 수 있다"로 줄여서 넘깁니다.
flowchart TD
subgraph A0["영역 0 · 백본 영역"]
C1["라우터"] --- C2["라우터"]
end
B1["영역 경계 라우터"]
B2["영역 경계 라우터"]
subgraph A1["영역 1"]
X1["라우터"] --- X2["라우터"]
end
subgraph A2["영역 2"]
Y1["라우터"] --- Y2["라우터"]
end
C1 --- B1 --- X1
C2 --- B2 --- Y1
그 결과 영역 1 의 라우터는 영역 2 안쪽 회선이 어떻게 이어졌는지 모릅니다. 영역 2 에서 회선이 흔들려도 영역 1 의 라우터는 지도 전체를 다시 계산하지 않습니다. 지도가 작아집니다. 다시 돌리는 계산도 줄어듭니다. 대가로 다른 영역으로 가는 길은 줄여 받은 비용만 보고 고릅니다.
링크 상태 방식이 치르는 대가
링크 상태 방식은 라우터에게 일을 더 시킵니다. 라우터마다 LSDB 전체를 들고 있어야 합니다. 망이 바뀔 때마다 계산도 다시 돌립니다. RIP 같은 거리 벡터 방식보다 메모리와 계산이 더 듭니다.
설계할 일도 늘어납니다. 영역을 어떻게 나눌지, 회선 비용을 얼마로 둘지를 운영자가 정해야 합니다. 비용을 잘못 매기면 속도가 낮은 회선으로 트래픽이 몰립니다.
이웃이 조용히 멈추면 알아채는 데 시간이 걸립니다. 회선이 끊기면 라우터가 곧바로 압니다. 그런데 회선 신호가 살아 있는 채로 상대 라우터만 멈췄다면 데드 인터벌이 지날 때까지 기다립니다. 흔히 쓰는 값이면 40초입니다.
이 공백을 줄이려고 BFD(Bidirectional Forwarding Detection, 양방향 전달 감지)를 곁들이기도 합니다. BFD 는 Hello 보다 훨씬 짧은 간격으로 상대가 살아 있는지 묻는 가벼운 프로토콜입니다.
OSPF 의 두 판과 같은 방식을 쓰는 IS-IS
IPv4(Internet Protocol version 4, 인터넷 프로토콜 4판) 망에서 쓰는 것은 OSPF 둘째 판인 OSPFv2 입니다. IPv6(Internet Protocol version 6, 인터넷 프로토콜 6판) 망에는 이를 고친 셋째 판 OSPFv3 를 씁니다. 지도를 나눠 갖고 다익스트라 알고리즘으로 계산하는 뼈대는 두 판이 같습니다.
같은 링크 상태 방식을 쓰는 프로토콜로 IS-IS(Intermediate System to Intermediate System)도 있습니다. 이름의 중간 시스템(Intermediate System)은 라우터를 가리킵니다. 한 자율 시스템 안쪽을 맡는다는 점도 OSPF 와 같습니다.
백엔드 개발자가 OSPF 를 만나는 곳
백엔드 개발자가 OSPF 설정을 만질 일은 드뭅니다. 그래도 서버가 놓인 망이 장애를 겪을 때 이 이름이 나옵니다.
첫째는 자체 데이터센터나 사내망입니다. 층마다, 랙마다 놓인 라우터들이 OSPF 로 길을 맞추는 구성이 흔합니다. 장애 보고서에 "OSPF 이웃이 끊겼다"가 나오면 라우터 둘이 서로의 Hello 를 못 듣게 됐다는 뜻입니다.
둘째는 장애 직후의 짧은 끊김입니다. 회선이 끊기면 수렴을 마칠 때까지 일부 패킷이 버려집니다. 라우터가 조용히 멈췄다면 데드 인터벌만큼 기다린 뒤에야 수렴이 시작됩니다. 요청 일부가 수십 초 동안 실패했다가 저절로 낫는 일이 이렇게 생길 수 있습니다.
관련 항목
OSPF 라우터가 주고받는 정보
LSA · 링크 상태 데이터베이스 · 라우터 ID · Hello 패킷 · 플러딩 · LSA 순번
OSPF 이웃 관계를 이루는 구성 요소
OSPF 이웃 · 인접 관계 · 지정 라우터 · 데드 인터벌 · OSPF 이웃 상태 · BFD
OSPF 가 망을 나누는 단위
OSPF 영역 · 백본 영역 · 영역 경계 라우터 · 스텁 영역 · 경로 요약 · ASBR
OSPF 가 길을 고르는 계산
다익스트라 알고리즘 · 최단 경로 · 링크 비용 · 메트릭 · 등비용 다중 경로
OSPF 가 속하는 라우팅 방식의 분류
링크 상태 라우팅 · 거리 벡터 라우팅 · 경로 벡터 라우팅 · 동적 라우팅 · 정적 라우팅
OSPF 와 같은 역할을 두고 겨루는 라우팅 프로토콜
OSPF 와 망의 안팎을 나눠 맡는 프로토콜과 단위
BGP · EGP · IGP · 자율 시스템
OSPF 패킷이 얹히는 네트워크 계층과 주소
IP · IPv4 · IPv6 · IP 주소 · 멀티캐스트 · 인터넷 계층
OSPF 패킷이 거치지 않는 전송 계층 프로토콜
TCP · UDP
OSPF 가 계산한 길을 담는 라우터 안의 표
경로표 · 다음 홉 · 포워딩 테이블 · RIB · 데이터 평면
OSPF 에서 나는 장애
OSPF 를 구현한 라우팅 소프트웨어
FRRouting · BIRD · Quagga
OSPF 를 규정하는 표준 문서
RFC 2328 · RFC 5340 · IETF
OSPF 가 속하는 상위 분류
다른 이름: Open Shortest Path First · 개방형 최단 경로 우선 · OSPFv2 · OSPFv3