Laravel HTTP Client ↔ System DNS Resolver: Inconsistent SSL Verification Behavior
0 reputation · 04 Dec 2021, 06:50 UTC
0 reputation · 04 Dec 2021, 06:50 UTC
The goal is to understand why SSL certificate validation sometimes fails when the Laravel HTTP Client resolves a host that has been cached by the underlying PHP‑FPM DNS resolver. The Laravel HTTP Client relies on Guzzle and ultimately cURL, which in turn uses the OS resolver and the CA bundle specified by curl.cainfo or openssl.cafile in php.ini. In a multi‑worker PHP‑FPM environment the resolver may cache DNS entries differently, leading to inconsistent host resolution and occasional “SSL certificate problem: unable to get local issuer certificate” errors.
Constraints include keeping SSL verification enabled in production, ensuring the CA bundle path is correct, and avoiding DNS‑related latency that can block worker processes. The uncertainty lies in whether the observed failures are due to DNS caching, a misconfigured CA bundle, or a subtle interaction between Guzzle’s withoutVerifying() method and PHP‑FPM’s resolver.
Questions:
curl.cainfo in php.ini guarantee consistent SSL verification across all PHP‑FPM workers, or is per‑worker configuration required?DNS caching by the system resolver does not make the Laravel HTTP Client ignore a correctly configured CA bundle. The Laravel HTTP Client uses Guzzle which uses cURL. cURL resolves the host via the OS resolver, then performs the TLS handshake and verifies the peer certificate against the CA bundle configured via curl.cainfo or openssl.cafile. A cached DNS entry can change which IP is contacted and can cause hostname mismatch errors, but it does not change which CA file cURL uses or make verification be skipped.
PHP-FPM has no DNS cache and no directive to disable DNS caching. DNS caching is performed by the OS resolver, e.g., glibc nscd, systemd-resolved, or a local resolver cache. Changing resolver caching does not fix CA bundle errors and would not affect SSL validation.
curl.cainfo and openssl.cafile are php.ini defaults for the curl and openssl extensions. In PHP-FPM each worker inherits the ini values loaded at pool start.curl.cainfo in the php.ini used by all pools is sufficient for consistency across workers if the path is identical, readable by the FPM user, and no pool overrides it with php_admin_value or php_value.withoutVerifying() or a handler that sets CURLOPT_SSL_VERIFYPEER false / verify => false overrides php.ini at runtime and disables verification.The error points to CA bundle configuration, not DNS caching. Common causes are:
withoutVerifying() used conditionally.curl.cainfo, openssl.cafile or verify related settings.DNS caching can contribute to a different symptom: "certificate verify failed" with hostname mismatch when a cached record points to an IP with a different certificate.
phpinfo() for curl.cainfo and openssl.cafile. Verify the file exists and is readable by the FPM user.php_admin_value[curl.cainfo], php_value[curl.cainfo], and similar for openssl. Overrides cause divergence even when the main php.ini looks correct.verify and any handler stack modifications. Log cURL error code and error message from the exception.curl --cacert /path/to/ca-bundle.pem -v https://target.hostDo not disable SSL verification in production to work around intermittent errors. withoutVerifying() removes protection against MITM attacks.
One missing diagnostic detail that changes the recommendation: the exact cURL error code and message per failing request, and whether the same host/IP pair is involved. "unable to get local issuer certificate" indicates CA bundle configuration, while "certificate verify failed" with hostname mismatch points to DNS returning an IP with a different certificate.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.