[Linux] 讓 curl 藉由 socks5 proxy 連線時,不要反解 DNS,造成連線失敗

[Linux] 讓 curl 藉由 socks5 proxy 連線時,不要反解 DNS,造成連線失敗

公司的專案程式通常需要支援各種 proxy server,

如 HTTP proxy, socks4 和 socks5 proxy。

今天遇到一個問題,我們的程式底層會使用 libcurl 做 HTTP 連線,

但連到一台 socks5 proxy 時卻不能成功…

 

試著用 curl 加上 -x 選項來指定 proxy server,

再加 -v 選項看看詳細的錯誤訊息:

testuser@localhost ~ curl -v -x socks5://172.22.1.1:8080 https://testdomain.com

* Rebuilt URL to: https://testdomain.com/
*   Trying 172.22.1.1...
* TCP_NODELAY set
* SOCKS5 communication to testdomain.com:443
* SOCKS5 connect to IPv6 2600:1417:1b:184::23ac (locally resolved)
* Can't complete SOCKS5 connection to 0.0.0.0:0. (1)
* Closing connection 0
curl: (7) Can't complete SOCKS5 connection to 0.0.0.0:0. (1)

 

可以看到訊息裡有一行 locally resolved,

這行代表的是 curl 自行去查詢了 DNS,將 testdomain.com 的 IP 找出來,

但因為 curl 使用的是 Happy Eyeball 的演算法,

同時會發出 Type A 和 AAAA 的 DNS request 封包,

因此如果 AAAA 的 DNS 回應封包先回來的話,

就會拿到 testdomain.com 的對應 IPv6 位址,

反之如果是 A 的 DNS 回應封包先回來的話,拿到的則是 IPv4 位址。

 

下面用 Wireshark 觀察一下 curl 產生出來的 DNS 封包,

它送出了 A 和 AAAA 兩種 DNS 封包,以下例來說是 A (IPv4) 的回應先回來,

但這個結果會依據網路狀況而有所不同,

有時候是 AAAA (IPv6) 的回應先回來:

 

curl 自行查詢 DNS 這件事情有什麼錯誤嗎?

以這個例子來說,curl 幫忙查出 testdomain.com 的 IPv6 位址 2600:1417:1b:184::23ac,

然後連線到 socks5 proxy 172.22.1.1,叫它連線到這個 IPv6 位址去。

然而,這台 socks5 proxy 所在的網路只設定了 IPv4 位址,

所以 proxy server 本身是無法藉由 IPv6 位址來連線的!

因此它自然無法連線到 curl 指定的 IPv6 位址,導致連線失敗…

 

要解決這個問題,可以叫 curl 不要雞婆自己去查 DNS,

而是讓 proxy server 自己來查 DNS,

因為 proxy server 自己知道所處的網路環境,

像是它不能連 IPv6 網路時,自然不會去問 Type AAAA (IPv6) 的 DNS 結果。

 

我們將原本的 socks5://<proxy>:<port> 改成 socks5h://<proxy>:<port>,

代表要讓 proxy 自己的查詢 DNS,

可以看到 curl 直接連到了 proxy server,沒有先做 DNS 查詢,

而最終 proxy 也成功完成了連線:

testuser@localhost ~ curl -v -x socks5h://172.22.1.1:8080 https://testdomain.com

* Rebuilt URL to: https://testdomain.com/
*   Trying 172.22.1.1...
* TCP_NODELAY set
* SOCKS5 communication to testdomain.com:443
* SOCKS5 request granted.
* Connected to 172.22.1.1 (172.22.1.1) port 8080 (#0)
...
* Curl_http_done: called premature == 0
* Connection #0 to host testdomain.com left intact

 

不過這種雷,幾乎是每次整合一個用到 libcurl 的模組,就會再踩到一次啊…

 

參考資料:CURLOPT_PROXY

(本頁面已被瀏覽過 1,372 次)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料