眾所周知,32 位的 IPv4 地址已經耗竭,IPv6 採用 128 位的地址長度擁有更大的地址空間。首先我們先來認識一下 IPv6 到底長成什麼樣子。
初識 IPv6上圖是我們最熟悉的 ping 的 IPv6 版本 ICMP v6。可以看到,IPv6 數據報文和IPv4 有很大的差別:
1、數據鏈路層(L2)的 type欄位標識為 0x86dd,表示承載的上層協議是 IPv6
IPv4 對比:type欄位為 0x0800
2、IPv6 的頭部欄位,和 IPv4 差別巨大(可以猜測到,IPv6 和 IPv4無法兼容)
IPv6 的報文頭部格式如下:
IPv6 報文頭部更精簡了,欄位更少了,對比起 IPv4,有以下幾個地方值得注意:
一、IPv6 報文頭部是定長(固定為 40位元組),IPv4 報文頭部是變長的。這個意味著,寫代碼處理 IPv6 數據報文的效率會提高很多:)
二、IPv6 中 Hop Limit 欄位含義類似 IPv4 的 TTL。
三、IPv6 中 的 Traffic Class 欄位含義類似 IPv4 中的 TOS(Type Of Service)。
四、IPv6 的報文頭部取消了校驗和欄位。取消這個欄位也是對 IPv4 協議的一個改進。當 IPv4 報文在網路間傳輸,每經過一個路由器轉發就是修改 TTL欄位,就需要重新計算校驗和,而由於數據鏈路層 L2 和傳輸層 L4 的校驗已經足夠強壯,因此 IPv6 取消這個欄位會提高路由器的轉發效率。值得一提的是,在 IPv6 協議下,傳輸層 L4 協議 UDP、TCP 是強制需要進行校驗和的(IPv4是可選的)。
五、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 分片報文來看看。
當發送一個分片 IPv6 數據報文的時候,IPv6 使用的是擴展頭部的形式組織各個分片的信息,如圖 IPv6 報文頭部 Next Header 欄位值為 44 表示存在擴展頭部,擴展頭部是 IPv6 分片數據信息。
對比 IPv4,分片信息是記錄在 IPv4 報文頭部的分片欄位中。
IPv6 的擴展頭部類型有很多種,除了上述的分片頭部,還有路由頭部、逐跳可選頭部等,具體的可以參考 RFC 2460。
IPv6 的地址語法一個 IPv6 的地址使用冒號十六進位表示方法:128 位的地址每 16 位分成一段,每個 16 位的段用十六進位表示並用冒號分隔開,例如:
一個普通公網IPv6地址: 2001:0D12:0000:0000:02AA:0987:FE29:9871
IPv6 地址支持壓縮前導零的表示方法,例如上面的地址可以壓縮表示為:
2001:D12:0:0:2AA:987:FE29:9871
為了進一步精簡 IPv6 地址,當冒號十六進位格式中出現連續幾段數值 0 的位段時,這些段可以壓縮為雙冒號的表示,例如上面的地址還可以進一步精簡表示為:
2001:D12::2AA:987:FE29:9871 又例如 IPv6 的地址:
FF80:0:0:0:FF:3BA:891:67C2 可以進一步精簡表示為:
FE80::FF:3BA:891:67C2 。
這裡值得注意的是,雙冒號只能出現一次。
IPv6 地址的號段劃分和前綴表示法IPv6 擁有 128 位巨大的地址空間,對於那麼大的空間,也不是隨意的劃分,而是使用按照 bit 位進行號段劃分。
IPv6 的地址結構如下圖:
例如:RFC 4291中定義了 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 可以由各作業系統實現生成。
IPv6的地址類型IPv6地址分三種類型
1、單播,對應於 IPv4 的普通公網和私網地址
2、組播,對應於 IPv4 的組播(多播)地址
3、任播,IPv6 新增的地址概念類型
IPv6 沒有廣播地址,用組播地址實現廣播的功能。實際上我們工作和生活最可能最多接觸的就是單播地址,接下來本文重點會講解單播地址的種類。組播和任播地址有興趣的同學自行查閱相關 RFC 和文獻。
IPv6 單播地址注意,大家如果在網上搜索 IPv6 的地址,可能都是千篇一律的把所有「出現過」的單播地址介紹出來,其實有一些單播地址類型已經在相關的 RFC 中被廢除或者不建議使用,而本節會指出這類地址。同時,在介紹單播地址的時候,儘量與 IPv4 中對應的或者相類似的概念做對比,加深理解。
IPv6 單播地址有以下幾種:
1、全球單播地址
前綴 2000::/3,相當於 IPv4 的公網地址( IPv6 的誕生根本上就是為了解決 IPv4 公網地址耗盡的問題)。這種地址在全球的路由器間可以路由。
2、鏈路本地地址
前綴 FE80::/10,顧名思義,此類地址用於同一鏈路上的節點間的通信,主要用於自動配置地址和鄰居節點發現過程。Windows 和 Linux 支持或開啟IPv6 後,默認會給網卡接口自動配置一個鏈路本地地址。也就是說,一個接口一定有一個鏈路本地地址。如下圖:
值得說的是,每個接口必須至少有一個鏈路本地地址;每個接口可以配置1 個以上的單播地址,例如一個接口可以配置一個鏈路本地地址,同時也可以配置一個全球單播地址。
注意,很容易會把鏈路本地地址和 IPv4 的私網/內網地址對應起來,其實鏈路本地地址對應於 IPv4 的 APIPA 地址,也就是 169.254 開頭的地址(典型場景就是 Windows 開啟自動獲取地址而獲取失敗後自動分配一個 169.254 的地址)。而 IPv4 私網對應於 IPv6 的什麼地址,在後面會介紹。
3、唯一本地地址
前綴 FC00::/7,相當於 IPv4 的私網地址(10.0.0.0、172.16.0.0、192.168.0.0),在 RFC 4193中新定義的一種解決私網需求的單播地址類型,用來代替廢棄使用的站點本地地址。
可能看到這裡,有同學會跳出來說:IPv6 不是為了解決 IPv4 地址耗盡的問題嗎,既然 IPv6 的地址空間那麼大,可以為每一個網絡節點分配公網 IPv6 的節點,那為什麼 IPv6 還需要支持私網?這裡需要談談對 IPv6 下私網支持的認識。
在 IPv4 中,利用 NAT 技術私網內的網絡節點可以使用統一的公網出口訪問網際網路資源,大大節省了 IPv4 公網地址的消耗(IPv6 推進緩慢的原因之一)。另一方面,由於默認情況下私網內節點與外界通信的發起是單向的,網絡訪問僅僅能從私網內發起,外部發起的請求會被統一網關或者防火牆阻隔掉,這樣的網絡架構很好的保護了私網內的節點安全性和私密性。可以設想一下,如果內部每臺辦公電腦都配置了 IPv6 的公網地址上網,是多麼可怕的事情,每臺辦公電腦都會面臨被黑客入侵的威脅。
因此,在安全性和私密性要求下,IPv6 中同樣需要支持私網,並且也需要支持 NAT。在 Linux 內核 3.7 版本開始加入對 IPv6 NAT 的支持,實現的方式和 IPv4 下的差別不大。
4、站點本地地址
前綴 FEC9::/48,以前是用來部署私網的,但 RFC 3879中已經不建議使用這類地址,建議使用唯一本地地址。大家知道有這麼一回事就可以了。網上還有很多文章還提到這種地址,但是沒有說明這種地址已經不再使用。
5、特殊地址:迴環地址
0:0:0:0:0:0:0:1或::1,等同於 IPv4 的127.0.0.1。
6、過渡地址:內嵌 IPv4 地址的 IPv6 地址
就是在 IPv6 的某一些十六進位段內嵌這IPv4的地址,例如 IPv6 地址中64:ff9b::10.10.10.10,此 IPv6 地址最後4個字節內嵌一個 IPv4 的地址,這類地址主要用於 IPv6/IPv4 的過渡技術中。
0:0:0:0:0:0:w.x.y.z 或 ::w.x.y.z(其中 w.x.y.z是點分十進位的 IPv4 地址)。但在 RFC 4291中已經不推薦使用這類地址,大家知道有這麼一回事就可以了。
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 地址主要用於對應的過渡技術的地址。
IPv6 接口 ID 生成算法從前面的介紹中可以看出,IPv6 單播地址是由前綴(64位)+接口 ID(64位)組成。接口 ID 的生成算法主要有以下幾種:
1、根據 RFC4291定義,接口 ID可以從 EUI-64 地址生成。
2、為了可以具備某種程度的匿名性,接口 ID 可以使用一個隨機分配的,Windows 作業系統默認就是使用這種生成算法,Linux 下也是默認開啟這個算法。
3、使用狀態化的自動配置技術分配,例如 DHCPv6分配。
4、手工配置。
IPv6 地址配置前面對 IPv6 的地址、前綴、接口等等做了介紹,接下來就是要介紹一個接口如何配置 IPv6 地址。IPv6 一個比 IPv4 更厲害的方面,就是可以自動配置地址,甚至這個配置過程不需要 DHCP v6(在 IPv4 中是 DHCP v4)這樣的地址配置協議。最典型的例子就是,只要開啟了 IPv6 協議棧的作業系統,每個接口就能自動配置了鏈路本地地址,這個是和 IPv4 最重要的區別之一。
IPv6 的地址配置有以下幾種:
1、只要開啟了 IPv6 協議棧,接口自動分配鏈路本地地址。
2、無狀態自動配置地址。
3、有狀態自動配置地址,例如 DHCPv6。
4、手動配置。
IPv6 的域名解析由於 IPv6 的地址擴展為 128位,比 IPv4 的更難書寫和記憶,因此 IPv6 下的 DNS 變得尤為重要。IPv6 的的DNS資源記錄類型為 AAAA(又稱作4A),用於解析指向 IPv6 地址的完全有效域名。下面是一個示例:
Hostipv6.example.com IN AAAA 2001:db8:1::1IPv6 下的域名解析可以認為是 IPv4 的擴展,詳細可以查看 RFC3596。
啟用和配置 IPv6
當前大部分作業系統和硬體都比較好地支持 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。
Android 也已經支持 IPv6(但是不支持 DHCP v6)。
下面我們主要以 Linux 系統為例來講解下如何啟用和配置 IPv6。
IPv6 啟用和關閉
雖然 Linux 系統 從 2.6 內核開始就已經支持 IPv6, 但是默認並沒有啟用。如果你需要使用 IPv6,你就必須在作業系統中啟用它。
1. 檢查當前運行的內核是否支持 IPv6
$ test -f /proc/net/if_inet6 && echo "IPv6 supported" || echo "IPv6 not supported"如果輸出 IPv6 not supported,就需要先加載 IPv6 模塊。
2. 加載 IPv6 內核模塊
2.1 手動加載 IPv6 內核模塊2.2 開機自動加載 IPv6 內核模塊
如果需要開機自動加載 IPv6 內核模塊, 你只需在內核模塊加載的配置文件中添加以下行。
$ vim /etc/modprobe.d/ipv6.confalias net-pf-10 ipv6options ipv6 disable=0如果是 Centos 6 以下的系統,配置文件在 /etc/modprobe.conf。2.3 驗證模塊是否加載成功
$ lsmod |grep -w 'ipv6' && echo "IPv6 module successfully loaded"如果輸出結果中列出模塊,則說明 IPv6 模塊已經正常加載。
3. 開啟內核參數支持 IPv6
編輯內核參數配置文件,修改以下幾項參數的值。
$ vim /etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6 = 0net.ipv6.conf.default.disable_ipv6 = 0net.ipv6.conf.lo.disable_ipv6 = 0修改完成後運行以下命令讓配置生效。
檢查內核中 IPv6 相關參數是否生效,若參數值全部為 0,則說明 IPv6 已經全部支持。
$ sysctl -a | grep ipv6 | grep disablenet.ipv6.conf.all.disable_ipv6 = 0net.ipv6.conf.default.disable_ipv6 = 0net.ipv6.conf.lo.disable_ipv6 = 0net.ipv6.conf.eth0.disable_ipv6 = 0net.ipv6.conf.eth1.disable_ipv6 = 0net.ipv6.conf.sit0.disable_ipv6 = 0編輯 /etc/modprobe.d/ipv6.conf,在文檔中加入如下的內容:
$ vim /etc/modprobe.d/ipv6.confalias net-pf-10 offalias ipv6 offoptions ipv6 disable=1保存退出,並且重新啟動系統。
在網卡上配置 IPv6 地址
按以上配置啟用 IPv6 完成之後,就可以修改伺服器的網絡配置文件來寫入 IPv6 地址。
編輯 /etc/sysconfig/network-scripts/ifcfg-eth0 文件,設置如下幾項。
$ vi /etc/sysconfig/network-scripts/ifcfg-eth0
IPV6INIT=yesIPV6ADDR=2001:470:18:ac4::2/64IPV6_DEFAULTGW=2001:470:19:ac4::/64編輯 /etc/sysconfig/network 文件,設置如下幾項。
$ vi /etc/sysconfig/networkNETWORKING_IPV6=yesIPV6_AUTOCONF=no以上配置文件修改完成之後,保存退出。然後運行以下命令使其生效。
$ service network restart 或者$ systemctl restart network.service編輯 /etc/network/interfaces 文件,將下面的內容添加到文件中。
$ vim /etc/network/interfacesiface eth0 inet6 static address YOUR_PUBLIC_IPV6_ADDRESS netmask 64 gateway YOUR_PUBLIC_PIV6_GATEWAY autoconf 0 dns-nameservers 2001:4860:4860::8844 2001:4860:4860::8888 209.244.0.3注意:上面的 YOUR_PUBLIC_IPV6_ADDRESS 最後沒有 /64。
以上配置文件修改完成之後,保存退出。然後運行以下命令使其生效。
$ service network restart 或者$ /etc/init.d/networking restart$ ifconfig eth1 inet6 add 2001:470:18:ac4::2/64 $ route -A inet6 add default gw 2001:470:19:ac4::/64 dev eth1配置完後,可以使用 ping6 命令進行測試,例如:ping 谷歌的 IPv6 地址來測試伺服器能否連接 IPv6 公網。
也可以使用瀏覽器訪問一些專用的測試工具進行測試。
https://test-ipv6.com/
http://ipv6-test.com/validate.php
IPv6 相關網絡工具
http://ip6.me/
DNS 解析工具,用於查看一個域名是否具有 AAAA 記錄。
圖10 Dig 獲取域名的 AAAA 記錄
通過 IPv6 網絡協議進行請求響應,獲取服務端數據。
圖11 Curl 通過 IPv6 獲取接口數據
查看 IPv6 網絡的連通性和域名解析的正確性。
圖12 Ping6 測試 IPv6 網絡連通性
查看對應 IPv6 地址埠是否開放。
圖13 Telnet 查看埠可用性
IPv6 網絡連通性判斷工具。
圖14 Mtr 查看 IPv6 網絡連通性
IPv6 網絡測試、評估和管理工具。
圖15 Traceroute6 查看 IPv6 路由節點情況
查看本機 IPv6 路由表。
圖16 查看本機 IPv6 路由表
申請並啟用 IPv6 隧道
由於國內大多數運營商網絡環境還沒有支持 IPv6,如果需要在沒有 IPv6 公網地址的伺服器上啟用 IPv6 地址並對外進行提供服務。 目前你可以使用 HE.Net 提供的免費 IPv6 隧道來獲取一個公網地址後就可以接入 IPv6 公網了。
HE.Net 的隧道是 6in4 隧道,即通過的你伺服器公網 IPv4 地址與 HE.Net 的公網 IPv4 地址建立一個隧道,然後給這個隧道配置 IPv6 公網地址,網關指向 HE.Net 就可以通過 IPv6 連接公網了。
6in4 是一種 IPv6 轉換傳送機制,是將 IPv6 的數據包直接封裝在 IPv4 數據包中,通過 IPv4 鏈路一條明確配置的隧道中進行傳送。6in4 隧道又被稱為 「proto-41 static」,因為隧道端點是需要手動配置的。雖然如此,但也可以使用 AICCU 通過隧道信息與控制協議伺服器通信獲得配置信息來自動配置。
相對於 6in4,6to4 是將終端的 IPv4 地址嵌入到其 IPv6 地址,代替使用手工配置隧道終端信息,從而實現自動傳輸。而 6over4 則將 IPv4 基礎網絡視為數據鏈路層,通過特定的多播地址在 IPv4 網絡進行多播來傳輸。ISATAP 也同樣使用相同的協議號和封裝方法來封裝數據包。
其網絡拓撲大致如下:
圖17 6in4 IPv6 隧道拓撲
1. 申請 IPv6 通道HE.Net 提供的免費 IPv6 隧道申請地址是 https://tunnelbroker.net/,你大致需要如下幾步就完成相應的申請和配置
1. 註冊帳號。
2. 郵箱激活。
3. 登錄。
4. 點擊 「Create Regular Tunnel」 連結來創新一個新的隧道。
5. 輸入你的伺服器的 IPv4 公網地址,並創建一個新的隧道。
6. 新的隧道創建完成後,在 「Example Configurations」 處根據你的實際情況選擇對應作業系統,獲取相應配置。
7. 將對應配置參數配置到你的作業系統上。
8. 配置成功後,你便可通過 IPv6 訪問對應的服務。
具體的操作步驟你可以參考以下幾篇文章:
使用 HE 的 6in4 隧道來訪問 IPv6
https://ekszz.com/blog/?p=20阿里雲ECS(CentOS 7)啟用 IPv6
http://t.cn/Ex6dqrr阿里雲 Centos 7 配置 HE 隧道支持 IPv6 訪問
https://www.duoluodeyu.com/2479.html阿里雲 Ubuntu 支持 IPv6 的完整步驟
https://jiandanxinli.github.io/2016-08-06.html如何把伺服器免費接入 IPv6?
https://zhuanlan.zhihu.com/p/33984430
2. 局限性
Miredo 是一個網絡工具,主要用於 BSD 和 Linux 的 IPV6 Teredo 隧道連結,可以轉換不支持 IPV6 的網絡連接 IPV6,內核中需要有 IPV6 和 TUN 隧道支持。維基百科,https://zh.wikipedia.org/wiki/Miredo
參考文檔
https://www.google.comhttp://t.cn/RmdLf6P
http://t.cn/Exc67UW
http://t.cn/ExcapDp
http://t.cn/Excjbyuhttp://t.cn/ExcnDbp
今日思想佛教中有一句話:初學者的心態;擁有初學者的心態是件了不起的事情。
—— 賈伯斯
推薦閱讀