curl_exec segmentation fault when using CURLOPT_PROXY
This documents my Segmentaion fault as requested here https://twitter.com/n_copa/status/1401971352073084928
My set up is docker containers. In development this is on an Intel Mac, in Production this is on a Digital Ocean server.
I was able to isolate and replicate the issue away from my production application (mySites.guru)
to replicate I started php:alpine3.13
docker run -it --rm php:alpine3.13 sh
out of the box this has:
PHP 8.0.7 (cli) (built: Jun 4 2021 19:02:30) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.7, Copyright (c) Zend Technologies
curl 7.76.1 (x86_64-alpine-linux-musl) libcurl/7.77.0 OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.9 nghttp2/1.42.0
Release-Date: 2021-04-14
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets
WARNING: curl and libcurl versions do not match. Functionality may be affected.
My exact test case, with redacted domains/proxy is below, the problem can be replicated with php script:
<?php
$ch = curl_init();
// replace a.working.proxy:8888 with a Nginx Forward Proxy
curl_setopt($ch, CURLOPT_PROXY, 'a.working.proxy:8888');
// replace https://a.site.that.has.blocked.your.proxies.ip/ with a site that you know has your Proxy's IP address blocked in their firewall.
curl_setopt($ch, CURLOPT_URL, 'https://a.site.that.has.blocked.your.proxies.ip/');
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
$res = curl_exec($ch);
print_r($res);
Then run as php test.php
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
In writing up these notes, I wanted to provide code that you could just run, so I took a proxy from https://spys.one/en/free-proxy-list/ and added it to the code, and used https://alpinelinux.org as the domain name, as there is no IP blocking of this exact proxy by https://alpinelinux.org - this is ruling out my initial theory and leads me to believe this seems to be an issue when using CURLOPT_PROXY to be sure. Your mileage might vary, I dont control these proxies and their responses.
<?php
error_reporting(E_ALL);
ini_set('display_errors',1);
$ch = curl_init();
curl_setopt($ch, CURLOPT_PROXY, '70.169.141.35:3128');
curl_setopt($ch, CURLOPT_URL, 'https://alpinelinux.org');
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
$res = curl_exec($ch);
print_r($res);exit;
When run I get:
/ # nano test.php
/ # php test.php
/ # php test.php
/ # php test.php
/ # php test.php
/ # php test.php
/ # nano test.php
/ # php test.php
/ # php test.php
/ # php test.php
Segmentation fault
/ # php test.php
/ # php test.php
/ # php test.php
/ # php test.php
/ # php test.php
Segmentation fault
/ # php test.php
Segmentation fault
/ # php test.php
/ # php test.php
/ # php test.php
Segmentation fault
As soon as you remove the curl_setopt($ch, CURLOPT_PROXY, '70.169.141.35:3128');
line EVERYTHING works fast and as normal, and NEVER seg faults... unfortunatly my use case needs to route every request through a forward proxy :)
I also tried with an upgraded Curl - apk upgrade gave:
# apk upgrade curl
(1/1) Upgrading curl (7.76.1-r0 -> 7.77.0-r0)
Executing busybox-1.32.1-r6.trigger
OK: 20 MiB in 34 packages
# curl -V
curl 7.77.0 (x86_64-alpine-linux-musl) libcurl/7.77.0 OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.9 nghttp2/1.42.0
Release-Date: 2021-05-26
Protocols: dict file ftp ftps gopher gophers http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli HSTS HTTP2 HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP UnixSockets
/ # nano test.php
/ # php test.php
/ # php test.php
Segmentation fault
/ # php test.php
/ # php test.php
Segmentation fault
/ # php test.php
/ # php test.php
Segmentation fault
/ # php test.php