2008-11-21 281 views
18

我想通過SSH建立一個ssh隧道到我的mysql服務器。通過SSH在PHP連接到MySQL服務器

理想情況下,我會返回一個mysqli數據庫指針,就像我直接連接。

我在沒有SSH2庫的共享主機上,但我可能能夠使用PECL在本地安裝它們。

如果有一種方法使用原生命令,那就太好了。

我在想這樣的事情,但沒有這些庫,它將無法正常工作。

$connection = ssh2_connect('SERVER IP', 22); 

ssh2_auth_password($connection, 'username', 'password'); 

$tunnel = ssh2_tunnel($connection, 'DESTINATION IP', 3307); 

$db = new mysqli_connect('127.0.0.1', 'DB_USERNAME', 'DB_PASSWORD', 
         'dbname', 3307, $tunnel) 
    or die ('Fail: ' . mysql_error()); 

任何人有任何想法?我正在Liquidweb上運行共享的CentOS Linux主機。

任何關於使隧道持續的想法?是否可以使用另一個腳本來建立它,並在PHP中利用它?

謝謝。

+0

您意識到該共享主機上的其他人也將能夠連接到您的數據庫嗎? – Zoredache 2008-11-21 18:01:23

+0

它仍然需要有效的用戶名和密碼才能連接,但這是一個明確的風險。如果隧道是在php中每次執行創建的,情況會是這樣嗎? – 2008-11-21 18:09:48

+0

我刪除了我以前的答案,正如我在閱讀文檔時注意到的那樣,它比我想要獲得mysqli使用SSL更多。 – Powerlord 2008-11-21 18:20:38

回答

0

埃裏克,

我認爲你在這一個運氣不好。你可以在你的PHP代碼中使用ssh擴展,或者你可以訪問服務器,你可以嘗試在命令行上創建一個ssh隧道。

雖然你可能需要特殊的權限來做到這一點。它也看起來像你沒有ssh訪問這個託管帳戶。

--Joao

1

我認爲最好的辦法是找到一個不同的託管服務提供商;我建議一個VPS解決方案(虛擬專用服務器),它可以讓你完全控制你的網絡主機。那麼,如果你不喜歡默認配置,你可以自己升級它。

14

我會使用autossh工具來創建一個持久的ssh隧道到你的mysql數據庫。然後,您只需將PHP代碼指向localhost即可。

您可以在此(沒有自動啓動)做測試:

ssh -L 3306:localhost:3306 [email protected] 

設置一個SSH密鑰,這樣你就不需要使用密碼,以及調整MySQL的系統上的.ssh/authorized_keys文件只允許它用於端口轉發。

有關ssh技巧的更多信息,請參閱Brian Hatch's關於SSH和端口轉發的優秀系列。

+0

這個答案讓我走上了正確的軌道。我終於明白了這一點:http://stackoverflow.com/questions/464317/connect-to-a-mysql-server-over-ssh-in-php#comment65229024_16138417 – Ryan 2016-08-13 19:59:17

2

可能,但爲什麼?它比需要更復雜,並且容易出錯。

你不能在本地運行數據庫嗎?如果沒有,你不能使用SQLite,XML文件或其他不需要單獨服務器守護進程的東西嗎?

真的不想初始化PHP腳本中的隧道。初始化一個SSH隧道需要很長時間(可以輕鬆一秒鐘或兩秒鐘),這意味着每個連接到數據庫的頁面在加載時都會有2秒的延遲。

如果做到這一點(我強烈反對),最好的方法是將有維持在後臺連接的腳本..

設置一個SSH keypair。然後使用autossh或執行所需SSH命令的簡單腳本,等到該進程死亡並重新啓動。它可能更智能,每10-20秒嘗試運行一次命令,如果失敗則重新連接。

使用SSH密鑰對,你就不必硬編碼在腳本中的遠程用戶的密碼。我建議限制遠程用戶可以做什麼(通過使用專用的隧道用戶,並給它一個受限制的shell,請參閱this問題)

總之,我強烈建議先嚐試SQLite,然後看看它是如何可行的使用XML文件存儲數據,然後嘗試竊聽您的Web主機獲取本地MySQL服務器,然後然後查看SSH隧道選項。

6

我做SSH都是由根證書和公共密鑰對嘗試過。它允許我通過命令行而不是通過PHP代碼。我也試過創建一個隧道(通過使用SSH2函數),並從PHP代碼運行shell命令(systemexec等);沒有工作。

最後我想SSH2函數執行shell命令,它終於摸索:)

這裏是我的代碼,如果它可以幫助你:

$connection = ssh2_connect($remotehost, '22'); 
if (ssh2_auth_password($connection, $user,$pass)) { 
    echo "Authentication Successful!\n"; 
} else { 
    die('Authentication Failed...'); 
} 


$stream=ssh2_exec($connection,'echo "select * from zingaya.users where id=\"1606\";" | mysql'); 
stream_set_blocking($stream, true); 
while($line = fgets($stream)) { 
    flush(); 
    echo $line."\n"; 
} 

試試這個,如果要專門使用PHP函數。

6

隧道必須在SQL操作(一個或多個)的過程中,可以保持開放。從RJMetrics以下舉例說明:

這裏是通用的SSH命令語法:

ssh -f -L bind-ip-address:bind-port:remote-ip-address:remote-port \ 
[email protected] [command] >> /path/to/logfile 

以下是如何安全地建立在短短2行的PHP代碼遠程數據庫的連接:

shell_exec("ssh -f -L 127.0.0.1:3307:127.0.0.1:3306 [email protected] sleep 60 >> logfile"); 
$db = mysqli_connect("127.0.0.1", "sqluser", "sqlpassword", "rjmadmin", 3307); 

我們使用shell_exec()函數創建具有60秒打開窗口的隧道,然後使用mysqli_connect()函數使用轉發的端口打開數據庫連接。請注意,我們必須在這裏使用「mysqli」庫,因爲mysql_connect()不允許我們指定端口,而mysql_*函數已棄用。

sleep 60:當涉及到的隧道連接,我們基本上有兩種選擇:離開連接打開所有的時間或將其打開,並根據需要將其關閉。我們更喜歡後者,因此我們在建立隧道時沒有指定-N選項,這會使其保持打開狀態,直到手動終止進程(對自動化不利)。由於沒有指定-N,所以只要SSH會話沒有被用於任何事情,我們的隧道就會自動關閉。這是理想的行爲,除了創建隧道和我們通過隧道啓動並運行MySQL連接之間的幾秒之外。爲了在此期間購買我們一段時間,我們在創建隧道時發出無害的sleep 60命令,這基本上會讓我們花費60秒在隧道關閉之前讓其他東西通過隧道。只要在這個時間框架內建立了MySQL連接,我們就已經完成了。