1. 程式人生 > >將 IPv6 照進現實,我們需要做些什麼?

將 IPv6 照進現實,我們需要做些什麼?

阿里妹導讀:隨著中共中央辦公廳、國務院辦公廳印發了《推進網際網路協議第六版(IPv6)規模部署行動計劃》後,整個 IPv6 產業鏈開始活躍起來。雖然目前我們距離世界上每一粒沙子都有一個地址的夢想還有點遠,但加速推進的大趨勢應該是不爭的事實。但是我們在仰望星空的同時還需要腳踏實地,那麼 IPv6 的現實是怎樣的呢,我們還需要準備什麼呢,這就是這篇文章想要表達的。

IPv6這個曾經以解決地址短缺問題而出現的技術存在了很久,但因為種種原因沒在世界範圍內普及,尤其是沒在中國普及。今天的文章不是 IPv6 科普文章,也沒有過多的涉及到網路如何改造,業務如何適配,更多的是從用的角度來看現狀。另外從我個人角度,移動網 IPv6 化會走在固網 IPv6 的前面,移動網應該是雙棧的策略,所以文章的分析都是以移動網為前提,固網暫不涉及。

手機支援雙棧嗎?

IPv6 在相當長一段時間內沒能夠在公眾網中普及,很重要的一個原因就是各方的動力不足,雖然一直在宣傳 IPv4 地址不夠用了,但縫縫補補還是讓網際網路走了這麼多年。如果拋開動力不足來看,IPv6 的普及其實是一個系統工程,需要的是端、管、雲,三方的協同支援,那麼我們先看下端,也就是手機的支援情況。

首先是蘋果 iPhone,對於 v6 蘋果早在幾年前就強推 APP 對於 IPv6 only 的支援,如果不通過這個功能稽核是不能上架 App Store 的。但當時對於 APP 開發者來說最為鬱悶的是在國內很難找到一個商用的 IPv6 Only 環境進行測試,更多是 Mac 熱點或者 WiFi APP 來模擬進行網路庫的邏輯測試,在移動網下是沒有辦法做測試的。而這樣的問題在目前 IPv6 改造期間一樣面臨,即在國內蘋果 iPhone 在移動網下只能獲得 v4 地址,沒有 v6 地址。為什麼呢,因為 iPhone 裡面的 APN 設定是不能修改的,而內建 APN 中對於地址請求所攜帶的欄位僅僅是 IPv4 型別,這樣即使網路支援雙棧,iPhone 還是隻能獲得v4地址,下圖就是一個蘋果手機在移動網內的信令請求:

上面標黃的地方顯示 PDN type 為 IPv4。如果雙棧的話,這裡的 type 型別是IPv4IPv6。在國家機構,運營商的聯合推動下,蘋果手機從 iOS12.1 開始已經開啟了預設雙棧的支援。

下面該談到 Android 了,安卓相對來說開放一些的,大多數的手機都可以支援 APN協議編輯,並且部分手機已經預設設定變成了 IPv4IPv6 雙棧協議支援,如下截圖:

但在這裡還有幾個坑需要告知:

  1. 不是所有的安卓手機都可以編輯 APN 協議型別。
  2. 即使可以編輯 APN 協議型別,也不是所有的手機都會把 IPv4/IPv6 作為預設協議。
  3. 有些手機儘管是支援雙棧的,但從系統 API 裡面是看不到所獲得的 IPv6 地址,但如果你同時開了 WiFi,奇蹟出現了,v6 地址又出來了。

碎片化的安卓帶來了碎片化的雙棧支援,這對客戶端進行當前網路環境判斷帶來了很大挑戰。

移動運營商現在支援雙棧嗎,手機得到的地址有什麼玄機?

說完了端,下一步就需要看看管,即運營商到底對於 v6支援的現狀如何,策略如何?如開篇所說拋開固網不談,在移動網的場景下,三大運營商都已經開通了IPv4IPv6 的雙棧支援。不過需要說明的是,這裡的雙棧支援管道特指下圖中從空口到移動核心網這裡,至於骨幹網和阿里網路的雙棧支援要根據各個運營商的互聯情況來看。

下面看下在某運營商網路下終端拿到的地址資訊:

一般使用者回拿到 IPv4v6 雙棧地址,v6地址的 DNS 不是必須的有些省份可能沒有,但在雙棧情況下只要 DNS 能支援 AAAA 記錄的解析查詢即可。

下面就是要進入重要的 IPv6 地址獲得環節了,即以上的2409開頭的 v6地址客戶端是怎麼獲得到呢,這個地址有什麼玄機嗎?移動網內手機和網路通訊有兩個面,一個是控制面也就是俗稱的信令面,這個層面 APP 是感知不到的,另一個是使用者面,即APP 正常的業務資料流都走在這裡。在 IPv4 only 的場景下,手機地址的獲得單純通過控制面的信令互動即可,但在 IPv4 IPv6 雙棧場景下,流程就發生了一些變化。先來看信令面:

