一般Docker都是直接使用IPV4地址就行,但是一些特殊的鏡像就需要容器內(nèi)有IPV6地址用起來效果才好。像qt這些下載軟件。我不用這個,但是用adguardhome設(shè)置DNS服務(wù)器,所以要求ipv6能通。
當我們開通IPV6以后,一般客戶端會同時存在多個 IPv6 地址:
- Loopback 地址:
::1,等價于 IPv4 中的 127.0.0.1 - 鏈路本地地址(Link Local Address):
fe80::/10網(wǎng)段,只在區(qū)域中是合法地址,類似于 IPv4 中的 169.254.0.0/16。fe80開頭 不可路由,電腦自動生成 - 唯一區(qū)域地址(Unique Local Addresses):局域網(wǎng)地址,只能用于本地通信,和 IPv4 的專用網(wǎng)絡(luò)地址
10.0.0.0/8、172.16.0.0/12和192.168.0.0/16類似,在 RFC 4193 中定義。固定前綴是fc00::/7,分為fc00::/8和fd00::/8兩部分,fc00::/8目前作為保留地址沒有定義,fd00::/8是現(xiàn)在使用的 ULA 地址,其中 40bit 隨機生成以避免沖突,可以使用 ULA 生成工具 來生成。 - 全局地址(Global Address Type):通常意義上的公網(wǎng)地址,以 2XXX: 開頭。但 2002: 開頭的是特殊的 6to4 過渡地址,不是原生的純 IPv6 網(wǎng)路地址。電信的是240e開頭,聯(lián)通2408開頭,移動2409開頭
-
本地站點地址(Site Local Address):fec0::/10 網(wǎng)段,私網(wǎng)地址,目前在 RFC 規(guī)范中已被廢棄
image.png
1. IPV6地址獲取方式
在路由器中開啟ipv6時,會讓選擇獲取方式,不同系統(tǒng)獲取方式顯示的稍有不同。我這里了解到大約幾種,大家可以對照自己的看一下。
需要明確:無狀態(tài)和有狀態(tài),僅僅指的是IPv6地址的獲取方式。
1.1 SLAAC
SLAAC( Stateless Address Autoconfiguration,無狀態(tài)地址配置)是IPv6地址自動配置協(xié)議的一種,主要用于在網(wǎng)絡(luò)上進行IPv6地址的分配。
SLAAC是IPv6的內(nèi)置特性,是通過網(wǎng)絡(luò)前綴和MAC地址構(gòu)造IPv6地址的方式來實現(xiàn)地址配置。它不需要任何服務(wù)器或其他配置信息,且可以快速地完成地址配置。SLAAC是一種基于前綴的地址配置方法,使用前綴將一個ipv6地址劃分為IPv6網(wǎng)絡(luò)地址和IPv6主機地址兩部分,網(wǎng)絡(luò)地址由網(wǎng)絡(luò)管理員配置,而主機地址由主機本地自動產(chǎn)生。對于一個無狀態(tài)的網(wǎng)絡(luò)環(huán)境,它是一種簡單快捷的方式。
SLAAC通過局域網(wǎng)中節(jié)點自動就近獲取IP地址,提高了地址分配的利用率,減少了管理員的工作量。但是,SLAAC在地址分配時缺乏安全性,犯罪分子可能會通過MAC地址來獲取到IPv6地址。同時,SLAAC無法為節(jié)點提供其他配置(如DNS信息等),對于像VoIP和視頻會議等應(yīng)用是不利的。
我用的老毛子潘多拉固件,開啟ipv6后,就是用的這種獲取方式。
1.2 DHCPv6
DHCPv6 (Dynamic Host Configuration Protocol version 6) 與SLAAC不同的是,DHCPv6(有狀態(tài),stateful)是一種動態(tài)IP地址分配,且需要在網(wǎng)絡(luò)中使用DHCP服務(wù)器。
DHCPv6是一種動態(tài)IP地址分配方法,它通過DHCP服務(wù)器和客戶端之間的數(shù)據(jù)交換,完成IPv6地址的配置。對于網(wǎng)絡(luò)管理員來說,他需要配置DHCP服務(wù)器信息,而客戶端需要啟用DHCP協(xié)議。DHCPv6可以用于分配地址及其他IPv6配置信息(如DNS服務(wù)器信息),使用起來更加靈活,在基于狀態(tài)的網(wǎng)絡(luò)環(huán)境中十分實用。
DHCPv6具有更高的優(yōu)先級,它可以分配到IPv6地址以外的配置信息,例如網(wǎng)關(guān)、DNS服務(wù)器等,更滿足實際的需要。但是,DHCPv6需要網(wǎng)絡(luò)管理員提供專用的DHCP服務(wù)器,大大增加了管理員的管理量和維護成本,同時,服務(wù)器出現(xiàn)故障將會導致客戶無法分配IPv6地址
1.3 SLAAC+DHCPv6
地址由slaac獲取,但是DNS由DHCPv6通告
注意:上面是IPV6地址獲取方式,但是有的路由器中是沒有上面的內(nèi)容的。而是讓你選擇 ipv6 的連接方式,一般的有橋接、Native模式、NAT6模式等。
1. Native
Native模式意味著原生支持,即設(shè)備直接使用IPv6地址進行通信,無需轉(zhuǎn)換或隧道化。
Native模式適用于多數(shù)情況,它類似于DHCP(動態(tài)主機配置協(xié)議)自動分配IPv6地址。在這種模式下,設(shè)備可以獲得公網(wǎng)IPv6地址,能夠直接訪問公共互聯(lián)網(wǎng)。
2.NAT6模式
NAT6是Network Address Translation for IPv6的縮寫,即IPv6網(wǎng)絡(luò)地址轉(zhuǎn)換。使用NAT6模式時,盡管終端設(shè)備可以獲得IPv6地址,但這個地址是局域網(wǎng)的IPv6地址。在這種模式下,終端設(shè)備只能在局域網(wǎng)內(nèi)部使用IPv6地址進行通信,無法直接訪問公共互聯(lián)網(wǎng)。它適用于路由器做管理網(wǎng)關(guān)的IPv6地址前綴代理,且上一級為光貓撥號的情況。
2. Docker 的 IPv6 支持
為 Docker 配置 IPv6 有三種常見的思路。
- 一種是通過 HOST 模式,直接使用主機網(wǎng)絡(luò),但是可能引來外部掃描和攻擊,存在十分嚴重的安全性問題。尤其是用來掛bt的,被別人看的一清二楚。IPv6 號稱可以為每一粒沙子都分配一個 IP 地址,因此完全可以為每個容器都分配一個獨立的 IPv6 地址,重新找回 IPv6 超大地址空間的安全優(yōu)勢。
這種方式雖然獲取到了IPV6地址,且大部分情景下使用沒問題,但特殊場景受限于 docker的網(wǎng)絡(luò)模型也會有一定的弊端。-Docker網(wǎng)絡(luò) - 簡書
- 一種是通過 HOST 模式,直接使用主機網(wǎng)絡(luò),但是可能引來外部掃描和攻擊,存在十分嚴重的安全性問題。尤其是用來掛bt的,被別人看的一清二楚。IPv6 號稱可以為每一粒沙子都分配一個 IP 地址,因此完全可以為每個容器都分配一個獨立的 IPv6 地址,重新找回 IPv6 超大地址空間的安全優(yōu)勢。
- 第二種是啟用官方的 IPv6 支持,在官方文檔中有說明,但是啟用后僅能獲取到私網(wǎng)(link-local)IPv6 地址,想要獲取公網(wǎng)(global)IPv6 地址,還要指定
--fixed-cidr-v6,在目前國內(nèi)運行商隨機分配前綴的情況下,配置較為麻煩。
- 第二種是啟用官方的 IPv6 支持,在官方文檔中有說明,但是啟用后僅能獲取到私網(wǎng)(link-local)IPv6 地址,想要獲取公網(wǎng)(global)IPv6 地址,還要指定
-
- 第三種也就是本文使用的方法是通過 macvlan,為 docker 創(chuàng)建一個支持 IPv6 的網(wǎng)絡(luò),自動從上級路由獲取公網(wǎng) IPv6 地址。
docker network create -d macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 --ipv6 --subnet=240x:xxxx:xxxx:xxxx::/64 --gateway=240x:xxxx:xxxx:xxxx::1 -o parent=eth0 adnet- docker network create -d macvlan 指定創(chuàng)建的網(wǎng)絡(luò)類型是macvlan
- --subnet=192.168.1.0/24 macvlan的ipv4網(wǎng)段,這里寫你的內(nèi)網(wǎng)網(wǎng)段即可,最后一位是0(/24默認不要動)
- --gateway=192.168.1.1 macvlan的ipv4網(wǎng)關(guān),最后一位是1(其實就是路由器的本地IP地址)
- --ipv6 啟用ipv6支持
- --subnet=240x:xxxx:xxxx:xxxx::/64 macvlan的ipv6前綴
- --gateway=240x:xxxx:xxxx:xxxx::1 macvlan的ipv6網(wǎng)關(guān)(其實就是前綴前4個網(wǎng)段::1)
- -o parent=eth0 橋接網(wǎng)絡(luò)走的是eth0接口(也就是前面我們ifconfig命令得出的接口名稱)
- adnet macvlan網(wǎng)絡(luò)的名稱,可以隨意更改
其中,ipv6的前綴可以用命令獲?。?code>ip -6 route show,自己那是什么就寫什么。ipv6的網(wǎng)關(guān)可以不用寫,會按規(guī)則自動生成
image.png
注意:使用macvlan網(wǎng)絡(luò)時,由于指定了ipv6的前綴,而ipv6地址是不定時變化的。當ipv6地址變了,我們設(shè)置的前綴還是原來的,會不會出問題呢?我確實遇到了這個問題,但是目前用macvlan網(wǎng)絡(luò)的容器(我是adguardhome)還是能正常訪問ipv6的,我也搞不懂為什么。也不知道怎么處理,就先這樣用著。
Docker安裝AdGuard Home,接入路由器,過濾局域網(wǎng)廣告 - 簡書
3. macvlan模式下,容器和宿主機互通
在 macvlan 模式下,出于安全考慮,默認禁止宿主機與容器的通信,也就是宿主機無法訪問以及反代容器。但是局域網(wǎng)中的其他設(shè)備可以訪問到容器。此時的網(wǎng)絡(luò)拓撲如下圖所示,可以將接入 macvlan 的容器看作一個直接接入局域網(wǎng)的設(shè)備(藍色線),只是無法與宿主機(以及宿主機中使用 brigde 模式的設(shè)備)直接通信(紅色線)。

