首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

解決 PHP 無法連接遠程 MySQL:SELinux 阻擋導致的隱性故障排查

     編輯:PHP 相關知識

同一代碼、同一 MySQL 賬號,機器 B 能連、機器 A 卻報 SQLSTATE[HY000] [2003] Can't connect to MySQL server。排除代碼、授權、防火牆、php.ini 後,真兇往往是 SELinux 策略阻擋 HTTPD 進程發起網絡連接。本文記錄排查全過程與一鍵修復方案。

故障現象

  • 三台服務器:A(故障)、B(正常)、C(MySQL 主機)
  • B 能用 PHP 連接 C 的 MySQL,A 連不上
  • 代碼、MySQL 用戶權限、防火牆(iptables/firewalld)均已排查一致
  • telnet C_IP 3306 通,mysql -h C_IP -u user -p 也能連
  • 唯獨 PHP-FPM/Apache 進程發起的連接失敗

根因定位:SELinux

對比 /etc/selinux/config 發現:

  • 機器 A:SELINUX=enforcing
  • 機器 B:SELINUX=disabled 或 permissive

SELinux 在 enforcing 模式下,默認策略 禁止 httpd_t 域進程主動發起 TCP 連接(httpd_can_network_connect = off),導致 PHP 連接遠程 MySQL 被內核攔截。

修復方案(二選一)

方案一:永久關閉 SELinux(簡單粗暴,生產環境需評估風險)

# 1. 編輯配置
vim /etc/selinux/config
# 修改
SELINUX=disabled

# 2. 重啟生效(或臨時生效:setenforce 0)
reboot

方案二:精準開放策略(推薦,保持安全基線)

# 檢查當前策略
getsebool httpd_can_network_connect
# 輸出: httpd_can_network_connect --> off

# 永久開放(重啟不失效)
setsebool -P httpd_can_network_connect on

# 驗證
getsebool httpd_can_network_connect
# 輸出: httpd_can_network_connect --> on

此策略專門允許 HTTPD 進程發起網絡連接(含 MySQL、PostgreSQL、HTTP API 等),不降低整體安全等級。

驗證修復

<?php
$pdo = new PDO("mysql:host=REMOTE_IP;dbname=test", "user", "pass");
echo "連接成功!";
?>

刷新頁面,不再報 2003 錯誤,即修復成功。

排查思路總結

  1. 代碼層面:同一代碼在 B 正常 → 非代碼問題
  2. 數據庫層面:B 能連 → 非授權/防火牆/端口問題
  3. 網絡層面:telnet/mysql 客戶端能連 → 非網絡不通
  4. 進程上下文:唯獨 Web 進程(httpd/php-fpm)失敗 → SELinux 策略差異
  5. 對比關鍵配置 /etc/selinux/config → 定位根因

經驗之談:CentOS/RHEL 系列默認開啟 SELinux,遷移部署時必須檢查。建議採用「方案二」精準放行,兼顧安全與功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved