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

PHP 連接遠端 MySQL 失敗排查:SELinux 阻擋連線的解決方案

     編輯:PHP 綜合知識

問題現象

三台伺服器:A、B、C。C 為 MySQL 資料庫伺服器,已開放遠端連線。
B 可正常用 PHP 連線 C。
A 同樣代碼、同樣參數,連線失敗(通常為 Can't connect to MySQL server 或 Permission denied)。

排除項目:

  • 代碼無誤(B 正常)
  • MySQL 權限正確(B 正常)
  • 防火牆/安全組已放行 3306
  • php.ini 無特殊限制

根因:SELinux 限制 Apache/PHP 對外網路連線

對比 A、B 兩台伺服器 /etc/selinux/config,發現 A 為 Enforcing,B 為 Disabled 或 Permissive。
SELinux 預設禁止 httpd 進程發起外部網路連線(httpd_can_network_connect = off)。

解決方案

方法一:永久關閉 SELinux(簡單粗暴,生產環境慎用)

# 1. 編輯配置
vim /etc/selinux/config
# 修改
SELINUX=disabled
# 2. 重啟生效
reboot
# 或臨時生效(無需重啟)
setenforce 0

方法二:精準開放 httpd 網路連線權限(推薦,保持 SELinux 啟用)

# 檢查當前布林值
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

-P 參數寫入持久化策略,重啟後依然生效。

方法三:若連線特定埠(非 3306)需額外開放

# 允許 httpd 連線任意埠
setsebool -P httpd_can_network_connect on

# 或針對特定埠(如 3306)透過 semanage
yum install policycoreutils-python-utils
semanage port -a -t mysqld_port_t -p tcp 3306
# 確認
semanage port -l | grep mysqld_port_t

驗證修復

<?php
$mysqli = new mysqli('db-server-c', 'user', 'pass', 'dbname', 3306);
if ($mysqli->connect_errno) {
    die("連線失敗: " . $mysqli->connect_error);
}
echo "連線成功!Server version: " . $mysqli->server_info;
$mysqli->close();

在 A 伺服器執行,應顯示「連線成功!」

補充:其他常見誤區

  • 以為是 PHP 模組缺失: php-mysqlnd 已安裝(B 正常即證明)。
  • 以為是 MySQL bind-address: C 已設 0.0.0.0 或具體 IP(B 正常即證明)。
  • 以為是防火牆: iptables/nftables/firewalld 已放行(B 正常即證明)。
  • 以為是 PHP 程式碼 bug: 同一份代碼在 B 正常,排除代碼問題。

結語

當「同樣代碼、同樣網路、同樣資料庫」只在特定伺服器連線失敗時,優先檢查 SELinux。使用 setsebool -P httpd_can_network_connect on 精準放行,比完全關閉 SELinux 更安全、更專業。

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