網路與 IP

CIDR 技術:路由彙總與超網怎麼算

CIDR 技術用在路由上,就是把多個連續的網段合併成一條字首更短的路由,減少路由條目、隔離網路變化。演算法的核心是把網段寫成二進位制,取共同的字首位。能否精確彙總,取決於合起來的位址數是不是 2 的冪、起點是否對齊、中間有沒有缺口。

作者 頂聯產品團隊發布於 7 分鐘閱讀

CIDR 技術在路由層面的用途,是把多個連續的網段合併成一條字首更短的路由,這個動作叫路由彙總,也叫路由聚合;彙總出來的那個大塊,在跨過 A、B、C 類邊界時被稱為超網。例如 192.168.32.0/24 到 192.168.39.0/24 這 8 個網段,可以彙總成一條 192.168.32.0/21。計算方法是把網段寫成二進位制,取它們從左往右完全相同的那幾位,相同位數就是彙總後的字首長度。彙總能否“精確”,也就是不多吸進不屬於你的位址,取決於三個條件:合起來的位址數是 2 的冪、起點對齊到彙總塊的大小、中間沒有缺口。下面給出演算法、例題、失敗原因和裝置上的配置方法。

路由彙總、超網、CIDR 聚合是什麼關係

這三個詞經常混用,說的是同一類操作,只是側重點不同:

說法 英文 側重點 例子
路由彙總 Route Summarization 在路由協議或路由表裡,用一條短字首代替多條長字首 OSPF 區域邊界把 32 條 /24 彙總成一條 /19
路由聚合、CIDR 聚合 Route Aggregation 與彙總同義,BGP 裡的叫法,命令就叫 aggregate 運營商把客戶的小塊聚合成自己的大字首對外宣告
超網 Supernetting 彙總後的字首比有類掩碼還短,跨過了 A、B、C 類邊界 4 個 C 類 192.168.32.0/24 至 192.168.35.0/24 合成 /22

區別只在超網:它強調“比有類邊界更短”。把 10.1.0.0/24 到 10.1.255.0/24 彙總成 10.1.0.0/16 是路由彙總,但 /16 仍比 A 類的 /8 長,嚴格說不叫超網;把 4 個 C 類合成 /22 才是超網。在 CIDR 普及之前,路由器按位址類別處理路由,比有類掩碼還短的字首無法表達,CIDR 允許任意字首長度,超網才成為可能。今天的裝置都按無類方式工作,這個區分主要出現在教材和考試裡,工作中說“彙總”即可。

彙總帶來的好處很具體:上游裝置的路由表變小;內部某個網段增刪或閃斷,只要彙總路由還在,上游感知不到,路由協議不會因此在全網重新計算;ACL、防火牆策略也可以按彙總塊寫一條規則。

彙總演算法:四步求出彙總路由

以 192.168.32.0/24 到 192.168.39.0/24 共 8 個網段為例:

  1. 找出變化的那一節。8 個網段的前兩節都是 192.168,第三節從 32 變到 39,第四節都是 0,只需要看第三節。
  2. 把這一節寫成二進位制。只寫最小值和最大值就夠了,中間的值一定夾在兩者之間:
32 = 0010 0000
39 = 0010 0111
     ^^^^ ^         前 5 位相同,後 3 位不同
  1. 數相同的位數,加上前面固定的節。前兩節固定 16 位,第三節相同 5 位,彙總字首長度是 16 + 5 = 21。
  2. 把不同的位清零,得到起始位址。第三節保留前 5 位 00100,後 3 位清零,還是 32,彙總路由為 192.168.32.0/21,掩碼 255.255.248.0。

最後做一次核對:/21 包含 2 的 11 次方,即 2,048 個位址,也就是 8 個 /24,正好是第三節 32 到 39,和要彙總的網段一一對應,這是一個精確彙總。

如果網段大小相同,還有一個更快的判斷方法:數量 N 是 2 的冪,並且起始的那一節能被 N 整除,就能精確彙總,字首長度減少 log₂N 位。上例 N = 8,32 ÷ 8 = 4 整除,/24 減 3 位得 /21。兩個條件任一不滿足,就只能多吸進位址或拆成多條,後面的例題會遇到。

