Posted on 2018-05-18 15:14
Jack Jiang 閱讀(444)
評論(0) 編輯 收藏
本文來自微信技術架構部的原創技術分享。
1、前言
普及IPV6喊了多少年了,連蘋果的APP上架App Store也早已強制IPV6的支持,然并卵,因為歷史遺留問題,即使在IPV4地址如果饑荒的情況下,所謂的普及還是遙遙無期。但不可否認的是,IPV6肯定是未來趨勢,做為網絡通信領域的程序員來說,詳細學習和了解IPV6是很有必要的,所謂厚積薄發,誰知道哪天IPV6真的普及了呢?那么,我們開始看正文吧。
學習交流:
- 即時通訊開發交流3群:185926912[推薦]
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
(本文同步發布于:http://www.52im.net/thread-1605-1-1.html)2、系列文章
文章太長,分為兩篇來講,本文是2篇文章中的第1篇:本文是系列文章中的上篇,主要講解IPV6的基本概念。3、正文引言
2017年11月26日,中共中央辦公廳和國務院辦公廳印發了《推薦互聯網協議第六版(IPv6)規模部署行動計劃》,并發出通知,要求各地區各部門結合實際認真貫徹落實。這條新聞傳達了一個很重要的信息:這個是推進中國IPv6發展的戰略總動員令。本文將會從以下幾個方面進一步介紹IPv6,包括有:- 1)IPv6的基本概念;
- 2)IPv6在Linux操作系統下的實現;
- 3)IPv6的實驗;
- 4)IPv6的過渡技術介紹;
- 5)IPv6在Linux平臺下socket編程應該注意的問題;
- 6)實現簡易版TGW支持IPv6雛形demo。
值得說的是,目前我們接觸得比較多的主流操作系統內核,已經很好地支持IPv6協議棧,例如:- Windows: windows 7、windows 8.x、windows 10,默認開啟IPv6;
- Linux: 內核2.6.x、內核3.x、內核4.x 已經支持IPv6(需要手動開啟);
- iOS:IOS9開始已經支持IPv6 Only,2016年蘋果已經強制要求app必須支持IPv6。
本系列文章提到的IPv6節點,沒有特殊說明,一般指的是純IPv6節點(IPv6 Only),也就是只支持IPv6協議棧。IPv4節點,是指純IPv4的節點,也就是只支持IPv4協議棧。如果節點支持IPv6和IPv4雙棧,會指明是雙棧節點。本文是系列文章中的上篇,主要講解IPV6的基本概念
,其它內容將在下篇《IPv6技術詳解:基本概念、應用現狀、技術實踐(下篇)》中詳細講解。眾所周知,32位的IPv4地址已經耗竭,IPv6采用128位的地址長度擁有更大的地址空間。首先我們先來認識一下IPv6到底長成什么樣子。4、初識IPv6
▲ 圖1:IPv6數據報文
上圖是我們最熟悉的ping的IPv6版本ICMPv6,可以看到,IPv6數據報文和IPv4有很大的差別:- 1)數據鏈路層(L2)的type字段標識為 0x86dd,表示承載的上層協議是IPv6(IPv4對比:type字段為0x0800);
- 2)IPv6的頭部字段,和IPv4差別巨大(可以猜測到,IPv6和IPv4無法兼容)。
IPv6的報文頭部格式如下:
▲ 圖2:IPv6報文頭部
IPv6報文頭部更精簡了,字段更少了,對比起IPv4,有以下幾個地方值得注意:- 1)IPv6報文頭部是定長(固定為40字節),IPv4報文頭部是變長的。這個意味著,寫代碼處理IPv6數據報文的效率會提高很多:);
- 2)IPv6中Hop Limit字段含義類似IPv4的TTL;
- 3)IPv6中的Traffic Class字段含義類似IPv4中的TOS(Type Of Service);
- 4)IPv6的報文頭部取消了校驗和字段:取消這個字段也是對IPv4協議的一個改進。當IPv4報文在網路間傳輸,每經過一個路由器轉發就是修改TTL字段,就需要重新計算校驗和,而由于數據鏈路層L2和傳輸層L4的校驗已經足夠強壯,因此IPv6取消這個字段會提高路由器的轉發效率。值得一提的是,在IPv6協議下,傳輸層L4協議UDP、TCP是強制需要進行校驗和的(IPv4是可選的);
- 5)IPv6報文頭部中的Next Header字段表示“承載上一層的協議類型”或者“擴展頭部類型”。
這里的含義與IPv4有很大的差別,需要加以解釋:- 當IPv6數據報文承載的是上層協議ICMPv6、TCP、UDP等的時候,Next Header的值分別為58、6、17,這個時候和IPv4報文頭部中的Protocol字段很類似;
- 當不是以上3種協議類型的時候,IPv6報文頭部緊接的是擴展頭部。擴展頭部是IPv6引入的一個新的概念,每個IPv6的數據報文可以承載0個或多個擴展頭部,擴展頭部通過鏈表的形式組織起來。當IPv6數據報文承載著擴展頭部的時候,Next Header的數值為擴展頭部的類型值。
為什么要引入擴展頭部這個概念,這里也是IPv6對IPv4改進的一個方面,用擴展頭部取代了IPv4的可選項信息,精簡了IPv6的頭部,增強了IPv6的擴展性。有同學會不會有疑問,IPv6的分片數據報文怎么處理?其實就是使用了IPv6擴展頭部。我們來抓一個UDP分片報文來看看。
▲ 圖3:IPv6分片報文
當發送一個分片IPv6數據報文的時候,IPv6使用的是擴展頭部的形式組織各個分片的信息,如圖IPv6報文頭部Next Header字段值為44表示存在擴展頭部,擴展頭部是IPv6分片數據信息。對比IPv4,分片信息是記錄在IPv4報文頭部的分片字段中。IPv6的擴展頭部類型有很多種,除了上述的分片頭部,還有路由頭部、逐跳可選頭部等,具體的可以參考RFC2460。本章主要介紹了IPv6的一些很直觀的認識,下面逐漸介紹IPv6上的基本知識和概念。5、IPv6的地址語法
一個IPv6的地址使用冒號十六進制表示方法:128位的地址每16位分成一段,每個16位的段用十六進制表示并用冒號分隔開,例如:一個普通公網IPv6地址:2001:0D12:0000:0000:02AA:0987:FE29:9871IPv6地址支持壓縮前導零的表示方法,例如上面的地址可以壓縮表示為:2001
12:0:0:2AA:987:FE29:9871為了進一步精簡IPv6地址,當冒號十六進制格式中出現連續幾段數值0的位段時,這些段可以壓縮為雙冒號的表示,例如上面的地址還可以進一步精簡表示為:[pquote]2001
12::2AA:987:FE29:9871又例如IPv6的地址FF80:0:0:0:FF:3BA:891:67C2可以進一步精簡表示為: FE80::FF:3BA:891:67C2這里值得注意的是:雙冒號只能出現一次
。6、IPv6地址的號段劃分和前綴表示法
IPv6擁有128位巨大的地址空間,對于那么大的空間,也不是隨意的劃分,而是使用按照bit位進行號段劃分(與鵝廠內部一些的64位uin改造放號的zone劃分算法)。IPv6的地址結構如下圖:
▲ 圖4:IPv6地址結構
例如RFC4291中定義了n=48, m=16,也就是子網和接口ID與各占64位。IPv6支持子網前綴標識方法,類似于IPv4的無分類域間路由CIDR機制(注意:IPv6沒有子網掩碼mask的概念
)。使用“IPv6地址/前綴長度”表示方法,例如:- 2001:C3:0:2C6A::/64表示一個子網;
- 而2001:C3:0:2C6A:C9B4:FF12:48BC:1A22/64表示該子網下的一個節點地址。
可以看到,一個IPv6的地址有子網前綴+接口ID構成,子網前綴由地址分配和管理機構定義和分配,而接口ID可以由各操作系統實現生成,生成算法后面的章節會介紹。7、IPv6的地址類型
IPv6地址分三種類型:- 1)單播,對應于IPv4的普通公網和私網地址;
- 2)組播,對應于IPv4的組播(多播)地址;
- 3)任播,IPv6新增的地址概念類型。
IPv6沒有廣播地址,用組播地址實現廣播的功能。實際上我們工作和生活最可能最多接觸的就是單播地址,接下來本文重點會講解單播地址的種類。組播和任播地址有興趣的同學自行查閱相關RFC和文獻。8、IPv6單播地址
注意:大家如果在網上搜索IPv6的地址,可能都是千篇一律的把所有“出現過”的單播地址介紹出來,其實有一些單播地址類型已經在相關的RFC中被廢除或者不建議使用,而本節會指出這類地址
。同時,在介紹單播地址的時候,盡量與IPv4中對應的或者相類似的概念做對比,加深理解。IPv6單播地址有以下幾種。8.1全球單播地址

