為什麼四十億從來就不夠用
回想這個段落前面講過的:一個 IPv4 位址寬 32 位元。聽起來很大方,直到你算一下:32 位元最多只能命名 2^32 個不同的位址,也就是大約 43 億個。在 1970 年代,當網際網路協定是為了幾百台研究機器而設計時,43 億感覺荒謬地、幾乎是難為情地多。沒有人想得到,有一天手機會比人還多,再加上筆電、相機、門鈴、汽車和燈泡,全都想要一個位址。
而且情況比這個原始數字暗示的還糟,因為位址是一整塊一整塊發出去的,不是一個一個發。如同你在 CIDR 看到的,一個機構拿到的是一整段前綴,例如一個 /16 或 /24,而每一塊裡有很多位址都閒置著——被保留、被預留給未來成長,或乾脆就被困在那裡用不到。所以實際能用的數量一直都遠少於 43 億。到了 2010 年代初,負責發放位址塊的各區域註冊機構開始一個洲接著一個洲地見底,再也沒有東西可發了。
上一篇講了那個讓一切繼續運轉的權宜之計:NAT,讓整個家庭與公司共用一個公開位址。NAT 爭取到一兩個十年,但它是補丁、不是解藥——它打破了「任何機器都能定址任何其他機器」這個乾淨的想法,並讓從點對點應用到在家架伺服器的一切都變得麻煩。誠實的修法,正是工程師在 1990 年代中期動手做的那一個:設計一個後繼協定,它的位址空間大到我們永遠不會再進行這場對話。那個後繼者就是 IPv6。
128 位元:一個你其實無法想像的數字
IPv6 最醒目的改變,是對位址動用蠻力:把位址從 32 位元加寬到 128 位元。這不是大四倍;每多一個位元數量就翻倍,所以 128 位元給出 2^128 個位址,大約是 3.4 後面接 38 個零。常見的比喻是:IPv6 位址多到可以給地球上每一粒沙子一個,還幾乎全部都用不完。逼出 NAT 的那場短缺,就此不再是問題——地球上每一台裝置都可以重新擁有一個真實、全球唯一的位址。
因為把一個 128 位元的數字寫成點分十進位會毫無希望,IPv6 位址改寫成八組、每組四個十六進位數字,用冒號分隔。為了好讀,一組裡開頭的零可以省略,而連續一整串全為零的組可以縮成一個雙冒號。於是長形式 2001:0db8:0000:0000:0000:0000:0000:0001 縮成親切的 2001:db8::1。一個位址裡雙冒號只能出現一次,否則你就無法判斷它代表了多少組零。
IPv4 address 32 bits -> 192.168.1.10 ~ 4.3 x 10^9 addresses (2^32) IPv6 address 128 bits -> 2001:db8::1 ~ 3.4 x 10^38 addresses (2^128) Writing an IPv6 address, step by step: full 2001:0db8:0000:0000:0000:0000:0000:0001 drop leading zeros in each group 2001:db8:0:0:0:0:0:1 collapse ONE run of zero groups 2001:db8::1 A prefix still uses CIDR slash notation: 2001:db8::/32 (first 32 bits = network)
不只是更大:一個更乾淨、更精簡的封包
設計者沒有止步於更寬的位址;他們趁機把 IP 資料包的標頭本身也整理了一番。IPv4 標頭長出了一叢欄位,很多很少用到,加上一個可變長度,逼路由器得小心翼翼地解析。IPv6 標頭固定為 40 位元組,帶的欄位少得多。那些瑣碎的東西——分段控制、選項——被搬出主標頭,移進可選的「延伸標頭」,只在需要時才串接上去,於是常見情況就是一個簡單、可預測、路由器能快速處理的標頭。
有一個改變重要到值得特別點出。回想前面講的 IP 分段:當一個資料包對某條連結的 MTU 來說太大時,IPv4 允許中途的某個路由器把它剁成幾片。IPv6 則完全禁止路由器分段——若一個封包對下一條連結來說太大,路由器就丟棄它,並回送一則 ICMP 訊息說明,原始發送端必須自己學到正確的大小、改送較小的封包。這叫做「路徑 MTU 探索」,它把吃力的工作留在那個資料包誕生的端點上,讓路由器除了轉送以外什麼都不必做。
難的地方:你沒辦法一鍵切換
這裡有個讓它成為漫長道路、而非快速升級的關鍵:IPv6 與 IPv4 不向後相容。一台純 IPv6 主機與一台純 IPv4 主機,根本無法理解彼此的封包——標頭的形狀不同,位址的大小也不同。沒有一個中央開關可以關掉舊的網際網路、打開新的。在已有數十億台裝置、路由器與伺服器在說 IPv4 的情況下,唯一務實的路徑是一段漸進、長達數十年的共存。那段共存,就是 IPv6 轉換的整個故事。
- 雙堆疊(dual stack):主力作法。一台裝置同時跑 IPv4 與 IPv6,兩種位址都有。當它想連到另一台機器時,它去問 DNS,DNS 可以回傳一個 IPv6 位址、一個 IPv4 位址、或兩者都回;裝置若有可用路徑就偏好 IPv6,沒有就悄悄退回 IPv4。
- 通道化(tunnelling):當兩座 IPv6 島嶼被一片純 IPv4 的海洋隔開時,你把每個 IPv6 封包包進一個 IPv4 封包裡載著它過海,到對岸再拆開。這就是基礎段落講過的封裝想法,用來把新協定偷渡穿過舊網路。
- 轉譯(translation):中途的一個閘道實際把封包從一種協定改寫成另一種,於是一個純 IPv6 的用戶端仍能連到一台純 IPv4 的伺服器。它很強大,但有損且複雜,很像 NAT,用在無法雙堆疊的場合。
- 隨著歲月推移,天平逐漸傾斜:越來越多網路開啟 IPv6,雙堆疊成為常態,而 IPv4 那一側被倚賴得越來越少,直到某一天它終於可以退役。我們在這場轉換中已走得很深,但尚未走完。
為什麼花了這麼久,以及它對路由器意味著什麼
如果 IPv6 明顯更好,為什麼規範出來二十五年多了,我們還在轉換途中?因為付錢部署它的人,不是受益的人。NAT 運作得夠好,對家庭使用者幾乎沒有壓力;而對一家 ISP 來說,為了一項顧客根本分不出與 IPv4 有何不同的服務去升級設備,是實實在在的成本與風險。這是經典的雞生蛋蛋生雞僵局:內容供應商等使用者先有 IPv6,網路又等值得透過它去取用的內容。最後是 IPv4 耗盡的真實痛苦,才終於推動了雙方。誠實的教訓是:更好的技術不會自己部署——是誘因與動能決定了步調。
不論一個封包穿的是哪個版本的外衣,路由器的核心工作都沒變,而那正是這個段落下一篇、也是最後一篇要打開的東西。路由器仍然從標頭裡讀出目的位址,到它的轉送表裡查找,以決定該從哪個介面把它送出去。查找用的是「最長相符前綴」——而請注意,這是一個更寬的 IPv6 位址要付出更多代價的地方,因為要比對的是 128 位元而不是 32 位元。兩者的原理完全相同;下一篇帶你進到那次查找的內部,看路由器如何在奈秒之內轉送一個封包。