某些 HTTPS 網站不會通過 IPv6 從 KVM 虛擬機載入
這讓我發瘋,因為我不能僅從 KVM 虛擬機並且只能通過 IPv6 載入某些 HTTPS 網站。IPv4 工作正常。IPv6 連接適用於來自管理程序的相同網站。
我的設置
- KVM 管理程序在Ubuntu 14.04.5 LTS上執行。
- eth0被添加到br0網橋介面,我使用這個網橋將虛擬機連接到外部世界。
- 兩個虛擬機在管理程序上執行。第一個在Ubuntu 12.04上執行(我知道它已經達到 EOL,但這並不重要),第二個是Ubuntu 16.04。兩個虛擬機都遇到了這個問題。
- VM 使用 Virtio 介面連接到網路。
- IPv6 地址由虛擬機管理程序和 VM 獲取。
- 如果域支持,我的 DNS 伺服器將返回 IPv6 地址,否則它適用於 IPv4。
- 我對管理程序和虛擬機都沒有 IPv6 的防火牆(ip6tables)。
# ip6tables -v -L -n Chain INPUT (policy ACCEPT 196K packets, 32M bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 5007K packets, 3858M bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 185K packets, 30M bytes) pkts bytes target prot opt in out source destination # ip6tables -v -L -n -t nat Chain PREROUTING (policy ACCEPT 1749 packets, 181K bytes) pkts bytes target prot opt in out source destination Chain INPUT (policy ACCEPT 135 packets, 24165 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 187 packets, 27578 bytes) pkts bytes target prot opt in out source destination Chain POSTROUTING (policy ACCEPT 1801 packets, 185K bytes) pkts bytes target prot opt in out source destination
問題
- IPv6(和 IPv4)連接適用於來自虛擬機管理程序的所有網站(這很好,正如預期的那樣)。
# wget https://lwn.net -O - > /dev/null; echo Exit code: $? --2017-08-02 18:55:47-- https://lwn.net/ Resolving lwn.net (lwn.net)... 2600:3c03::f03c:91ff:fe61:5c5b, 45.33.94.129 Connecting to lwn.net (lwn.net)|2600:3c03::f03c:91ff:fe61:5c5b|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 25202 (25K) [text/html] Saving to: ‘STDOUT’ 100%[=====================================>] 25,202 149KB/s in 0.2s 2017-08-02 18:55:48 (149 KB/s) - written to stdout [25202/25202] Exit code: 0
- IPv6 連接適用於我在虛擬機內部嘗試過的大多數網站,但不是全部。例如,**https://lwn.net>**和**<https://hioa.no**是我遇到問題的兩個 https 網站。正如您從下面的 wget 命令中看到的那樣,連接達到了連接狀態,但它卡在了那裡:
# wget https://lwn.net -O - > /dev/null; echo Exit code: $? --2017-08-02 18:53:40-- https://lwn.net/ Resolving lwn.net (lwn.net)... 2600:3c03::f03c:91ff:fe61:5c5b, 45.33.94.129 Connecting to lwn.net (lwn.net)|2600:3c03::f03c:91ff:fe61:5c5b|:443... connected.
到目前為止我嘗試解決的問題
- 從 ping6 開始。有趣的是,當使用 IPv6 時,來自 VM 的 ping 對所有域都有效!包括那些 https 不工作的。
# ping6 -c 1 -n hioa.no PING hioa.no(2001:700:700:2::65) 56 data bytes 64 bytes from 2001:700:700:2::65: icmp_seq=1 ttl=53 time=88.7 ms # ping6 -c 1 -n lwn.net PING lwn.net(2600:3c03::f03c:91ff:fe61:5c5b) 56 data bytes 64 bytes from 2600:3c03::f03c:91ff:fe61:5c5b: icmp_seq=1 ttl=54 time=145 ms
- 我試圖將虛擬網路設備從virtio更改為e1000。問題依然存在。
- 嘗試使用 IPv4 連接到我遇到問題的網站。
# dig A lwn.net ; <<>> DiG 9.10.3-P4-Ubuntu <<>> A lwn.net ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41423 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;lwn.net. IN A ;; ANSWER SECTION: lwn.net. 2633 IN A 45.33.94.129
IPv4 連接工作正常!
# wget --no-check-certificate https://45.33.94.129 -O - > /dev/null; echo Exit code: $? --2017-08-02 18:41:32-- https://45.33.94.129/ Connecting to 45.33.94.129:443... connected. WARNING: certificate common name `*.lwn.net' doesn't match requested host name `45.33.94.129'. HTTP request sent, awaiting response... 200 OK Length: 25226 (25K) [text/html] Saving to: `STDOUT' 100%[==================================>] 25,226 137K/s in 0.2s 2017-08-02 18:41:33 (137 KB/s) - written to stdout [25226/25226] Exit code: 0
- 嘗試使用“openssl s_client”連接並查看是否有任何錯誤消息,但“openssl s_client”還不支持 IPv6(至少在 Ubuntu 16.04 中包含的 openssl 版本中不支持)。
- 檢查dmesg和*/var/log/syslog*但那裡沒有任何相關內容。
任何人都知道為什麼我會在某些網站上出現這種奇怪的行為?關於下一步我應該嘗試調查什麼的任何指示?
通過將 VM 中的 MTU 減少到 1492 解決了問題。管理程序負責建立與網際網路的 PPPoE 連接,ppp0 介面的 MTU 為 1492 字節。
不過,既然 IPv4 和 IPv6 都實現了路徑 MTU 發現,為什麼 MTU 會成為問題?那麼為什麼路徑 MTU 發現在這種情況下不起作用(僅適用於某些 IPv6 目的地)?
好像在這裡遇到了黑洞的情況。
我擷取了一些流量
tcpdump
並將文件載入到 Wireshark 中。我觀察到連接通過 TCP 三向握手,如您在附圖(數據包 1-3)中所見。這從我的問題的輸出中也很明顯,您可以看到 wget 在列印消息wget
後卡住了。connected
三次握手成功後,客戶端(我的虛擬機)發送 SSL “Client Hello”消息,但從未收到“Server Hello”回复。客戶端收到的是一個基於 TCP 序列號明顯亂序的數據包(wireshark 也報告$$ TCP Previous segment not captured $$,續數據)。然後,客戶端對已接收到的最後一個有序數據包(重複 ACK)響應 ACK(數據包 6),並且連接停止,因為伺服器嘗試重新發送失去的數據包,該數據包大於支持的 MTU 並且永遠不會到達. 所以連接卡在那裡,直到我按下Ctrl
+C
開始連接終止(數據包 8-10)。那麼為什麼路徑 MTU 發現不僅適用於某些 IPv6 目的地(不是全部),而且 IPv4 根本沒有問題?對於這個問題,並且由於我的安裝沒有 IPv6 防火牆,我假設在通往某些網站的途中有一些防火牆阻止了路徑 MTU 發現工作所需的ICMPv6 數據包太大消息。有趣的是,簡單的 ICMPv6 ping 數據包通過,我什至收到回复。