leo
leo

Reputation: 31

php-fpm crashed when curl or file_get_contents request a https url

My server is nginx + php-fpm

code below will cause the bug

file_get_contents('https://github.com');

or

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://github.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch); //crash here
curl_close($ch);

the webpage shows 502 error

nginx log is

[error] 2656#0: *541 recv() failed (104: Connection reset by peer) while reading response header from upstream

fpm log is

Jul 03 00:37:37.619903 [NOTICE] fpm_got_signal(), line 48: received SIGCHLD

Jul 03 00:37:37.619926 [WARNING] fpm_children_bury(), line 215: child 3567 (pool default) exited on signal 11 SIGSEGV (core dumped) after 417.576755 seconds from start

Jul 03 00:37:37.620807 [NOTICE] fpm_children_make(), line 352: child 4193 (pool default) started

If the request url starts with http:// , everything is OK .

php configure command is

'./configure' '--prefix=/www/nginx_php-5.2.17' '--with-config-file-path=/www/nginx_php-5.2.17/etc' '--with-mysql=/www/mysql' '--with-iconv=/usr' '--with-freetype-dir' '--with-jpeg-dir' '--with-png-dir' '--with-zlib' '--with-libxml-dir=/usr' '--enable-xml' '--disable-rpath' '--enable-discard-path' '--enable-inline-optimization' '--with-curl' '--enable-mbregex' '--enable-mbstring' '--with-mcrypt=/usr' '--with-gd' '--enable-gd-native-ttf' '--with-openssl' '--with-mhash' '--enable-ftp' '--enable-sockets' '--enable-zip' '--enable-fastcgi' '--enable-fpm' '--with-fpm-conf=/www/etc/php-fpm.conf'

Upvotes: 3

Views: 2569

Answers (2)

404 Not Found
404 Not Found

Reputation: 3665

I recently had to deal with a similar issue. Without getting too deep into the details, the issue was that the combination of an older PHP version (built from source) with newer cURL and OpenSSL libraries from the package manager caused a conflict due to incompatible versions.

The basic steps I ended up doing to fix the issue were to install cURL and OpenSSL from the distro package manager. Use them to download the source packages for compatible cURL and OpenSSL versions. Uninstall cURL. Build OpenSSL from source, then build cURL, configured to use the OpenSSL I just built. From there, I was able to build PHP using the newly built cURL and OpenSSL libraries.

This is the snippet of the install script I ended up with:

# [curl should have been installed from package manager before this]
# Note: This script is based on Ubuntu 18. Paths may differ for different distributions. 

cd /usr/local/src

# Download OpenSSL and cURL sources first, using the pre-installed version of cURL. 
curl -SL --progress-bar https://www.openssl.org/source/old/1.0.2/openssl-1.0.2n.tar.gz -o openssl-1.0.2n.tar.gz
curl -SL https://curl.se/download/curl-7.65.0.tar.xz -o curl-7.65.0.tar.xz

# Remove the pre-installed cURL, we'll rebuild it from the source bundle,
# using the shared libraries from the OpenSSL version we will build now. 
apt-get remove -y --purge curl

# Extract and build OpenSSL from source package, making sure to enable the `shared` option
# so that `libssl.so` and `libcrypto.so` shared libraries are built, too. 
tar xvf openssl-1.0.2n.tar.gz
cd openssl-1.0.2n
./config shared # add the `-d` flag to include debug symbols
make -j 10
make install_sw

# Add a new config file for the dynamic linker, so that it knows to look for the new shared libraries we're building. 
# The first line is for where the new cURL libs will be, and the latter is where new OpenSSL libs will be.
echo -e "/usr/local/lib \n/usr/local/ssl/lib" > /etc/ld.so.conf.d/local.conf

# Reload the linker cache
ldconfig

cd /usr/local/src

# Extract and build cURL from source package, making sure to tell it to use the OpenSSL version we just built. 
tar -xvf curl-7.65.0.tar.xz
cd curl-7.65.0
./configure --with-ssl=/usr/local/ssl # add the `--enable-debug` flag to include debug symbols
make -j 10
make install

# Reload the linker cache
ldconfig

cd /usr/local/src

# Reload utility (bin) locations; find the newly built `curl` binary. 
hash -r

curl -SL --progress-bar http://www.php.net/distributions/php-5.5.38.tar.bz2 -o php-5.5.38.tar.bz2
tar -xvf php-5.5.38.tar.bz2
cd php-5.5.38

# Make sure the `--with-openssl` flag includes a path to the SSL libs created after building it from source. 
# `--with-curl`, by default, will look in `/usr/local/lib` and `/usr/local/include`; When built from source, 
# the generated libraries WILL be placed here, so you shouldn't need to specify the path, unless you put them elsewhere
# or your distro uses different paths
./configure \
    --with-openssl=/usr/local/ssl \ 
    --with-curl \
    # Any other config flags here
    # Other flags were omitted for this example

make -j 10
make install

Note: I wrote this for a testing and development environment. Even ignoring that it's using PHP 5.5, this may not be suitable for a production environment.

Upvotes: 0

CodeAngry
CodeAngry

Reputation: 12985

Try adding these two:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

They will prevent the verification of the SSL certificate. This might be the issue as the verification might fail. Unless it's mandatory to verify the source, always add these 2 lines when downloading data with cURL.

PS: Not sure this will help you though.

Upvotes: 1

Related Questions