IPv4 地址耗盡,為啥 IPv6 還是沒人用?
今年年初,因 IPv4 將耗盡,巨頭企業宣布收費后,IT行業內對 IPv6 的發展尤為關注,網絡工程師們也不例外。
我一直對IPv6這個名字感到困惑,因為我覺得IPv4名字來源于它用來表示32位的四個字節,所以IPv6應該被稱為IP16。
但實際上,這只是協議的版本號。
在IPv4推出之前,曾存在過IPv1、IPv2和IPv3,它們主要用于內部研究IP協議,后來被我們現在的IPv4所取代。
在上世紀80年代,還提出過IPv5的提案,旨在優化實時通信,但大家發現IPv6能解決地址空間問題后,該提案就被放棄了,因此才有了IPv6這個名字,代表互聯網協議第6版。
后來有人嘗試創建IPv7、IPv8等更高版本,但它們要么已被廢棄,要么被擱置起來。
和IPv4一樣,IPv6有自身的尋址方案,但它使用的是128位地址而非IPv4的32位地址。
這兩種協議之間的差異不僅體現在地址空間大小上,而且與IPv4對比,IPv6有其獨特特性,比如:
01 IPv6沒有子網掩碼
IPv6和IPv4同樣支持CIDR(無類別域間路由),但從用戶角度看,IPv6地址要簡單得多:前半部分是全球互聯網地址,后半部分是本地地址。這是推薦的IPv6地址使用方式。當你訪問某個顯示IP地址的網站如WhatismyipWhatever時,它會顯示出你的IPv6地址形式如下:
1111:2222:3333:4444:5555:6666:7777:8888
但是,你的互聯網服務提供商(ISP)只知道你的前綴部分為1111:2222:3333:4444,并將這個/64的地址塊分配給你。地址的剩余部分對你的網絡中的每一臺設備都是獨一無二的。ISP只會將所有以1111:2222:3333:4444開頭的數據包轉發至你的路由器,然后路由器會將數據包進一步傳遞到目標設備。因此,地址的后半部分(5555:6666:7777:8888),我們可以稱之為INTERFACE_ID,這部分對于你的設備來說是唯一的。這就意味著你擁有的每一臺設備都擁有一個獨特的IPv6地址,可以從世界任何地方單獨訪問,原因在于:
02 IPv6 不使用 NAT 技術
實際上,針對 IPv6 的 NAT(Network Address Translation,是指網絡地址轉換) 并不存在公開的標準規范。雖然有一個名為 NAT66 的草案提議,但至今并未轉化為現實標準。
之所以在 IPv6 中不需要 NAT,是因為理論上地球的每個設備都可以有一個獨立的全球可訪問的地址。
開始我對此感到很奇怪,因為在玩網絡游戲時雖然我們常常痛恨 NAT 導致的種種不便,但它卻給人一種安全感,除非你明確通過 UPnP 或端口轉發允許,否則你的本地設備永遠不會被外部網絡直接訪問。
有一個殘酷的事實是,NAT 并不是一道安全屏障,它只是一個替代的數據包轉發機制。
在默認情況下,你的IPv6路由器本不應隨意將來自外部的連接嘗試轉發給本地設備。
因此,在 IPv6 環境下,即便不使用 NAT,你也同樣可以獲得相同級別的安全保障。
實際上,借助IPv6地址,你無需經過路由器,或者不必另行配置VPN,就能直接訪問本地網絡上的每一臺設備:只需要進行身份驗證即可。
盡管IPv6為每臺設備分配獨立的IPv6地址帶來了便利,但也存在一個與安全相關的問題:由于每個設備都有獨一無二的地址,因此它們可以被個別識別和跟蹤,這對我們的隱私保護構成威脅。
為此,現代操作系統引入了臨時IPv6地址的概念,該地址的INTERFACE_ID會定期變化。
這樣一來,你可以使用永久IPv6地址接收外部的連接請求,而在建立連接時,對外展示的是一個頻繁變動的二級臨時地址作為你的IPv6地址。
03 IPv6地址具備自動配置功能
IPv6協議無需依賴DHCP(Dynamic Host Configuration Protocol,動態主機設置協議)服務器或手動網絡配置來確定IP地址、子網掩碼及網關地址。一臺設備可以不通過詢問中央服務器而自主獲取IP地址。
這一過程是通過一個名為SLAAC(Stateless Address Autoconfiguration,無狀態地址自動配置)的協議實現的,具體步驟如下:
操作系統(特別是操作系統的IPv6堆棧)會生成一個64位的設備標識符,通常是隨機生成的,比如5555:6666:7777:8888,這個標識符構成了你的IPv6地址INTERFACE_ID部分。
操作系統會在該INTERFACE_ID前加上fe80,這是僅限本地使用的IPv6網絡前綴。因此,你現在得到的IPv6地址是:fe80::5555:6666:7777:8888。(請注意這里的"a::b"語法表示的是:“在'a'和'b'之間存在所有值為零的段”。關于這點我們稍后再詳細介紹。)
你的設備會將一個數據包發送到本地網絡上指定的鄰居多播組,以確保沒有其他設備使用相同的IPv6地址,這被稱為重復地址檢測(DAD)。而分配到重復地址的幾率很小。
設備將它獲取到的本地地址發送給路由器(與IPv4不同,在IPv6中,路由器始終可以通過組播地址ff02::2被訪問到),并通過發送一個RS(路由請求)ICMPv6數據包來請求路由器的實際前綴。路由器收到請求后,會通過RA(路由通告)數據包回應,并用回復的實際前綴替換掉fe80,設備隨后開始使用這個新的地址作為其永久地址。這就是你現在的IPv6互聯網地址。
如此一來,無狀態配置的優勢在于減少了路由器上的管理開銷:路由器無需單獨維護網絡中每個設備的IP配置信息。
意味著這將可以帶來更好的性能表現,特別是在大型網絡中尤為明顯。
IPv6也有一些夸大的說法,我們一起梳理澄清下:
01 你設備只有一個IPv6地址,可用于在所有地方
確實,你會使用同一個IPv6地址進行本地和遠程連接。但是,“一統天下之IP地址,尋遍萬物之IP地址”的說法并不準確。
正如我之前所提到的,你的設備會為了不同范圍的目的聲明多個IPv6地址,比如鏈路本地(fe80::)和互聯網。
此外,你的設備也可能獲得兩個不同的公網IPv6地址:永久地址和臨時地址。
臨時IPv6地址旨在保護你的隱私,它們會定期輪換。而永久IPv6地址主要用于必須具有靜態IPv6地址的服務器。
02 為宇宙中每個原子分配一個IP地址
還遠遠不夠的。宇宙中大約有22?2個原子,地球約有21??個原子,所以我們至少需要168位(八位對齊)的地址空間來容納它們。
實際上,IPv6的地址空間略小于128位:前16位是IANA預留的。
因此,你只能用剩下的112位來標識設備。盡管這非常多,遠超過我們在未來幾千年里地球上可能制造的所有設備的數量,但并不能為每一個原子分配一個獨立的IP地址。
然而,我們可以為地球上的每一粒沙子分配IPv6地址,甚至我們還可以將這些地址全部裝進一個單一的/64前綴內。總之,IPv6地址空間是極其龐大的。
03 每個設備的通用連接
沒錯,IPv6沒有NAT機制,這意味著不再需要端口轉發或維護地址空間。但是,如果你想建立直接連接,仍然需要有一種機制允許遠程主機連接到你的設備。
默認情況下,你的路由器/防火墻會阻止任何連接嘗試。
你會怎么做呢?
就像UPnP/IGD時代一樣,今天的應用程序仍然需要與PCP(端口控制協議)這類協議配合工作,才能以編程方式打開端口訪問權限。
所以,并不是說你突然間就能憑借全局+本地IPv6地址實現通用連接。雖然你不必手動設置端口轉發,但應用程序仍需與路由器協作才能使自身變得可訪問。
從我看來,在某些情況下,IPv6的表現甚至不如IPv4。
在IPv4環境下,我們習以為常的一些功能,當過渡到IPv6后可能會讓你懷念,例如:
01 依賴ISP提供子網劃分服務
由于IPv6不采用NAT技術,許多美國ISP默認只向你的路由器轉發一個64位前綴(通常稱為“/64”)。
這意味著路由器無法在IPv6地址中嵌入子網信息。
要知道,IPv6地址是由設備自動配置的,因此路由器無法強制這些設備使用小于64位的本地地址,這讓路由器無法知道應該將數據包轉發到哪個子網。
你得依賴于ISP提供短于64位的前綴,這樣你的路由器才能利用剩余的比特位來識別數據包應當發往哪個子網。
理論上講,通過分配60位前綴,ISP實際上完全有能力給家庭用戶提供至少16個子網,但不知道為何他們并沒有這樣做。
或許是因為他們在IPv4地址空間匱乏時期的心理創傷讓他們變得貪婪?
或者是他們想通過額外收費來賺錢:“嘿,如果你想要更短的前綴,那就多付點錢給我們。”
據我所知,Comcast Xfinity和AT&T兩家公司都只為家庭用戶提供了一個簡單的/64前綴:即單個子網。
你或許會說,家庭用戶可能根本不需要子網劃分,但是隨著物聯網設備的普及以及我們對網絡安全越來越高的依賴性,隔離不可信設備的重要性正在日益凸顯。
歐洲IP地址分配權威機構RIPE建議住宅ISP客戶使用56位前綴,這樣每位客戶可以獲得256個子網,這是歐洲提出最貪婪、也最保守的選項,而在美國,這幾乎是可望而不可及的夢想。
當然,你可以手動配置每一臺設備的IPv6地址,并以此方式賦予它們子網標識符,但這將是一項巨大的工程,尤其是考慮到添加新設備時帶來的管理負擔。難道你想退休后變成一個人工DHCP服務器嗎?
02 IPv6地址在URI中需要額外編碼
我們可能都試過在瀏覽器輸入“http://192.168.0.1”并訪問路由器設置。在URI規范中“:”字符是為端口號保留的,所以如果沒有額外的編碼,無法直接采用相同的方式來訪問IPv6地址。若想通過IPv6地址訪問一臺設備托管的網頁,必須采用如下格式:
“http://[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]/path/?query”
注意地址兩邊的方括號。
但這還不是最糟糕的部分,因為:
03 IPv6地址難以記憶
理論上我們不應去記住IP地址,但實際情況并非如此。對于IPv6地址,我至今也無法確定可靠且一致地訪問自家路由器所使用的地址。確切地說,我無法記下它的完整IP地址。
mDNS有助于解決這個問題,但它也不總是穩定有效。
十六進制數字相比十進制數字也更為復雜。這就像是試圖記憶Windows XP產品激活碼一樣困難。
記住IPv4地址是一種通用技能,由于普遍存在的NAT技術,多數情況下“192.168.1.1”都能派上用場,我們無需查詢。而在任意設備上找出路由器的IPv6地址則需要不同的技巧。
從積極的一面看,現在你知道IPv6地址的最右側64位部分始終是隨機生成的,所以至少可以避免誤以為它是固定不變的或者是有意義的。
你可以將這一部分稱作BLABLA而非INTERFACE_ID。你可以記住你的/64前綴,至少能找到路由器的地址,通常是類似1111:2222:3333:4444::1這樣的形式。
04 IPv6地址復雜
當然,IPv4地址同樣復雜。你知道2130706433是一個有效的IPv4地址嗎?或者換種寫法,0x7F000001、0177.0000.0000.0001,以及127.1其實都是一回事?
如果不信,你大可在終端嘗試ping它們。雖然很難相信,但它們全等同于127.0.0.1這個地址。
IPv6地址在表示形式上也有類似的多樣性。以下是其一些特征:
IPv6地址的表示方法相對復雜,由8個十六進制分組組成,這些組被稱為“hextet”(實際上“Hextet”是hexadectet的誤稱,但現在已約定俗成)。這樣一來,就可能出現類似的十六進制表達技巧:
IPv6地址中的零值前綴不會顯示,因此2600:00ab實際上顯示為2600:ab。
如前所述,如果某個十六進制四字組的值為零值,可以完全從地址中刪除,并用雙冒號代替。因此,2600:ab:0:0:1234:5678:90ab:cdef將顯示為2600:ab::1234:5678:90ab:cdef。看到雙冒號了嗎?不過要注意的是,這種簡化方式只能應用于地址中首組連續的零值四字組。
因此,2600:ab:0:0:1234:0:0:cdef仍顯示為2600:ab::1234::0:cdef。另外,不能僅僅簡化單個零值的十六進制四字組。
因此,2600:0:1234:5678:abcd:ef01:2345:6789中的零值保持原樣,不會被省略。
你可以指定區域ID:通過在地址末尾添加“%”后綴和區域ID來指定要通過哪個網絡接口訪問該地址。例如,當你同時通過WiFi和以太網連接到同一網絡時,你可能想要通過局域網來ping你的路由器。
在這種情況下,你需要在地址后面追加“%”符號,并添加你的區域ID(即網絡適配器標識符),例如fe80::1%eth0或fe80::1%3。問題是,在IPv6 URI中除了需要用到方括號之外,你在瀏覽器地址欄或其他需要在URI中使用區域ID的地方,還必須將“%”轉義為“%25”。
IPv6地址還可以用來表示IPv4地址。因此,你可以通過在其前方添加IPv4轉換前綴的方式,使用IPv6地址語法來ping 127.0.0.1,這時它將被視為一個IPv4地址,即:::ffff:127.0.0.1。
但這并不意味著你的IPv4請求會通過IPv6網絡進行傳輸,而是告訴底層網絡協議棧使用IPv4連接。如果選擇不同于::ffff的前綴,IPv4部分將會被合并到最后兩個十六進制字節中,并通過IPv6網絡與該IP地址建立連接。
例如,IPv6地址2600:1000:2000:3000::192.168.1.1會被視為2600:1000:2000:3000::c0a8:101,其中最后兩個十六進制字節相當于IPv4地址192.168.1.1的十六進制表示形式。
這些都是有效的IPv6地址:
:: 表示所有零,即0:0:0:0:0:0:0:0.
2600:: 相當于2600:0:0:0:0:0:0:0.
::ffff:1.1.1.1 等同于IPv4地址1.1.1.1 。
2607:f8b0:4005:80f::200e 是我ping google.com時獲取的地址,與2607:f8b0:4005:80f:0:0:0:200e等效。可以看出,像Facebook一樣,Google也選擇了艱難的道路,決定為其IPv6地址手動分配特定的INTERFACE_ID。
最終,在地址欄中輸入的IPv6地址可能看起來像下面這個人為構造的例子:
https://[542b:b2ae:ed5c:cb5a:e38b:2c49:123:192.168.1.1%25eth3]
我可記不住這么長的地址。
通過這次學習,讓我對IPv6的相關知識有了更清晰的認識。例如,我以前不知道IPv6地址是通過無狀態協議自動配置的,也不知道IPv6中沒有NAT技術,更不了解地址空間是如何恰好被便捷地劃分為兩半的。
我希望我們能有一個指向默認網關的快捷IPv6地址,我提議使用fe80::1。國際互聯網工程任務組(IETF),不妨考慮一下這個提議。
我還記得當初Windows 2000宣布支持IPv6時,那是個重大的進步,我們都認為IPv6將在十年左右的時間里被廣泛采用。
沒想到我們錯得離譜!
然而,通過對IPv6的學習,我才理解到為什么這項技術沒有快速普及起來。
05 IPv6并未對終端用戶提供實質好處
盡管IPv6在技術上較為先進,但IPv4卻簡單實用,即使是在NAT(網絡地址轉換)之后,甚至是多層NAT環境下,面對地址空間極度緊張、DHCP配置繁瑣、端口轉發復雜的條件下,IPv4依然能夠正常運作。只要出現問題,總有人找到解決方案使其繼續工作。
理論上IPv6因無需NAT可能具有更低延遲的優勢,但這點改進還不足以顯著提升用戶體驗,不足以讓用戶強烈要求切換至IPv6。
正因為IPv6并未帶來直觀可見的好處,用戶并不會主動要求使用,往往是在他們不知情的情況下被推向IPv6,就像我們現在在移動網絡中幾乎默認使用IPv6一樣。
這意味著,一旦互聯網服務提供商感受到IPv4的限制帶來的足夠壓力時,它們將會立刻切換到IPv6。
我希望IPv6能夠開啟一些IPv4無法實現的獨特功能場景,讓用戶能夠因為想要使用這些功能而主動需求IPv6。盡管如此,我還是喜歡IPv6特質,期待有一天我們完全放棄IPv4,轉而圍繞IPv6來構建所有網絡服務。
對于IPv6,一些開發者提出自己的觀點:
開發者@9dev 表示
對終端用戶而言,真正的益處在于整個互聯網協議棧回歸到它應有的完全透明狀態。用戶不應該再需要操心IP地址問題;IPv6使得設備真正實現“即插即用”,即設備能夠自行獲取地址,自行協商連接。理想情況下,用戶再也不必關心這部分連接問題。的確,IPv6給網絡運營商帶來了復雜性,但這也是復雜性應當的。
@lxgr 有不同的意見:
針對“IPv6沒有子網掩碼”的說法,他認為絕對是有子網掩碼的,只不過在IPv6中它們被稱為前綴長度。/64前綴剛好適合與SLAAC(無狀態地址自動配置)配合使用。
針對“IPv6沒有NAT”的說法,同樣,IPv4也沒有自帶NAT。NAT是一種路由器可以選擇實現的技術,當然在IPv6中也同樣可行。例如,Linux操作系統就實現了IPv6的NAT,只擁有一個IPv6地址的情況下,例如從本地網絡獲得一個地址并在機器上運行虛擬機時,IPv6的NAT可能是必不可少的。
針對“IPv6地址是自配置的”的說法,有時確實是這樣,但也有時候并非如此,還有DHCPv6和靜態配置的方式。
針對“IPv6地址無法記住”的說法,那又怎樣呢?反正他也沒興趣記住IPv4地址、電話號碼等信息。
針對“IPv6對終端用戶沒有好處”的說法,作為終端用戶,他發現IPv6給我帶來了很多好處:
防火墻穿越比NAT穿越更可預測且成功率更高。像VoIP、Tailscale等服務在IPv6環境下相比跨越一層或多層NAT的成功率大大提高。
家里的所有設備都可以獲取公網地址,他可以通過路由器上的防火墻規則選擇性地開放入站連接。
移動網絡上的路由更為直接,從而降低了延遲(IPv4常常需要通過一系列昂貴且具有狀態的CG-NAT設備,在使用的移動網絡服務商部署IPv6的地區,這種情況得以避免)。
對于 IPv6,你怎么看?