2012-02-24 9 views
3

私はPHPスクリプトからSSH経由でリモートサーバー上でコマンドを実行しようとしています。私は、コマンドラインから実行した場合、それは通常のログインシェルを持つユーザーと自分の.sshディレクトリとして実行しているので、.sshディレクトリを作成せずにsshコマンドを実行することはできますか?

$ssh_command = "ssh -F keys/config -o UserKnownHostsFile=keys/known_hosts -i keys/deployment_key -p $ssh_port $r 
    $git_fetch = "git --git-dir=$remote_path/.git --work-tree=$remote_path fetch 2>&1"; 
    exec("$ssh_command '$git_fetch' 2>&1", $out); 

スクリプトは、正常に動作します:ここでは、スニペットです。 SSHがApacheユーザーのホームディレクトリに.sshディレクトリを作成できないため、Webインターフェイス経由でスクリプトを実行しようとすると失敗します。

SSHを.sshディレクトリなしで使用することは可能ですか、またはApacheユーザーとしてSSHを実行するための別の方法がありますか?私は、Apacheユーザーの.sshフォルダを作成しないことをお勧めします。

+0

私は困惑しています。あなたは味とは別の理由がありますか? Apacheプロセスから特定の要求を受け取り、応答を返す別のユーザーアカウントで実行されているサービス内でSSHをコンパートメント化することは実際には価値がありますか? – minopret

+0

PHP SSH2ライブラリを使用したくない主な理由は、私がPECLを一切扱わないことでした。受け入れられた答えの解は良いものだと思います。 – Rafe

答えて

3

私はphpseclib, a pure PHP SSH implementationでそれを行うだろう:

<?php 
include('Net/SSH2.php'); 

$key = new Crypt_RSA(); 
//$key->setPassword('whatever'); 
$key->loadKey(file_get_contents('privatekey')); 

$ssh = new Net_SSH2('www.domain.tld'); 
if (!$ssh->login('username', $key)) { 
    exit('Login Failed'); 
} 

echo $ssh->read('[email protected]:~$'); 
$ssh->write("ls -la\n"); 
echo $ssh->read('[email protected]:~$'); 
?> 

唯一の他の事私は、彼らはPHP SSHライブラリはPECL拡張モジュールであると言うときに参照する人々を想像することができます。私はそれがかなりひどく書かれているので、個人的にそれを使用することをお勧めしたいと思います。インストールが難しく、ひ​​どくサポートされているという事実は、公開鍵と秘密鍵を提供する必要があります。 phpseclibは秘密鍵だけを必要とします。これは、秘密鍵には通常、その中に埋め込まれた公開鍵が含まれているので意味があります。 PECL SSH2拡張機能は、個別に抽出する必要があります。これは愚かです。

phpseclibは、PECL SSH2ライブラリよりもさらに多くのフォーマットをサポートしています。 phpseclibは、PuTTYキーフォーマット、XML署名キーなどをサポートします。

0

いいえ、OpenSSHクライアントを使用する場合は、ユーザーの自宅に.sshが必要です。これを避ける方法はありません。これは、統合設定が含まれているため、セキュリティ機能であることを意味します。空のダミーディレクトリを保持するだけで、クライアントはそこに書き込まれませんが、適切なユーザー権限が必要です。

+0

これはPHP SSH2ライブラリを使用する場合にも必要ですか? – Rafe

+1

AFAIKでは、このような制限なしにSSH2ライブラリを使用できます。言い換えれば:それは解決策になります。 –

3

私は1つの小さな問題/副作用でこの制限を回避することができます。

オプションUserKnownHostsFile=/dev/nullStrictHostKeyChecking=noを設定すると、SSHを実際には格納していないか、ホスト鍵の検証が必要なものにすることができます。

を「いいえ」に設定すると、キーを最初に認識または確認せずにサーバーに接続できます。 /dev/nullUserKnownHostsFileに使用するだけで、何も読み書きしないので、保存された値は読み取られません。

SSHはまだ.sshディレクトリを作成しようとしていますが、失敗すると警告が表示され、接続が続行されます。警告は出力に含まれます(警告を抑制しない限り)。

ここは例です。注:この例では、認証を設定していないので、パスワードの認証と失敗を試みますが、IDを使用しているので、正常に接続できるはずです。

<?php 
$ssh_command = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no " 
       ."-p 2223 [email protected]"; 

exec("$ssh_command ls 2>&1", $out); 

var_dump($out); 

// output when called from browser running as daemon(1) 
array(5) { 
    [0]=> 
    string(44) "Could not create directory '/usr/sbin/.ssh'." 
    [1]=> 
    string(110) "Warning: Permanently added '[host.localdomain]:2223,[192.168.88.20]:2223' (RSA) to the list of known hosts." 
    [2]=> 
    string(36) "Permission denied, please try again." 
    [3]=> 
    string(36) "Permission denied, please try again." 
    [4]=> 
    string(82) "Received disconnect from 192.168.88.20: 2: Too many authentication failures for user" 
} 

あなたの出力は、最も可能性の高い出力のみが続く恒久的に知られているホスト(/dev/null)のリストにホストを追加することについての警告、続く、.sshディレクトリを作成できないという最初の警告が含まれますあなたの命令から。最初の行がこの警告であるかどうかを確認し、$out配列からそれをシフトさせる必要があります。

もう1つの注意:悪意のあるサーバーへの接続を試みるために、中間者攻撃やDNS/IPハッキングの可能性があります。

シマンテックのSSH Host Key Protectionに関する記事を参照してください。

+1

known_hostsファイルの場所を手動で指定することもできます。これにより、man-in-the-middle攻撃に対する脆弱性を開放することなく、デフォルトの場所を避けることができます。 – Rafe

0

解決策:

Do not do this。私は長年に渡ってPHPを使用していませんが、現代の汎用プログラミング言語では、これは巨大なWTFになります。私は、PHP SSH2ライブラリの使用についてコミットした1人のユーザーに気付きました。これは、IMHOに行く方法です。

コマンドを実行するためにシェルに飛び出すことは、結果が重要でない副作用を引き起こしている場合にのみ発生します。重要なことにこれを頼りにしている場合や、コマンドの結果がプログラムの状態を何らかの形で変更する必要がある場合は、これを処理するための内部ライブラリを探したり、適切なC言語ライブラリ。それ以外の場合、あなたは傷ついている世界のために自分自身を設定しています。

0

問題は、SSHが最初に探すのはユーザーの構成ファイルだということです。 -Fフラグを使用して、独自の設定ファイルの場所を指定することができますが、これは問題を解決するはずですが、私はすぐに作業を開始していますので、これを二重チェックしませんでした。アイデンティティファイル& c。のような他のものの場所を指定する必要があります。ファイルは正しい所有権とアクセス権を持っている必要があります。そうしないとSSHが不平を言います。

つまり、SSH2のようなSSHライブラリを使用することは可能な限り大いに優れた解決策です。

+0

他の場所で設定ファイルを探すように言っても、実際にはまだ作成したいと思っています。 – Rafe

0

〜/ .sshがHOME環境変数を使用して着陸する場所を制御できます。そうすれば、Apacheが提供するディレクトリではないと確信できます。