四道例題:從整齊到不整齊

例題一:字首長度不同的網段能彙總嗎? 一個機房有 10.40.8.0/23、10.40.10.0/24、10.40.11.0/25、10.40.11.128/25 四個網段。長度不同不影響演算法,把最小起點和最大終點拿出來比:最小是 10.40.8.0,最大終點是 10.40.11.255,第三節 8 = 0000 1000,11 = 0000 1011,前 6 位相同,彙總為 10.40.8.0/22。再核對位址數:512 + 256 + 128 + 128 = 1,024,與 /22 的大小相等,精確彙總。

例題二:三個網段怎麼彙總? 172.16.4.0/24、172.16.5.0/24、172.16.6.0/24。第三節 4 = 0000 0100,6 = 0000 0110,前 6 位相同,能覆蓋它們的最小字首是 172.16.4.0/22。但 /22 有 4 個 /24,多出來的 172.16.7.0/24 不屬於你。兩種處理:一是宣告兩條精確路由 172.16.4.0/23 和 172.16.6.0/24;二是宣告 /22,前提是 172.16.7.0/24 確定沒有分配給別人,並在本裝置上配丟棄路由。

例題三:數量是 2 的冪,為什麼還是不行? 172.16.6.0/24 到 172.16.9.0/24,正好 4 個。第三節 6 = 0000 0110,9 = 0000 1001,只有前 4 位相同,覆蓋它們的最小字首是 172.16.0.0/20,一口氣吸進 16 個 /24,其中 12 個不屬於你。原因是起點 6 不能被 4 整除,這 4 個網段橫跨了 172.16.4.0/22 和 172.16.8.0/22 兩個塊的邊界。精確的寫法是兩條 /23:172.16.6.0/23 和 172.16.8.0/23。

例題四:第四節上的彙總。 4 條互聯鏈路 10.255.0.0/30、10.255.0.4/30、10.255.0.8/30、10.255.0.12/30。變化發生在第四節,0 = 0000 0000,最大終點 15 = 0000 1111,前 4 位相同,24 + 4 = 28,彙總為 10.255.0.0/28。N = 4,起點 0 能被 4 整除,/30 減 2 位,結果一致。

手算容易在邊界上出錯,可以用 Python 自帶的 ipaddress 模組核對:下面的函式求出能覆蓋全部網段的最小彙總字首,並列出彙總後會多吸進哪些不屬於你的塊,列表為空就是精確彙總。

import ipaddress as ip

def summarize(nets):
    nets = [ip.ip_network(n) for n in nets]
    lo = min(int(n.network_address) for n in nets)
    hi = max(int(n.broadcast_address) for n in nets)
    plen = 32 - (lo ^ hi).bit_length()          # 起點和終點相同的高位個數
    sup = ip.ip_network((lo, plen), strict=False)
    extra = [sup]
    for n in nets:                                # 從彙總塊里扣掉自己的網段
        out = []
        for b in extra:
            if b.subnet_of(n):
                continue
            out.extend(b.address_exclude(n) if n.subnet_of(b) else [b])
        extra = out
    return sup, sorted(extra)

print(summarize(["172.16.6.0/24", "172.16.7.0/24", "172.16.8.0/24", "172.16.9.0/24"]))
# 172.16.0.0/20,多吸進 172.16.0.0/22、172.16.4.0/23、172.16.10.0/23、172.16.12.0/22
print(summarize(["10.40.8.0/23", "10.40.10.0/24", "10.40.11.0/25", "10.40.11.128/25"]))
# 10.40.8.0/22,多吸進的列表為空

彙總失敗的常見原因

“彙總失敗”有兩種表現:算出來的彙總塊比實際網段大,把別人的位址也包了進來;或者彙總配上去之後,部分流量走錯、丟包。原因歸納如下:

