php 由于代理,curl 在浏览器和 CLI 下的行为不同
php curl behaves differently under browser & CLI due to proxy
最初我在尝试弄清楚为什么当我尝试通过 CLI 执行相同的脚本时 php 浏览器下的 curl 行为不同时遇到了问题。
通过打开 CURLOPT_VERBOSE 日志输出并比较 CLI 和浏览器的结果,以下是我看到的差异:
CLI 下的 CURL
* About to connect() to proxy localhost port 3128 (#4)
* Trying ::1...
* Connection refused
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3128 (#4)
* Establish HTTP proxy tunnel to someurl.com:443
* Server auth using Basic with user 'some_username'
> CONNECT someurl.com:443 HTTP/1.1
Host: someurl.com:443
Proxy-Connection: Keep-Alive
< HTTP/1.1 407 Proxy Authentication Required
< Mime-Version: 1.0
< Date: Fri, 11 Dec 2020 12:04:46 CST
< Via: 1.1 someotherurl.com:8080 (Cisco-WSA/12.0.1-334)
< Content-Type: text/html
< Connection: close
< Proxy-Connection: close
< Content-Length: 2109
< X-RBT-SCAR: 2.3.4.5:11517381:2000
< Proxy-Authenticate: Basic realm="Cntlm for parent"
* Authentication problem. Ignoring this.
<
* Received HTTP code 407 from proxy after CONNECT
* Connection #4 to host localhost left intact
浏览器下的 CURL
* About to connect() to someurl.com port 443 (#6)
* Trying 1.2.3.4...
* Connected to someurl.com (1.2.3.4) port 443 (#6)
* warning: ignoring value of ssl.verifyhost
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: C=US,ST=FL,L=Boca Raton,O=Telit IoT Platforms,OU=secureWISE,CN=someurl.com
* start date: Apr 15 21:18:15 2020 GMT
* expire date: May 15 21:18:15 2022 GMT
* common name: someurl.com
* issuer: E=support@securewise.net,CN=secureWISE CA-256,OU=SecureWISE Certificate Authority,O=ILS Technology LLC,O=Telit Wireless Solutions Inc,L=Boca Raton,ST=Florida,C=US
* Server auth using Basic with user 'some_username'
> GET /someurl HTTP/1.1
Authorization: Basic SomeAuthKey
Host: someurl.com
Accept: */*
< HTTP/1.1 200 OK
< Date: Fri, 11 Dec 2020 04:07:40 GMT
< Server: Apache-Coyote/1.1
< X-Powered-By: Undertow/1
< Set-Cookie: JSESSIONID=c2BBPwZBjGxCaH5om6unoKaI; path=/
< Set-Cookie: somekey=somevalue; path=/
< Content-Type: text/xml
< Content-Length: 125291
< Content-disposition: attachment; filename=somefilename.xml
< Vary: Accept-Encoding,User-Agent
< SWOrigin: sw_proxy
< Connection: close
<
* Closing connection 6
我最初的预感是这与代理有关(因为这台电脑确实使用代理上网)
并且查看浏览器日志,似乎跳过了代理。
我还检查了浏览器和 CLI 的 phpinfo(),我可以看到定义了 proxy
、http_proxy
、https_proxy
在环境变量中,以及 CLI 的 $_SERVER
下,但 不在浏览器上 ,这让我更相信我的假设是正确的。
所以为了解决这个问题,我尝试在 curl 调用之前添加以下代码:
if(isset($_SERVER['http_proxy']))
unset($_SERVER['http_proxy']);
if (isset($_SERVER['https_proxy']))
unset($_SERVER['https_proxy']);
if (isset($_SERVER['proxy']))
unset($_SERVER['proxy']);
if(isset($_ENV['http_proxy']))
unset($_ENV['http_proxy']);
if (isset($_ENV['https_proxy']))
unset($_ENV['https_proxy']);
if (isset($_ENV['proxy']))
unset($_ENV['proxy']);
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "someuser:somepass");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$result = curl_exec($ch);
curl_close($ch);
但是verbose还是显示在CLI下执行时还是会尝试通过代理
对此有什么建议吗?
仔细研究后发现,我所要做的就是通过在 NoProxy 配置中包含 url 来绕过 /etc/cntlm.conf 中的 someurl.com。
最初我在尝试弄清楚为什么当我尝试通过 CLI 执行相同的脚本时 php 浏览器下的 curl 行为不同时遇到了问题。
通过打开 CURLOPT_VERBOSE 日志输出并比较 CLI 和浏览器的结果,以下是我看到的差异:
CLI 下的 CURL
* About to connect() to proxy localhost port 3128 (#4)
* Trying ::1...
* Connection refused
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3128 (#4)
* Establish HTTP proxy tunnel to someurl.com:443
* Server auth using Basic with user 'some_username'
> CONNECT someurl.com:443 HTTP/1.1
Host: someurl.com:443
Proxy-Connection: Keep-Alive
< HTTP/1.1 407 Proxy Authentication Required
< Mime-Version: 1.0
< Date: Fri, 11 Dec 2020 12:04:46 CST
< Via: 1.1 someotherurl.com:8080 (Cisco-WSA/12.0.1-334)
< Content-Type: text/html
< Connection: close
< Proxy-Connection: close
< Content-Length: 2109
< X-RBT-SCAR: 2.3.4.5:11517381:2000
< Proxy-Authenticate: Basic realm="Cntlm for parent"
* Authentication problem. Ignoring this.
<
* Received HTTP code 407 from proxy after CONNECT
* Connection #4 to host localhost left intact
浏览器下的 CURL
* About to connect() to someurl.com port 443 (#6)
* Trying 1.2.3.4...
* Connected to someurl.com (1.2.3.4) port 443 (#6)
* warning: ignoring value of ssl.verifyhost
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: C=US,ST=FL,L=Boca Raton,O=Telit IoT Platforms,OU=secureWISE,CN=someurl.com
* start date: Apr 15 21:18:15 2020 GMT
* expire date: May 15 21:18:15 2022 GMT
* common name: someurl.com
* issuer: E=support@securewise.net,CN=secureWISE CA-256,OU=SecureWISE Certificate Authority,O=ILS Technology LLC,O=Telit Wireless Solutions Inc,L=Boca Raton,ST=Florida,C=US
* Server auth using Basic with user 'some_username'
> GET /someurl HTTP/1.1
Authorization: Basic SomeAuthKey
Host: someurl.com
Accept: */*
< HTTP/1.1 200 OK
< Date: Fri, 11 Dec 2020 04:07:40 GMT
< Server: Apache-Coyote/1.1
< X-Powered-By: Undertow/1
< Set-Cookie: JSESSIONID=c2BBPwZBjGxCaH5om6unoKaI; path=/
< Set-Cookie: somekey=somevalue; path=/
< Content-Type: text/xml
< Content-Length: 125291
< Content-disposition: attachment; filename=somefilename.xml
< Vary: Accept-Encoding,User-Agent
< SWOrigin: sw_proxy
< Connection: close
<
* Closing connection 6
我最初的预感是这与代理有关(因为这台电脑确实使用代理上网)
并且查看浏览器日志,似乎跳过了代理。
我还检查了浏览器和 CLI 的 phpinfo(),我可以看到定义了 proxy
、http_proxy
、https_proxy
在环境变量中,以及 CLI 的 $_SERVER
下,但 不在浏览器上 ,这让我更相信我的假设是正确的。
所以为了解决这个问题,我尝试在 curl 调用之前添加以下代码:
if(isset($_SERVER['http_proxy']))
unset($_SERVER['http_proxy']);
if (isset($_SERVER['https_proxy']))
unset($_SERVER['https_proxy']);
if (isset($_SERVER['proxy']))
unset($_SERVER['proxy']);
if(isset($_ENV['http_proxy']))
unset($_ENV['http_proxy']);
if (isset($_ENV['https_proxy']))
unset($_ENV['https_proxy']);
if (isset($_ENV['proxy']))
unset($_ENV['proxy']);
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "someuser:somepass");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_VERBOSE, true);
$result = curl_exec($ch);
curl_close($ch);
但是verbose还是显示在CLI下执行时还是会尝试通过代理
对此有什么建议吗?
仔细研究后发现,我所要做的就是通过在 NoProxy 配置中包含 url 来绕过 /etc/cntlm.conf 中的 someurl.com。