但 macvlan 之間可以通信,因此通過新建一個虛擬接口,然后修改路由,使得
主機 <-> 容器變?yōu)?code>主機 <-> 虛擬接口 <-> 容器,就可以打通容器與宿主機之間的通信。
3.1 配置
-
- 創(chuàng)建虛擬網(wǎng)卡接口,類型macvlan
ip link add joinnet link eth0 type macvlan mode bridge -
- 設(shè)置網(wǎng)卡接口ip
ip addr add 192.168.1.245 dev joinnet -
- 啟動接口
ip link set joinnet up -
- 設(shè)置路由,宿主機和容器打通,此處添加的是
容器IP
ip route add 192.168.1.110 dev joinnet - 設(shè)置路由,宿主機和容器打通,此處添加的是
至此,即可實現(xiàn)宿主機到容器的訪問。
修改完成后的網(wǎng)絡(luò)拓撲類似下圖。通過手動配置靜態(tài)路由,將 192.168.1.110 的路由指向新建的 joinnet虛擬接口,由于該接口視作一個局域網(wǎng)設(shè)備可以訪問到容器,因此從主機 -> 容器變得可達。(粉色線)
反過來,若是 macvlan 下的容器需要訪問主機,直接訪問主機 IP 也是不通的(紅色線),但此時訪問主機可以直接使用虛擬接口的 IP 來替代(綠色線),即在 macvlan 容器下使用 192.168.1.245:port 即可正常訪問到主機服務(wù)。