原因 例子 後果 處理方法
數量不是 2 的冪 3 個、6 個連續 /24 彙總塊裡有空位 拆成多條精確彙總;或確認空位未分配後整塊宣告並配 Null0
起點沒對齊 第三節從 6 到 9 彙總塊成倍擴大 按對齊邊界拆成多條;新規劃時讓起點對齊
中間有缺口 8 到 15 裡有一個 /24 分給了別的機房 兩處都宣告覆蓋同一段的路由 缺口所在位置宣告更長的明細,靠最長字首匹配分流;或者回收重新規劃
網段分散在不同出口 10.40.8.0/23 在機房 A,10.40.10.0/23 在機房 B 任一邊宣告 /22 都會把另一邊的流量引過來 各自只彙總本地擁有的部分
彙總點選錯 在只連了一部分網段的裝置上配彙總 這台裝置成為整段位址的入口,收到不屬於它的流量 在所有明細都匯聚到的那台裝置上彙總
彙總後的字首仍然太長 兩個 /26 合成 /25 後向公網宣告 多數運營商不接收長於 /24 的 IPv4 字首,宣告被上游過濾 公網宣告至少湊成 /24,具體以上游運營商的要求為準

第三、四行最隱蔽:兩台裝置宣告了重疊的字首,平時靠最長字首匹配各走各的,一旦某處的明細路由消失,流量就會被另一處的彙總路由吸走。所以規劃位址時,同一個彙總塊只放在一個位置,寧可多留空塊,也不要把一個塊拆給兩個機房。

彙總路由要配一條指向 Null0 的丟棄路由

彙總塊裡有未使用的位址時,必須防止環路。設想匯聚路由器 DC-R1 向核心宣告 10.40.8.0/22,自己的預設路由指向核心,而 10.40.11.0/24 還沒有啟用。一個發往 10.40.11.5 的包會這樣走:

  1. 核心查表,命中 10.40.8.0/22,交給 DC-R1;
  2. DC-R1 沒有 10.40.11.0/24 的明細,只能命中預設路由,又交回核心;
  3. 核心再交給 DC-R1,來回往返,直到 TTL 減到 0 才被丟棄。

TTL 為 64 的包會在這條鏈路上來回約 32 次,掃描器對整段位址做探測時,這種流量會被放大幾十倍佔用互聯頻寬。解決方法是在彙總裝置上加一條指向 Null0 的彙總路由:

ip route 10.40.8.0 255.255.252.0 Null0

Null0 是一個虛擬介面,送進去的包直接丟棄。根據最長字首匹配,10.40.8.0/23、10.40.10.0/24 這些明細路由比 /22 更長,仍然正常轉發;只有沒有明細的位址才落到這條 /22 上被丟棄,不會再回到預設路由。OSPF、EIGRP、BGP 在裝置上做彙總時,思科 IOS 預設會自動生成這條丟棄路由,靜態彙總要手工新增。

在思科、華為裝置上怎麼配彙總

彙總配置在哪裡,取決於路由從哪裡來:

! 1. 靜態宣告:本地丟棄路由 + 透過 BGP 宣告
ip route 10.40.8.0 255.255.252.0 Null0
router bgp 65001
 network 10.40.8.0 mask 255.255.252.0
!
! 2. OSPF:在 ABR 上把區域 1 的明細彙總後發往骨幹區域
router ospf 1
 area 1 range 10.40.8.0 255.255.252.0
!
! 3. OSPF:在 ASBR 上彙總重分佈進來的外部路由
router ospf 1
 summary-address 10.40.8.0 255.255.252.0
!
! 4. EIGRP:在出介面上彙總,100 是 AS 號
interface GigabitEthernet0/0/1
 ip summary-address eigrp 100 10.40.8.0 255.255.252.0
!
! 5. BGP:表中至少有一條明細時生成聚合,summary-only 抑制明細不再宣告
router bgp 65001
 aggregate-address 10.40.8.0 255.255.252.0 summary-only

