前一段时间也就是 7月1号,OpenSSH 服务端有个高危 RCE 漏洞:CVE-2024-6387
赶着去给服务端升级了下,并重启了服务器
apt update && apt upgrade =y
更新系统之后,不知道为什么手贱去升级了一下 php 8.1
升级时秒报错,没有日志输出,没在意,因为当时服务没挂
结果一两天后发现跑着 php8.1 的网站寄了,检查后台发现php8.1服务掉了,无法启动,报错
/www/server/php/81/sbin/php-fpm: symbol lookup error: /www/server/php/81/sbin/php-fpm: undefined symbol: EVP_md2, version OPENSSL_1_1_0
然后还发现不只是没安装的版本也无法安装,比如 8.3,而是所有 php 版本都是会报这个错误及安装失败,文件不存在:xxxxxxx
原因是宝塔在系统安装了多个 openssl 版本,php 编译时并不是系统的版本,而是特定的 openssl 1.1.1 版本,结果 PHP-FPM 在运行时使用了非 OpenSSL 1.1.1 版本,或者说没有找到 openssl 1.1.1 版本的库路径,导致符号查找错误
我直接去改安装脚本 /www/server/panel/install/php.sh
,发现宝塔没具体定义 8.1 使用的特殊编译参数,而是把它作为 if xxxx else 兜底规则的一部分进行处理,其默认参数如下
在第 645 行左右,上面是 php8.3 的 编译配置段落 if [ "${version}" == "8.3" ];then
,接着下一个的兜底处理 else
后面跟着的 ./configure xxxxxxxxxxxxxxxxxx
原本是
./configure --prefix=${php_setup_path} --with-config-file-path=${php_setup_path}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --di sable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-intl --enable-pcntl --enable-ftp --enable-gd --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-mbstring --disable -fileinfo --enable-opcache --with-sodium=/usr/local/libsodium --with-webp ${i_make_args}
修改一下 --with-openssl
参数指定具体安装的 openssl 1.1.1 库路径,改成 --with-openssl=/usr/local/openssl111
,修改后如下
./configure --prefix=${php_setup_path} --with-config-file-path=${php_setup_path}/etc --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype --with-jpeg --with-zlib --with-libxml-dir=/usr --enable-xml --di sable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-intl --enable-pcntl --enable-ftp -- enable-gd --with-openssl=/usr/local/openssl111 --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-soap --with-gettext --enable-mbstring --disable -fileinfo --enable-opcache --with-sodium=/usr/local/libsodium --with-webp ${i_make_args}
这还不够,最多就编译成功,我测试时,编译日志能看到 -I/usr/local/openssl111/include
,但是 php-fpm 还是无法启动
这里估计是没有使用编译时的 openssl 版本,手动检查下,查看 php-fpm 链接的 openssl 版本
ldd /www/server/php/81/sbin/php-fpm | grep ssl
返回内容
libssl.so.1.1 => /usr/local/openssl111/lib/libssl.so.1.1 (0x00007fc46143c000)
libcrypto.so.1.1 => /usr/local/openssl111/lib/libcrypto.so.1.1 (0x00007fc45f8fd000)
libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007fc45ead3000)
可以看到 php-fpm 的确链接到了 openssl 1.1.1, libssl.so.1.1 => /usr/local/openssl111/lib/libssl.so.1.1
但是 libssl.so.3 => /lib/x86_64-linux-gnu/libssl.so.3 (0x00007fc45ead3000)
表明系统的确用的是 OpenSSL 3.0.2
启动时没有正确识别到 openssl 1.1.1,而是使用了系统的 openssl 3.0.2,这时要配置一下库路径防止它弄混了
echo "/usr/local/openssl111/lib" | sudo tee /etc/ld.so.conf.d/openssl-1.1.1.conf
接着刷新一下更新共享库缓存
ldconfig -v
接着手动安装 php 8.1
/www/server/panel/install/php.sh install 81
最后就能用了,也能正常安装扩展了