▲ 圖5:IPv6全球單播地址結構
前綴2000::/3,相當于IPv4的公網地址(IPv6的誕生根本上就是為了解決IPv4公網地址耗盡的問題)。這種地址在全球的路由器間可以路由。8.2鏈路本地地址

▲ 圖6:鏈路本地地址結構
前綴FE80::/10,顧名思義,此類地址用于同一鏈路上的節點間的通信,主要用于自動配置地址和鄰居節點發現過程。Windows和Linux支持或開啟IPv6后,默認會給網卡接口自動配置一個鏈路本地地址。也就是說,一個接口一定有一個鏈路本地地址。如下圖:
▲ 圖7:Linux下查看鏈路本地地址
▲ 圖8:Windows下查看鏈路本地地址
值得說的是:每個接口必須至少有一個鏈路本地地址;每個接口可以配置1個以上的單播地址,例如一個接口可以配置一個鏈路本地地址,同時也可以配置一個全球單播地址。注意:很容易會把鏈路本地地址和IPv4的私網/內網地址對應起來,其實鏈路本地地址對應于IPv4的APIPA地址,也就是169.254開頭的地址(典型場景就是windows開啟自動獲取地址而獲取失敗后自動分配一個169.254的地址)。而IPv4私網對應于IPv6的什么地址,后面會介紹。特別地:在IPv6 socket編程中,可以使用鏈路本地地址編程通信,但是需要增加一些額外的參數(這是一個小坑),在后面介紹編程的章節會介紹。8.3唯一本地地址

▲ 圖9:唯一本地地址結構
前綴FC00::/7,相當于IPv4的私網地址(10.0.0.0、172.16.0.0、192.168.0.0),在RFC4193中新定義的一種解決私網需求的單播地址類型,用來代替廢棄使用的站點本地地址。可能看到這里,有同學會跳出來說:IPv6不是為了解決IPv4地址耗盡的問題嗎,既然IPv6的地址空間那么大,可以為每一個網絡節點分配公網IPv6的節點,那為什么IPv6還需要支持私網?這里需要談談對IPv6下私網支持的認識。在IPv4中,利用NAT技術私網內的網絡節點可以使用統一的公網出口訪問互聯網資源,大大節省了IPv4公網地址的消耗(IPv6推進緩慢的原因之一)。另一方面,由于默認情況下私網內節點與外界通信的發起是單向的,網絡訪問僅僅能從私網內發起,外部發起的請求會被統一網關或者防火墻阻隔掉,這樣的網絡架構很好的保護了私網內的節點安全性和私密性。可以設想一下,如果鵝廠內部每臺辦公電腦都配置了IPv6的公網地址上網,是多么可怕的事情,每臺辦公電腦都會面臨被黑客入侵的威脅(肉雞真多)。因此,在安全性和私密性要求下,IPv6中同樣需要支持私網,并且也需要支持NAT
。在Linux內核3.7版本開始加入對IPv6 NAT的支持,實現的方式和IPv4下的差別不大(Linux內核代碼中變量和函數的命名幾乎就是ctrl+c和ctrl+v過來的-_-||)。8.4站點本地地址
前綴FEC9::/48,以前是用來部署私網的,但RFC3879中已經不建議使用這類地址,建議使用唯一本地地址。大家知道有這么一回事就可以了。網上還有很多文章還提到這種地址,但是沒有說明這種地址已經不再使用。8.5特殊地址:回環地址
0:0:0:0:0:0:0:1或::1,等同于IPv4的127.0.0.18.6過渡地址:內嵌IPv4地址的IPv6地址
就是在IPv6的某一些十六進制段內嵌這IPv4的地址,例如IPv6地址中64:ff9b::10.10.10.10,此IPv6地址最后4個字節內嵌一個IPv4的地址,這類地址主要用于IPv6/IPv4的過渡技術中。9、IPv4兼容地址
0:0:0:0:0:0:w.x.y.z或::w.x.y.z(其中w.x.y.z是點分十進制的IPv4地址)。但在RFC4291中已經不推薦使用這類地址,大家知道有這么一回事就可以了。過渡地址:IPv4映射地址0:0:0:0:0:FFFF:w.x.y.z或::FFFF:w.x.y.z(其中w.x.y.z是點分十進制的IPv4地址),用于IPv6地址表示IPv4地址。主要用于某些場景下IPv6節點與IPv4節點通信,Linux內核對這類地址很好地支持,在后面編程和內核分析的章節會分析使用過程。過渡地址:特定過渡技術地址6to4地址、ISATAP地址、Teredo地址主要用于對應的過渡技術的地址,在后面介紹過渡技術的時候會介紹。10、IPv6接口ID生成算法
從前面的介紹中可以看出,IPv6單播地址是由前綴(64位)+接口ID(64位)組成。接口ID的生成算法主要有以下幾種:- 1)根據RFC4291定義,接口ID可以從EUI-64地址生成:詳細算法可以查看regli同學的PPT第14頁;
- 2)為了可以具備某種程度的匿名信,接口ID可以使用一個隨機分配的,windows操作系統默認就是使用這種生成算法,Linux下也是默認開啟這個算法;
- 3)使用狀態化的自動配置技術分配,例如DHCPv6分配;
- 4)手工配置。
11、IPv6地址配置
前面對IPv6的地址、前綴、接口等等做了介紹,接下來就是要介紹一個接口如何配置IPv6地址。IPv6一個比IPv4更厲害的方面,就是可以自動配置地址,甚至這個配置過程不需要DHCPv6(在IPv4中是DHCPv4)這樣的地址配置協議。最典型的例子就是,只要開啟了IPv6協議棧的操作系統,每個接口就能自動配置了鏈路本地地址,這個是和IPv4最重要的區別之一。IPv6的地址配置有以下幾種:- 1)只要開啟了IPv6協議棧,接口自動分配鏈路本地地址;
- 2)無狀態自動配置地址(RFC2462),后面會有實驗演示;
- 3)有狀態自動配置地址,例如DHCPv6。
- 4)手動配置。
12、IPv6的域名解析
由于IPv6的地址擴展為128位,比IPv4的更難書寫和記憶,因此IPv6下的DNS變得尤為重要。IPv6的的DNS資源記錄類型為AAAA(又稱作4A),用于解析指向IPv6地址的完全有效域名。下面是一個示例:Hostipv6.example.wechat.com IN AAAA 2001:db8:1::1IPv6下的域名解析可以認為是IPv4的擴展,詳細可以查看RFC3596.(—— 本文未完,下篇待續 ——)附錄:更多相關文章
[1] 更多網絡編程基礎資料:《TCP/IP詳解 - 第11章·UDP:用戶數據報協議》《TCP/IP詳解 - 第17章·TCP:傳輸控制協議》《TCP/IP詳解 - 第18章·TCP連接的建立與終止》《TCP/IP詳解 - 第21章·TCP的超時與重傳》《技術往事:改變世界的TCP/IP協議(珍貴多圖、手機慎點)》《通俗易懂-深入理解TCP協議(上):理論基礎》《通俗易懂-深入理解TCP協議(下):RTT、滑動窗口、擁塞處理》《理論經典:TCP協議的3次握手與4次揮手過程詳解》《理論聯系實際:Wireshark抓包分析TCP 3次握手、4次揮手過程》《計算機網絡通訊協議關系圖(中文珍藏版)》《UDP中一個包的大小最大能多大?》《P2P技術詳解(一):NAT詳解——詳細原理、P2P簡介》《P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解》《P2P技術詳解(三):P2P技術之STUN、TURN、ICE詳解》《通俗易懂:快速理解P2P技術中的NAT穿透原理》《高性能網絡編程(一):單臺服務器并發TCP連接數到底可以有多少》《高性能網絡編程(二):上一個10年,著名的C10K并發連接問題》《高性能網絡編程(三):下一個10年,是時候考慮C10M并發問題了》《高性能網絡編程(四):從C10K到C10M高性能網絡應用的理論探索》《不為人知的網絡編程(一):淺析TCP協議中的疑難雜癥(上篇)》《不為人知的網絡編程(二):淺析TCP協議中的疑難雜癥(下篇)》《不為人知的網絡編程(三):關閉TCP連接時為什么會TIME_WAIT、CLOSE_WAIT》《不為人知的網絡編程(四):深入研究分析TCP的異常關閉》《不為人知的網絡編程(五):UDP的連接性和負載均衡》《不為人知的網絡編程(六):深入地理解UDP協議并用好它》《不為人知的網絡編程(七):如何讓不可靠的UDP變的可靠?》《網絡編程懶人入門(一):快速理解網絡通信協議(上篇)》《網絡編程懶人入門(二):快速理解網絡通信協議(下篇)》《網絡編程懶人入門(三):快速理解TCP協議一篇就夠》《網絡編程懶人入門(四):快速理解TCP和UDP的差異》《網絡編程懶人入門(五):快速理解為什么說UDP有時比TCP更有優勢》《技術掃盲:新一代基于UDP的低延時網絡傳輸層協議——QUIC詳解》《讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享》《現代移動端網絡短連接的優化手段總結:請求速度、弱網適應、安全保障》《聊聊iOS中網絡編程長連接的那些事》《移動端IM開發者必讀(一):通俗易懂,理解移動網絡的“弱”和“慢”》《移動端IM開發者必讀(二):史上最全移動弱網絡優化方法總結》《IPv6技術詳解:基本概念、應用現狀、技術實踐(上篇)》>> 更多同類文章 ……[2] QQ、微信團隊分享的其它技術文章:《微信朋友圈千億訪問量背后的技術挑戰和實踐總結》《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(圖片壓縮篇)》《騰訊技術分享:騰訊是如何大幅降低帶寬和網絡流量的(音視頻技術篇)》《微信團隊分享:微信移動端的全文檢索多音字問題解決方案》《騰訊技術分享:Android版手機QQ的緩存監控與優化實踐》《微信團隊分享:iOS版微信的高性能通用key-value組件技術實踐》《微信團隊分享:iOS版微信是如何防止特殊字符導致的炸群、APP崩潰的?》《騰訊技術分享:Android手Q的線程死鎖監控系統技術實踐》《微信團隊原創分享:iOS版微信的內存監控系統技術實踐》《讓互聯網更快:新一代QUIC協議在騰訊的技術實踐分享》《iOS后臺喚醒實戰:微信收款到賬語音提醒技術總結》《騰訊技術分享:社交網絡圖片的帶寬壓縮技術演進之路》《微信團隊分享:視頻圖像的超分辨率技術原理和應用場景》《微信團隊分享:微信每日億次實時音視頻聊天背后的技術解密》《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(上篇)》《QQ音樂團隊分享:Android中的圖片壓縮技術詳解(下篇)》《騰訊團隊分享:手機QQ中的人臉識別酷炫動畫效果實現詳解》《騰訊團隊分享 :一次手Q聊天界面中圖片顯示bug的追蹤過程分享》《微信團隊分享:微信Android版小視頻編碼填過的那些坑》 《微信手機端的本地數據全文檢索優化之路》 《企業微信客戶端中組織架構數據的同步更新方案優化實戰》《微信團隊披露:微信界面卡死超級bug“15。。。。”的來龍去脈》《QQ 18年:解密8億月活的QQ后臺服務接口隔離技術》《月活8.89億的超級IM微信是如何進行Android端兼容測試的》《以手機QQ為例探討移動端IM中的“輕應用”》《一篇文章get微信開源移動端數據庫組件WCDB的一切!》《微信客戶端團隊負責人技術訪談:如何著手客戶端性能監控和優化》《微信后臺基于時間序的海量數據冷熱分級架構設計實踐》《微信團隊原創分享:Android版微信的臃腫之困與模塊化實踐之路》《微信后臺團隊:微信后臺異步消息隊列的優化升級實踐分享》《微信團隊原創分享:微信客戶端SQLite數據庫損壞修復實踐》 《騰訊原創分享(一):如何大幅提升移動網絡下手機QQ的圖片傳輸速度和成功率》 《騰訊原創分享(二):如何大幅壓縮移動網絡下APP的流量消耗(下篇)》 《騰訊原創分享(三):如何大幅壓縮移動網絡下APP的流量消耗(上篇)》 《微信Mars:微信內部正在使用的網絡層封裝庫,即將開源》 《如約而至:微信自用的移動端IM網絡層跨平臺組件庫Mars已正式開源》 《開源libco庫:單機千萬連接、支撐微信8億用戶的后臺框架基石 [源碼下載]》 《微信新一代通信安全解決方案:基于TLS1.3的MMTLS詳解》 《微信團隊原創分享:Android版微信后臺保活實戰分享(進程保活篇)》 《微信團隊原創分享:Android版微信后臺保活實戰分享(網絡保活篇)》 《Android版微信從300KB到30MB的技術演進(PPT講稿) [附件下載]》 《微信團隊原創分享:Android版微信從300KB到30MB的技術演進》 《微信技術總監談架構:微信之道——大道至簡(演講全文)》《微信技術總監談架構:微信之道——大道至簡(PPT講稿) [附件下載]》 《如何解讀《微信技術總監談架構:微信之道——大道至簡》》《微信海量用戶背后的后臺系統存儲架構(視頻+PPT) [附件下載]》《微信異步化改造實踐:8億月活、單機千萬連接背后的后臺解決方案》 《微信朋友圈海量技術之道PPT [附件下載]》 《微信對網絡影響的技術試驗及分析(論文全文)》 《一份微信后臺技術架構的總結性筆記》 《架構之道:3個程序員成就微信朋友圈日均10億發布量[有視頻]》 《快速裂變:見證微信強大后臺架構從0到1的演進歷程(一)》《快速裂變:見證微信強大后臺架構從0到1的演進歷程(二)》 《微信團隊原創分享:Android內存泄漏監控和優化技巧總結》 《全面總結iOS版微信升級iOS9遇到的各種“坑”》 《微信團隊原創資源混淆工具:讓你的APK立減1M》 《微信團隊原創Android資源混淆工具:AndResGuard [有源碼]》 《Android版微信安裝包“減肥”實戰記錄》 《iOS版微信安裝包“減肥”實戰記錄》 《移動端IM實踐:iOS版微信界面卡頓監測方案》 《微信“紅包照片”背后的技術難題》 《移動端IM實踐:iOS版微信小視頻功能技術方案實錄》 《移動端IM實踐:Android版微信如何大幅提升交互性能(一)》《移動端IM實踐:Android版微信如何大幅提升交互性能(二)》《移動端IM實踐:實現Android版微信的智能心跳機制》 《移動端IM實踐:WhatsApp、Line、微信的心跳策略分析》 《移動端IM實踐:谷歌消息推送服務(GCM)研究(來自微信)》《移動端IM實踐:iOS版微信的多設備字體適配方案探討》 《信鴿團隊原創:一起走過 iOS10 上消息推送(APNS)的坑》《騰訊信鴿技術分享:百億級實時消息推送的實戰經驗》《IPv6技術詳解:基本概念、應用現狀、技術實踐(上篇)》>> 更多同類文章 ……
(本文同步發布于:http://www.52im.net/thread-1605-1-1.html)