幾個要點:

  • area range 只在 ABR 上、只對該區域內部的路由生效;對重分佈進來的路由要用 summary-address。兩者寫錯位置時命令能輸入,但不起作用。
  • BGP 的 network ... mask 要求路由表裡有完全一致的字首才會宣告,這也是第一種寫法要先加 Null0 靜態路由的原因。
  • aggregate-address 不加 summary-only 時,彙總和明細會一起宣告出去,上游路由表並沒有變小。
  • 配好後用 show ip route 10.40.8.0 255.255.252.0 longer-prefixes 檢視彙總路由和它下面的全部明細;OSPF、EIGRP 的彙總會顯示為 is a summary ... Null0,BGP 被抑制的明細在 show ip bgp 裡帶有 s 標記。

華為 VRP 的對應寫法:

場景 思科 IOS 華為 VRP
丟棄路由 ip route 10.40.8.0 255.255.252.0 Null0 ip route-static 10.40.8.0 22 NULL0
OSPF 區域間彙總 area 1 range ...(OSPF 程序下) abr-summary 10.40.8.0 255.255.252.0(區域檢視下)
OSPF 外部路由彙總 summary-address ... asbr-summary 10.40.8.0 255.255.252.0(OSPF 檢視下)
BGP 聚合並抑制明細 aggregate-address ... summary-only aggregate 10.40.8.0 22 detail-suppressed
檢視結果 show ip route ... longer-prefixes display ip routing-table 10.40.8.0 22 longer-match

華為裝置做 OSPF 或 BGP 彙總時,是否自動生成指向 NULL0 的黑洞路由隨協議和軟體版本而定,配置後用 display ip routing-table 10.40.8.0 22 檢查,沒有就手工加上第一行的靜態路由。具體引數隨軟體版本略有差異,以裝置的命令手冊為準。

在 IPAM 裡怎麼落地

彙總能不能做乾淨,在分配位址的那一刻就決定了:一個 /22 只要有一個 /24 分到了別的機房,這個 /22 就再也無法完整彙總。所以位址台帳要按彙總塊來組織,而不是按“下一個空閒的 /24”來分。

Toplink DCIM 的 IP 位址管理以 CIDR 格式錄入位址段,自動算出起止位址和掩碼,大段可以自動拆分為多個 /24 分別管理;每個段記錄所屬機房、VLAN 和閘道器裝置。按機房錄入彙總塊後,哪個 /24 在哪個機房、哪些還空著一目瞭然,例題二里那種“空位到底有沒有分給別人”的問題,查一下段的歸屬就能回答。暫時不用的段可以設為鎖定,自動分配時不會被佔用,給將來的擴容和彙總留出完整的塊。

常見問題

思科的 auto-summary 是什麼,要不要關?

auto-summary 是 RIP 和 EIGRP 在有類邊界上自動彙總的功能,例如把 10.40.8.0/22 自動彙總成 10.0.0.0/8。同一個有類網路的子網分散在不同位置時,它會讓兩邊都宣告同一條 /8,造成流量走錯。EIGRP 從 IOS 15.0(1)M 起預設關閉;RIPv2 在不少 IOS 版本里預設開啟,用 show ip protocols 可以確認當前狀態。今天的網路應當執行 no auto-summary 關閉它,改為手工彙總。

IPv6 也能這樣彙總嗎?

能,演算法相同,只是按十六進位制換算二進位制。例如 2001:db8:10::/48 到 2001:db8:13::/48 四個塊,第三組 0x10 到 0x13 的前 14 位相同,加上前兩組的 32 位,彙總為 2001:db8:10::/46。IPv6 位址空間大,規劃時按 2 的冪對齊預留,彙總通常比 IPv4 簡單。

彙總後某個子網斷了,上游還會把流量送過來嗎?

會。只要彙總範圍內還有任何一個明細路由存在,彙總路由就一直宣告,上游看不到明細的變化,發往斷開子網的流量仍會送到彙總裝置,再被 Null0 丟棄。這是彙總隔離故障的代價:需要靠監控發現明細路由的消失,而不是靠上游路由表。

想看看在你的機房裡怎麼用?

從一次產品示範開始,梳理你的業務鏈路。

查看價格
服務熱線 400-112-2951

讓我們聊聊你的 IDC 業務

掃碼新增企業微信,預約產品示範或申請試用。

Toplink 企業微信二維碼

長按儲存或使用企業微信 / 微信掃描

也可致電
400-112-2951
Telegram
@TopLink88