Create Session Request 是手機發給核心網的,裡面攜帶了幾個重要的資訊:

PDN Type 欄位需要是 IPv4/IPv6, PDN Address and Prefix(IPv6) 是全零。
Create Session Response 是核心網對手機的響應。

裡面包含了類似 PDN AddressPrefix 和 DNS Server 的資訊,但你可能會很奇怪發現這個 Prefix 不是一個真正的 Prefix,也和手機獲得到的地址格式有很多差異。

這時候就需要再看一下使用者面的訊息:

根據 IPv6 地址分配規則,FE80開頭的是鏈路單播地址,FF02::1是所有開啟了 IPv6組播的主機,再來看下 Router Advertisement 訊息:

這個訊息就包含了重要的 Prefix 欄位,這是基於 IPv6 stateless Autonomous Address-Configuration(SLACC) 的實現,從後續的資料流可以看到,手機收到了這個64位的字首後補充了後面的64位組合成完整的128位IPv6地址作為源地址進行正常的業務訪問。不過稍微有一點疑問的是這後面的64位地址是怎麼生成的,從多次測試來看每次後64位都是變化的,由於在手機上構造包需要 root,所以後續條件具備情況下會進行通過構造不同後64位的資料報文來進行測試,看看網路是不是僅靠前64位來識別使用者的。

接著就面臨到了最後一個問題,即這個地址有玄機嗎?128位的地址一方面讓人很難記,另一方面也給地址掃描造成了巨大的難度,如果這些地址都是完全隨機的,那麼對於那些依賴地址資訊的後端業務來說將是巨大的災難。不過運營商幫我們在一定程度上解決了這個問題,但他們的出發點是為了更好的監管,也就是在文章片頭的那句世界上的每一粒沙子都有一個地址後面要加上世界上每一粒沙子都是可被追蹤的。

根據工信部2014年釋出的《YD/T 2682-2014 IPv6接入地址編址編碼技術要求》,其中對使用者裝置接入地址結構的指導性意見為:

其中:

  • PB 為 IPv6 接入地址塊字首,長度為 n 的位元串。
  • AI 是編址識別符號,長度為 s+t 的位元串,包括長度為 s 的省份識別符號和長度為 t 的接入型別表示符兩部分。其中接入型別包括固網動態接入、固網靜態接入、移動蜂窩接入。
  • CC 是區/縣編碼,長度為 8 位。在工信部的檔案附錄,明確了全國各區縣的具體8位編碼。
  • SSI 是子網識別符號,長度為56-n-s-t。
  • IID 是介面識別符號,長度64位。

國內三大運營商都基於此技術要求做了進一步的細化,這裡不再描述細節,但從地址大段上來看中國移動使用的2409:8000::/20IPv6地址,中國聯通使用的2408:8000::/20 IPv6地址,中國電信則有240E::/24、240E::/20、2001:0C68 ::/32、2001:07FA:0010::/48、2402:8800::/32 五塊地址。

不過這裡需要說明的是目前雙棧僅在 4G 下開啟,也就是說回到 2G 會變成 IPv4 only,這又該客戶端對於當前網路環境判斷增加了變數;還有就是由於目前地址具有了一定的位置屬性,那麼跨區縣移動場景下的地址分配怎麼處理還暫不明確。

Happy EyeBall 問題

在手機,網路和服務端全鏈路支援雙棧的場景下,手機首先要面對的就是一個選擇問題,即一個域名會解析出來 A 和 AAAA 記錄,簡化來說就是兩個地址,同時返回兩個地址,怎麼選擇?一個快,一個慢怎麼選擇?一個出問題怎麼選擇?地址選擇好了才能有後續的建連,才會有業務發生,所以這個選擇策略很重要。如果從體驗角度出發,誰快連誰這是最簡單的邏輯,但在當前 v4 網路好於 v6 的大環境下這樣的邏輯只會讓 v6 的普及變得更為艱難,因此針對這個問題,IET F先起了一個名字叫 Happy Eyeball,接著釋出了兩份 RFC 來描述推薦的處理邏輯,最新的是 RFC8305 Happy Eyeballs Version 2: Better Connectivity Using Concurrency,有興趣的可以去閱讀下,這裡只摘抄出最重要的一段:

The algorithm proceeds as follows: if a positive AAAA response (a responsewith at least one valid AAAA record) is received first, the first IPv6connection attempt is immediately started. If a positive A response is receivedfirst due to reordering, the client SHOULD wait a short time for the AAAAresponse to ensure that preference is given to IPv6 (it is common for the AAAAresponse to follow the A response by a few milliseconds). This delay will bereferred to as the "Resolution Delay". The recommended value for theResolution Delay is 50 milliseconds. If a positive AAAA response is receivedwithin the Resolution Delay period, the client immediately starts the IPv6connection attempt.