3.2 開機自動配置
由于上面的虛擬網(wǎng)絡(luò)接口配置在宿主機重啟后會丟失,因此需要創(chuàng)建開機啟動腳本,以實現(xiàn)自動配置。
-
- 網(wǎng)絡(luò)配置腳本 net_docker_macvlan.sh
#!/bin/bash # macvlan 接口名稱[可修改] MACVLAN_INTERFACE="joinnet" # 橋接網(wǎng)口[需修改] PARENT_INTERFACE="eth0" # macvlan 接口 IP [需修改] IP_ADDRESS="192.168.1.245/24" # 所有路由列表 [需修改] ROUTES=("192.168.1.110" "192.168.1.111") start_macvlan() { ip link add $MACVLAN_INTERFACE link $PARENT_INTERFACE type macvlan mode bridge ip addr add $IP_ADDRESS dev $MACVLAN_INTERFACE ip link set $MACVLAN_INTERFACE up for route in "${ROUTES[@]}"; do ip route add $route dev $MACVLAN_INTERFACE done } stop_macvlan() { for route in "${ROUTES[@]}"; do ip route del $route dev $MACVLAN_INTERFACE || true done ip link set $MACVLAN_INTERFACE down || true ip addr del $IP_ADDRESS dev $MACVLAN_INTERFACE || true ip link del $MACVLAN_INTERFACE || true } case "$1" in start) start_macvlan ;; stop) stop_macvlan ;; *) echo "Usage: $0 {start|stop}" exit 1 esac
賦予腳本可執(zhí)行權(quán)限:sudo chmod +x ./net_docker_macvlan.sh
-
- 設(shè)置上面的腳本開機自啟
創(chuàng)建自啟腳本:sudo vim /etc/systemd/system/net_docker_macvlan.service,內(nèi)容如下:
[Unit] Description=Setup macvlan shim for docker to allow to route to host BindsTo=docker.service Requires=docker.service After=docker.service [Service] Type=oneshot ExecStart=/usr/xxx/xxx/xxx/net_docker_macvlan.sh start ExecStop=/us/xxx/xxx/xxx/net_docker_macvlan.sh stop RemainAfterExit=yes Restart=no [Install] WantedBy=multi-user.target - 設(shè)置上面的腳本開機自啟
如果是群暉用戶,由于群暉的 docker systemed 不是 docker.service,因此需要修改 BindsTo、Requires 和 After,根據(jù) DSM 版本不同,服務(wù)名稱可能也不同,可以通過以下方式查看:systemctl list-units --type=service | grep docker。
當然也可以使用 network.target,當網(wǎng)絡(luò)服務(wù)設(shè)置完成后啟動,不強制依賴 docker,是一種更寬松的設(shè)置方式。
最后使用 systemctl start net_docker_macvlan啟動腳本了。
systemctl enable net_docker_macvlan開機自啟

