PHP Curl通过VPN访问服务器异常:命令行正常Apache下挂起
这种命令行正常、Apache环境挂起的情况,核心原因几乎都是两种运行环境的用户上下文、网络配置不一致导致的,我给你梳理几个最常见的排查方向:
先模拟Apache用户的命令行环境测试
这是最快定位问题的方法:用Apache的运行用户(通常是www-data或apache)执行命令行PHP,比如运行sudo -u www-data php -a,然后输入同样的curl代码。如果这里也挂起,那问题就锁定在用户权限/环境上了;如果能正常运行,再去查Apache的配置差异。检查OpenVPN的路由与用户权限
OpenVPN的连接有时候会绑定到启动它的用户,路由规则可能只对该用户生效。而Apache的运行用户可能没有权限访问OpenVPN的隧道接口,或者路由表中没有指向公司内网的条目。
你可以对比命令行用户和Apache用户的路由表:命令行下跑ip route,找到访问status.int.companyname.com对应的路由(通常是指向tun0这类OpenVPN接口),然后切换到Apache用户(sudo -u www-data bash)再跑ip route,看是否有这条路由。如果没有,需要把这条路由添加为系统全局路由,或者调整OpenVPN的配置让路由对所有用户生效。排查DNS解析问题
命令行用的DNS服务器能正确解析内网域名,但Apache的PHP可能用了不同的DNS配置。你可以先在脚本里直接用目标服务器的内网IP代替域名测试,如果能正常获取数据,那就是DNS的问题。
临时解决可以在curl里强制指定解析:curl_setopt($ch, CURLOPT_RESOLVE, ['status.int.companyname.com:443:192.168.1.100']); // 替换成实际的内网IP和端口长期解决要确保Apache用户的DNS配置(比如
/etc/resolv.conf)和命令行用户一致,或者在php.ini里设置curl.dns_server指定正确的DNS服务器。检查SSL证书与Curl配置差异
如果目标接口是HTTPS,可能命令行的PHP信任公司的自签名证书,但Apache的PHP没有配置对应的CA证书。你可以临时添加curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);(仅测试用,生产环境别这么干)来排除证书问题。另外对比命令行php -i | grep curl和Apache下phpinfo()的curl配置,看curl.cainfo等参数是否一致。排查SELinux或防火墙限制
很多Linux系统默认开启SELinux,它可能会阻止Apache发起出站网络请求。你可以先临时关闭SELinux(sudo setenforce 0)测试,如果脚本恢复正常,就需要添加SELinux规则允许Apache访问网络。另外检查防火墙规则,看是否限制了Apache用户的出站连接。
内容的提问来源于stack exchange,提问作者peteredhead

