靜態(tài)IP配置:IPv4與IPv6雙棧地址及路由排障指南)
1. 配置前的準(zhǔn)備工作為什么新裝系統(tǒng)的以太網(wǎng)卡往往沒有地址如果你剛裝完一套 Linux 服務(wù)器插上網(wǎng)線之后習(xí)慣性地ping www.example.com大概率會(huì)得到Name or service not known或者Network is unreachable的報(bào)錯(cuò)。別急著懷疑網(wǎng)卡壞了絕大多數(shù)情況下只是因?yàn)槟氵€沒有給以太網(wǎng)接口配置 IP 地址。無(wú)論是 IPv4 還是 IPv6系統(tǒng)默認(rèn)的網(wǎng)絡(luò)棧不會(huì)自動(dòng)幫你決定該用哪個(gè)地址除非你明確開啟了 DHCP 客戶端或者手工指定了靜態(tài)地址。這里涉及的其實(shí)是網(wǎng)絡(luò)服務(wù)最基礎(chǔ)的一環(huán)以太網(wǎng)接口的地址分配。所謂“網(wǎng)絡(luò)服務(wù)2”通常意味著你已經(jīng)了解了網(wǎng)卡驅(qū)動(dòng)和鏈路層的基礎(chǔ)那么接下來(lái)要面對(duì)的就是網(wǎng)絡(luò)層配置。很多人習(xí)慣跳過(guò)這一步直接依賴某一套圖形化工具或者云平臺(tái)的一鍵網(wǎng)絡(luò)設(shè)置結(jié)果到了需要排查問(wèn)題的時(shí)候連ip addr的輸出都看不懂。我建議所有管理員都把手工配置這條路走一遍哪怕最終你維護(hù)的環(huán)境全部用 DHCP理解靜態(tài)配置的原理也會(huì)讓你在排障時(shí)少走很多彎路。1.1 默認(rèn)網(wǎng)絡(luò)棧的初始化邏輯現(xiàn)代 Linux 系統(tǒng)啟動(dòng)時(shí)內(nèi)核會(huì)枚舉所有以太網(wǎng)設(shè)備但默認(rèn)并不會(huì)主動(dòng)給它們分配任何 IPv4 地址。IPv6 的情況稍好一點(diǎn)因?yàn)閮?nèi)核默認(rèn)啟用了 IPv6 的自動(dòng)配置機(jī)制但這也要取決于路由器是否發(fā)送 Router AdvertisementRA報(bào)文。如果你的交換機(jī)端口沒有配置 IPv6 路由通告那么 IPv6 地址同樣不會(huì)出現(xiàn)。我見過(guò)不少新手管理員在/etc/sysconfig/network-scripts/RHEL 系或者/etc/network/interfacesDebian 系里寫了配置但忘了重啟網(wǎng)絡(luò)服務(wù)或者沒有執(zhí)行ip addr flush清掉舊地址結(jié)果新舊配置混在一起產(chǎn)生了意料之外的路由。所以配置前先確認(rèn)你當(dāng)前網(wǎng)卡的真實(shí)狀態(tài)非常關(guān)鍵不要想當(dāng)然。1.2 找出網(wǎng)卡接口名稱與驅(qū)動(dòng)狀態(tài)我一般會(huì)先用兩個(gè)命令確認(rèn)當(dāng)前狀態(tài)ip link show這個(gè)命令會(huì)列出所有網(wǎng)絡(luò)接口包括狀態(tài)為 DOWN 的接口。注意接口名稱常見的有eth0、ens33、enp3s0這類。如果你使用的是虛擬化環(huán)境接口名可能是ens18或者enp0s3。拿到接口名之后再執(zhí)行ip addr show eth0如果看到state DOWN就先把它啟用ip link set eth0 up啟用后再次查看如果還是沒有 IPv4 地址那就說(shuō)明當(dāng)前沒有 DHCP 服務(wù)或者你沒有配置靜態(tài)地址。這時(shí)候你才真正進(jìn)入了以太網(wǎng)配置 IPv4 和 IPv6 的主題。2. IPv4 地址配置的核心步驟與靜態(tài)規(guī)劃IPv4 的配置看起來(lái)簡(jiǎn)單就是給接口一個(gè)IP/掩碼再配上網(wǎng)關(guān)和 DNS。但真正做好靜態(tài)規(guī)劃并不容易尤其是當(dāng)你面對(duì)多塊網(wǎng)卡、多個(gè)網(wǎng)段的服務(wù)器時(shí)掩碼和網(wǎng)關(guān)一旦配錯(cuò)輕則本地通信失敗重則影響整個(gè)路由表。2.1 靜態(tài) IPv4 配置的完整命令流程我以 RHEL 系系統(tǒng)為例因?yàn)樗膎mcli工具既強(qiáng)大又很適合腳本化操作。假設(shè)我要把eth0配置成192.168.10.10/24網(wǎng)關(guān)為192.168.10.1DNS 為223.5.5.5那么可以這樣nmcli connection modify eth0 ipv4.addresses 192.168.10.10/24 nmcli connection modify eth0 ipv4.gateway 192.168.10.1 nmcli connection modify eth0 ipv4.dns 223.5.5.5 nmcli connection modify eth0 ipv4.method manual nmcli connection up eth0每一步都值得解釋一下。第一條是設(shè)置 IP 地址和掩碼這里用的是 CIDR 表示法寫成192.168.10.10 255.255.255.0也是等價(jià)的但 CIDR 更簡(jiǎn)潔。第二條設(shè)置默認(rèn)網(wǎng)關(guān)第三條設(shè)置 DNS 服務(wù)器第四條是關(guān)鍵——ipv4.method manual告訴系統(tǒng)不要試圖通過(guò) DHCP 獲取地址而是采用我們手工指定的配置。最后一條激活連接。如果你用的是 Debian/Ubuntu 系配置文件/etc/netplan/01-netcfg.yaml大概是這樣的network: version: 2 ethernets: eth0: dhcp4: false addresses: - 192.168.10.10/24 routes: - to: default via: 192.168.10.1 nameservers: addresses: - 223.5.5.5然后執(zhí)行netplan apply即可。這里有一個(gè)容易被忽略的點(diǎn)routes部分要寫成to: default而不是寫gateway4因?yàn)樾掳姹?netplan 已經(jīng)棄用了gateway4字段。如果你沿用網(wǎng)上的舊教程可能直接報(bào)錯(cuò)。2.2 網(wǎng)關(guān)與 DNS 的關(guān)聯(lián)路由表的形成很多人在配完 IP 后發(fā)現(xiàn)能 ping 通同網(wǎng)段的機(jī)器但訪問(wèn)外網(wǎng)失敗。這通常不是 IP 配錯(cuò)了而是默認(rèn)路由沒有生效。你可以用ip route show查看路由表default via 192.168.10.1 dev eth0 192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.10如果只有第二行而沒有第一行說(shuō)明默認(rèn)路由缺失。這時(shí)你就要檢查網(wǎng)關(guān)配置是否寫對(duì)了。網(wǎng)關(guān)必須和你的 IP 在同一個(gè)網(wǎng)段內(nèi)否則系統(tǒng)根本沒法把包發(fā)到網(wǎng)關(guān)。這個(gè)邏輯就像快遞員要知道處理中心在哪里如果處理中心的地址和你的寄件地址不在同一個(gè)城市快遞就送不到。DNS 配置同樣重要。我看到有人只配了 IP 和網(wǎng)關(guān)然后就抱怨域名解析失敗。檢查一下/etc/resolv.conf里面有沒有nameserver行。在 systemd 系統(tǒng)里這個(gè)文件往往由systemd-resolved管理你直接改文件可能會(huì)被覆蓋。最好還是通過(guò)nmcli或者 netplan 來(lái)配置 DNS這樣系統(tǒng)重啟后也不會(huì)丟。3. IPv6 配置從 SLAAC 到手工靜態(tài)地址IPv6 的配置比 IPv4 多了一些新概念比如鏈路本地地址、全局單播地址、SLAAC無(wú)狀態(tài)地址自動(dòng)配置、DHCPv6 等等。很多人第一次接觸 IPv6 時(shí)被這些術(shù)語(yǔ)嚇住其實(shí)只要抓住一條主線IPv6 地址是怎么產(chǎn)生的以及路由是怎么確定的。3.1 IPv6 地址的組成與 EUI-64 原理IPv6 地址是 128 位通常寫成八組十六進(jìn)制數(shù)。配置靜態(tài) IPv6 時(shí)你至少要指定一個(gè)前綴長(zhǎng)度和接口標(biāo)識(shí)符。如果你不想手工算 EUI-64可以用ip命令直接指定完整地址ip -6 addr add 2001:db8:100::10/64 dev eth0這里2001:db8:100::10就是我手工指定的地址/64是前綴長(zhǎng)度。但在生產(chǎn)環(huán)境我更推薦使用 EUI-64 格式即用網(wǎng)卡的 MAC 地址自動(dòng)生成接口 ID。怎么實(shí)現(xiàn)呢Linux 下你可以這樣操作ip -6 addr add 2001:db8:100::/64 dev eth0注意我寫的是2001:db8:100::/64沒有指定主機(jī)部分。內(nèi)核會(huì)使用網(wǎng)卡的 MAC 地址根據(jù) EUI-64 規(guī)則填充后 64 位接口標(biāo)識(shí)符從而生成一個(gè)完整的可全局路由地址。這樣做的最大好處是只要前綴不變?nèi)魏我粔K物理網(wǎng)卡都會(huì)得到一個(gè)相對(duì)穩(wěn)定的 IPv6 地址不需要你去記手工 ID。這種機(jī)制的原理在于EUI-64 會(huì)把 Mac 地址的中間部分插入ff:fe再把第 7 位翻轉(zhuǎn)U/L 位。比如 MAC 是00:1a:2b:3c:4d:5e生成的接口 ID 就會(huì)類似021a:2bff:fe3c:4d5e。你不需要手工去算內(nèi)核會(huì)替你完成但理解這個(gè)過(guò)程對(duì)排查“為什么我的 IPv6 地址和我預(yù)期的不一樣”很有幫助。3.2 手工配置與自動(dòng)獲取的取舍IPv6 有兩條自動(dòng)配置路徑SLAAC 和 DHCPv6。SLAAC 依賴路由器的路由通告不需要額外狀態(tài)記錄所以很輕量。DHCPv6 則更接近傳統(tǒng)的 IPv4 DHCP能下發(fā) DNS、域名等額外參數(shù)。我見過(guò)一些網(wǎng)絡(luò)環(huán)境管理員把 RA 廣播關(guān)掉了導(dǎo)致客戶端拿不到 IPv6 地址然后又來(lái)問(wèn)我為什么 IPv6 不通。實(shí)際上如果你只在局域網(wǎng)內(nèi)部測(cè)試 IPv6完全可以手工靜態(tài)配置不需要依賴任何自動(dòng)機(jī)制。下面是一個(gè)手工配置同時(shí)生效 IPv4 和 IPv6 的例子nmcli connection modify eth0 ipv6.addresses 2001:db8:100::10/64 nmcli connection modify eth0 ipv6.gateway 2001:db8:100::1 nmcli connection modify eth0 ipv6.method manual nmcli connection modify eth0 ipv4.addresses 192.168.10.10/24 nmcli connection modify eth0 ipv4.gateway 192.168.10.1 nmcli connection modify eth0 ipv4.dns 223.5.5.5 nmcli connection modify eth0 ipv6.dns 2400:3200::1 nmcli connection up eth0這里有個(gè)經(jīng)驗(yàn)點(diǎn)很多人只改了ipv6.method manual但忘了設(shè)置ipv6.gateway。如果沒有網(wǎng)關(guān)IPv6 通信只能在同一鏈路內(nèi)進(jìn)行無(wú)法訪問(wèn)外部網(wǎng)絡(luò)。IPv6 的默認(rèn)路由和 IPv4 是獨(dú)立存在的你必須確認(rèn)路由表里有ip -6 route show看到類似default via 2001:db8:100::1 dev eth0的條目說(shuō)明 IPv6 默認(rèn)路由已經(jīng)生效。4. 雙棧共存IPv4 與 IPv6 的優(yōu)先級(jí)切換實(shí)踐現(xiàn)代網(wǎng)絡(luò)基本都是雙棧同一個(gè)網(wǎng)卡既跑 IPv4 又跑 IPv6。雙棧的好處是應(yīng)用層可以用更先進(jìn)的協(xié)議訪問(wèn)資源壞處是配置復(fù)雜度上升容易在 DNS 解析和路由策略上踩坑。4.1 雙棧環(huán)境下的 DNS 解析行為雙棧環(huán)境下getaddrinfo會(huì)嘗試解析 A 記錄IPv4和 AAAA 記錄IPv6。默認(rèn)情況下Linux 的gai.conf會(huì)優(yōu)先選擇 IPv6但前提是系統(tǒng)檢測(cè)到本機(jī)有可用的全局 IPv6 地址。如果你只配了 IPv4沒有配 IPv6那么即使 DNS 返回了 AAAA 記錄程序也會(huì)自動(dòng)跳過(guò)回落到 IPv4。我見過(guò)一個(gè)有意思的問(wèn)題雙棧服務(wù)器上某個(gè)應(yīng)用總是優(yōu)先走 IPv6但管理的交換機(jī)沒有完全配置好 IPv6 路由導(dǎo)致連接超時(shí)。這時(shí)就能通過(guò)修改/etc/gai.conf中的precedence規(guī)則來(lái)調(diào)整優(yōu)先級(jí)。比如將 IPv4 的優(yōu)先級(jí)調(diào)高precedence ::ffff:0:0/96 100這個(gè)配置表示所有 IPv4 映射地址都有最高優(yōu)先級(jí) 100。保存后重啟相關(guān)服務(wù)你就會(huì)發(fā)現(xiàn)應(yīng)用開始優(yōu)先使用 IPv4 連接。4.2 修改地址族選擇策略的實(shí)戰(zhàn)修改優(yōu)先級(jí)到底怎么驗(yàn)證我通常用一個(gè)小工具測(cè)試getent ahosts example.com這個(gè)命令會(huì)輸出example.com解析出來(lái)的所有地址并且顯示順序。如果第一行是 IPv6 地址說(shuō)明當(dāng)前策略優(yōu)先 IPv6如果第一行是 IPv4 地址說(shuō)明優(yōu)先 IPv4。實(shí)際調(diào)整時(shí)除了gai.conf還要看系統(tǒng)層面是否啟用了disable_ipv6。有些管理員為了省事直接在內(nèi)核參數(shù)里關(guān)了 IPv6sysctl -w net.ipv6.conf.all.disable_ipv61這么做當(dāng)然可以徹底避免 IPv6 問(wèn)題但也會(huì)讓你喪失雙棧的能力。我更傾向于保持 IPv6 啟用只在應(yīng)用層做策略切換。畢竟 IPv6 地址資源充足某些場(chǎng)景下反而更好用比如做遠(yuǎn)程管理的靜態(tài)地址時(shí)不用擔(dān)心和內(nèi)網(wǎng)自動(dòng)分配沖突。5. 配置后的連通性驗(yàn)證與常見故障排查地址配好了路由也配好了接下來(lái)就是驗(yàn)證。驗(yàn)證的方法決定了你排障的效率。很多人只會(huì)ping但ping的報(bào)錯(cuò)信息有限無(wú)法區(qū)分是本地地址問(wèn)題、路由問(wèn)題還是遠(yuǎn)端防火墻問(wèn)題。5.1 ping、traceroute、ip 命令的組合用法我建議按以下順序排查先看接口地址是否正確ip addr show eth0。再看路由表是否完整ip route show和ip -6 route show。然后 ping 同網(wǎng)段的網(wǎng)關(guān)ping -c 4 192.168.10.1IPv6 則用ping6 -c 4 2001:db8:100::1。如果網(wǎng)關(guān)通了再 ping 外網(wǎng)地址注意不要一開始就 ping 域名因?yàn)橛蛎馕隹赡鼙旧砭陀袉?wèn)題。先 ping 一個(gè)公網(wǎng) IPv4 地址比如ping -c 4 223.5.5.5以及公網(wǎng) IPv6 地址比如ping6 -c 4 2400:3200::1。如果 IP 通但域名不通就排查 DNScat /etc/resolv.conf再用nslookup或dig測(cè)試。如果某一跳不通用traceroute或者traceroute6看是在哪一跳丟包。這套流程適用于絕大多數(shù)連通性故障。注意ping6在現(xiàn)代系統(tǒng)里可能已經(jīng)并入ping -6我用的是ping -6也完全可以。5.2 我踩過(guò)的幾個(gè)配置雷區(qū)第一個(gè)雷區(qū)是忘記把接口配置做成持久化。比如我用ip addr add臨時(shí)配置成功后感覺很順利結(jié)果系統(tǒng)一重啟配置全部丟失進(jìn)入無(wú)法遠(yuǎn)程連接的尷尬局面。臨時(shí)命令只適合測(cè)試環(huán)境生產(chǎn)環(huán)境必須寫入nmcli connection或者 netplan 或/etc/sysconfig/network-scripts/確保重啟后依然生效。第二個(gè)雷區(qū)是 IPv4 和 IPv6 的默認(rèn)路由互相干擾。有些系統(tǒng)會(huì)同時(shí)下發(fā) IPv4 和 IPv6 的默認(rèn)路由但其中一個(gè)網(wǎng)段實(shí)際不可達(dá)導(dǎo)致數(shù)據(jù)包走到“黑洞”。我建議配置完成后立刻檢查路由表把多余的默認(rèn)路由刪掉保留真正可用的一條。刪除方法ip route del default via 192.168.10.1或者針對(duì) IPv6ip -6 route del default via 2001:db8:100::1第三個(gè)雷區(qū)是 DNS 解析超時(shí)。systemd-resolved會(huì)默認(rèn)向所有配置的 DNS 服務(wù)器發(fā)起請(qǐng)求如果其中一個(gè)不可達(dá)會(huì)導(dǎo)致解析時(shí)間變長(zhǎng)。你可以在/etc/systemd/resolved.conf里設(shè)置DNSStubListenerno或者使用FallbackDNS但最簡(jiǎn)單的方案還是確保 DNS 服務(wù)器地址是可用的。第四個(gè)雷區(qū)是鏈路本地地址和全局地址混淆。IPv6 的接口一定有一個(gè)fe80::開頭的鏈路本地地址這是自動(dòng)生成的不需要配置。你不能用鏈路本地地址作為默認(rèn)網(wǎng)關(guān)因?yàn)樗辉谕绘溌穬?nèi)有效。檢查有沒有全局 IPv6 地址就看有沒有2001:或者公網(wǎng)前綴開頭的地址而鏈路本地地址永遠(yuǎn)以fe80:開頭。在我自己的維護(hù)經(jīng)歷里最讓人抓狂的一次是一臺(tái)服務(wù)器的網(wǎng)卡配置看起來(lái)完全正確IPv4 和 IPv6 地址都在路由也在但就是無(wú)法和同一交換機(jī)上的另一臺(tái)機(jī)器通信。后來(lái)我發(fā)現(xiàn)問(wèn)題出在對(duì)端機(jī)器的防火墻規(guī)則上它只放行了 IPv4 的 ICMP卻沒有放行 IPv6 的 ICMPv6。IPv6 的鄰居發(fā)現(xiàn)協(xié)議依賴 ICMPv6如果對(duì)端丟棄了 ICMPv6即使你的配置毫無(wú)問(wèn)題鄰居表也無(wú)法建立通信自然失敗。所以排查雙棧問(wèn)題時(shí)一定不要只盯本地配置還要檢查對(duì)端防火墻和交換機(jī)端口的 IPv6 支持情況。最后分享一個(gè)我在實(shí)際配置中養(yǎng)成的習(xí)慣在/etc/hosts里先寫好本機(jī)的主機(jī)名解析這樣系統(tǒng)啟動(dòng)時(shí)就不會(huì)因?yàn)?DNS 不可用而卡住某些服務(wù)。配完 IP 和路由后我會(huì)立刻執(zhí)行ping -c 1 網(wǎng)關(guān)并同時(shí)測(cè)試getent ahosts用最小代價(jià)確認(rèn)端到端鏈路是否完整。配置網(wǎng)絡(luò)這件事往往最花時(shí)間的不是敲命令而是理清地址、路由和 DNS 之間的邏輯關(guān)系。只要這三條線捋順了IPv4 和 IPv6 其實(shí)都一樣——一個(gè)是大家熟悉的舊地址體系一個(gè)是需要多點(diǎn)耐心的新地址體系掌握好它們之間的聯(lián)系與區(qū)別大多數(shù)網(wǎng)絡(luò)問(wèn)題都能迎刃而解。