Contents

解決 localhost 返回 ::1 而非 127.0.0.1 的問題

有時候程式明明只想針對本機連線做白名單判斷,結果抓到的不是 127.0.0.1,而是 ::1。第一次看到會很像系統解析錯誤,但其實這通常只是 IPv6 和 IPv4 的差異。

先理解 ::1 是什麼

::1 是 IPv6 的 loopback 位址,功能上對應 IPv4 的 127.0.0.1。換句話說,兩者都代表「這台機器自己」。

差別只在於:

  1. 127.0.0.1 是 IPv4。
  2. ::1 是 IPv6。

所以當系統、Runtime 或 DNS 解析優先使用 IPv6 時,localhost 解析成 ::1 其實是正常現象。

https://user-images.githubusercontent.com/6058558/269945098-97e335dd-3da8-4e70-9949-6040c9b94c74.png

為什麼程式會拿到 ::1

常見原因有這幾個:

  1. 作業系統啟用了 IPv6。
  2. /etc/hosts 或系統 hosts 設定把 localhost 對到 ::1
  3. 某些函式庫在解析主機名稱時會優先取 IPv6。

這代表問題不一定在你的應用程式,而是整個網路堆疊本來就支援 IPv6。

實務上怎麼解

1. 程式端同時接受兩種 loopback

如果你是在做白名單判斷,最穩的方式通常不是硬限定只能是 127.0.0.1,而是把 ::1 一起納入。

1
Set<String> allowedIps = new HashSet<>(Arrays.asList("127.0.0.1", "::1"));

這樣比較不會因為不同環境的解析策略不同而出問題。

2. 確認系統實際怎麼解析 localhost

可以先檢查:

1
2
ping localhost
getent hosts localhost

在不同系統上,看到的結果可能不一樣。先知道系統現在怎麼解,會比直接改程式碼更有方向。

3. 必要時再調整 hosts

如果你真的有特殊需求,要讓 localhost 固定走 IPv4,再回頭看 hosts 設定。不過這種改法會影響整台機器,不一定是最好的第一選擇。

開發上常見的誤區

1. 把 localhost 和 127.0.0.1 當成完全等價字串

概念上接近,但實際解析結果不一定永遠相同,尤其在 IPv6 開著的環境。

2. 只測一種環境

在某台機器上永遠拿到 127.0.0.1,不代表同事機器、容器、CI 或正式環境也一樣。

小結

localhost 返回 ::1 而不是 127.0.0.1,大多數時候不是異常,而是系統正在走 IPv6。實務上如果你只是要辨識本機來源,建議同時接受兩種 loopback 位址,會比硬把環境改回 IPv4 更穩。