簡單來說就是 RFC 建議優選 IPv6,且給 AAAA 記錄的返回留50毫秒的容忍期。

由於系統的限制,這樣選擇邏輯的落地是客戶端網路庫無關的,基於網路材料來看目前各系統的具體實現:

蘋果 iOS:在 v4 和 v6 雙協議棧的情況下,從 ios9 開始蘋果會發出 A 和 AAAA 記錄的 DNS 請求,如果首先收到了 DNS 的 AAAA 記錄返回,那麼蘋果會馬上發出v6 的 syn,如果首先收到了 A 記錄的返回,會有一個 25ms 的定時器,如果超時了就會發送 v4 syn,如果在這個定時器內收到 AAAA 就會發送 v6 的 syn。這個機制和 Happy Eyeball 基本一致,只是等待時長不同,蘋果會不會修改到 RFC 建議值未知。

Android:優選 v6,但等待時長未知。

這樣的機制從理論上就會出現由於這個等待時長造成業務體驗的下降。

還有NAT嗎,會有PAT嗎,還有防火牆嗎?

在移動網只有 IPv4 的場景下,手機使用者訪問服務端的整個鏈路中必不可少的一箇中間裝置就是運營商的防火牆,一方面為了應對 v4 地址稀缺的問題,裝置會做公私網的地址翻譯,為了更進一步的複用地址,還會做埠翻譯,另一方面為了安全性考慮,裝置會做一些類似 ACL 的安全策略,通常只會允許出方向的訪問,同時為了降低對於裝置的負荷,還會做一些超時的設定,斷開那些空閒較長的連線。而這樣的限制對於服務端某些過度依賴地址的應用,對於埠轉換不友好的應用,對於需要長期保活的應用都會產生一定的影響,那麼在 IPv4v6 雙棧的場景下如何呢,我做了如下的測試:在一臺有公網 IPv6 地址的伺服器上簡單用 python 寫了一個開啟80埠的服務端:

Server start at:2400:3200:1000:xx:::80
wait for connection...
在手機上執行busybox telnet 2400:3200:1000:xx:: 80 命令
這是服務端打出的日誌
Connected by('2409:8928:84e:995:xxxx:xxxx:xxxx:xxxx', 34102, 0, 0)

其中 Connected by ('2409:8928:84e:995:xxxx:xxxx:xxxx:xxxx 為服務端看到的手機地址,34102為對應的埠號,那麼這個地址和埠號是不是手機自身的呢,去手機上看一下:

odin:/ $ busyboxnetstat
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 10.84.66.147:43623 111.13.134.131:443 CLOSE_WAIT
tcp 0 0 10.84.66.147:46051 140.205.34.21:443 ESTABLISHED
tcp 0 0 ::ffff:10.84.66.147:49856 ::ffff:112.13.64.13:5333 ESTABLISHED
tcp 0 0 ::ffff:10.84.66.147:37201 ::ffff:39.106.239.196:443 ESTABLISHED
tcp 0 0 ::ffff:10.84.66.147:55440 ::ffff:118.194.55.183:5223 ESTABLISHED
tcp 0 0 2409:8928:84e:995:3b4a:38ce:8ead:1972:34102 2400:3200:1000:xxxx:::80ESTABLISHED

從上面輸出來看,運營商的中間裝置沒有做 NAT,也沒有做 PAT,服務端看到了手機發出的原始的源地址和源埠,當然防火牆還是有的,主動從服務端還是不能訪問手機。

MTU問題

從協議頭來看 v4 和 v6 有一個比較重要的差異就是 Don’t Fragment bit 這個位一直開的,也就是由於一直是開的所以在 IPv6 的頭裡面就沒有明示這個欄位,如果有fragment 就會增加一個 Fragemention Header。由於網路中間支援 v6 的路由器不會對對 IPv6 包進行分片,所以如果一個包過大那麼路由器會產生 ICMP6 Type2 資料包,內含 Packet Too Big (PTB) 和 MTU 資訊返回給傳送方,這樣機制看上去比較好,但是由於中間裝置可能會過濾掉 PTB 資料包造成這樣的通知傳送方收不到影響正常傳輸,因此傳送方最好在開始的時候就不要傳送過大的資料包,目前一個建議參考值 MTU 是1280位元組。

未結束的結束語

IPv6 的序幕剛剛拉開,這篇文章也僅是粗淺的初步分析,拋磚引玉。隨著時間的推移,文中的一些舉例也可能隨著網路演進或者策略更改而變化,所以若有不對的地方還請見諒,希望在後面的過程中能夠積累沉澱出更多的實踐和思考,提升 IPv6 下的業務體驗。

 


本文作者:南書

原文連結

本文來自雲棲社群合作伙伴“阿里技術”,如需轉載