2012-02-24 5 views
3

Я пытаюсь запустить команду на удаленном сервере через SSH из скрипта PHP. Вот фрагмент кода:Возможно ли выполнить команду 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. Когда я пытаюсь запустить скрипт через веб-интерфейс, он терпит неудачу, потому что SSH не может создать свой .ssh-каталог в домашнем каталоге пользователя Apache.

Можно ли использовать SSH без каталога .ssh или есть ли другая альтернатива для запуска SSH в качестве пользователя Apache? Я бы предпочел не создавать папку .ssh для пользователя Apache.

+0

Я озадачен. У вас есть причины, кроме вкуса? Стоит ли разделять SSH в сервисе, запущенном под другой учетной записью пользователя, которая принимает конкретные запросы и дает ответы на ваш процесс Apache? – 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. Я лично рекомендовал бы не использовать это, потому что это очень плохо написано. Тот факт, что его сложно установить и плохо поддерживать в стороне, требует наличия открытых и закрытых ключей. Для phpclib требуется только закрытый ключ. Это имеет смысл, потому что закрытые ключи обычно содержат открытый ключ, встроенный в них. Расширение PECL SSH2 требует, чтобы он извлекался отдельно, что глупо.

phpseclib также поддерживает более тонны форматов, чем библиотека PECL SSH2. phpseclib поддерживает формат ключа PuTTY, ключи XML-подписи и т. д.

0

Нет, вам нужен .ssh в доме пользователя при использовании клиента OpenSSH. Невозможно избежать этого - это значит, что это функция безопасности, поскольку она содержит встроенные настройки. Просто сохраните пустой каталог-заглушку - клиент не будет писать там, но вы должны иметь соответствующие права пользователя на него.

+0

Это также необходимо, если вы используете библиотеку PHP SSH2? – Rafe

+1

AFAIK вы можете использовать библиотеку SSH2 без каких-либо ограничений. Другими словами: Это было бы решением. –

3

Я могу обойти это ограничение с помощью одной маленькой проблемы/побочного эффекта.

Установка параметров UserKnownHostsFile=/dev/null и StrictHostKeyChecking=no, вы можете обмануть SSH, фактически не сохраняя или требуя проверки ключа хоста.

Установка StrictHostKeyChecking no no позволяет подключиться к серверу, не зная или не проверив его ключ; и с использованием /dev/null для UserKnownHostsFile просто читает и ничего не пишет, поэтому никакие значения никогда не считываются из сохраненных.

Предостережение состояло в том, что SSH по-прежнему пытается создать каталог .ssh и выходит из строя, но сбой приводит к предупреждению и продолжит соединение. Предупреждение будет включено в ваш выход (если вы не подавите предупреждения).

Вот пример. Примечание. В этом примере я не настроил аутентификацию, поэтому попытаюсь использовать аутентификацию пароля и выйти из строя, но поскольку вы используете идентификатор, вы должны иметь возможность подключиться просто отлично.

<?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" 
} 

Ваш выход, скорее всего, включать только первое предупреждение о невозможности создать каталог .ssh, а затем предупреждение о постоянно добавляя хост в список известных хостов (/dev/null), а затем на выходе из вашей команды; поэтому вам нужно будет проверить, была ли первая строка этой предупреждающей, и сдвинуть ее из массива $out.

Другое примечание: Это открывает возможность нападений «человек в середине» или взлома DNS/IP, чтобы попытаться подключиться к серверу-изгои.

См. Эту статью от SSH Host Key Protection от Symantec.

+1

Вы также можете вручную указать местоположение файла known_hosts, что я и сделал. Это позволяет избежать расположения по умолчанию, не открывая уязвимость для атак типа «человек в середине». – Rafe

0

НЕ ДЕЛАЙТЕ ЭТО. Я не использовал PHP в течение многих лет, но на любом современном языке программирования общего назначения это было бы огромным WTF. Я заметил, что один пользователь подключился к использованию библиотеки PHP SSH2 ... это был бы путь, ИМХО.

Выпрыгивание в оболочку для выполнения команды должно ТОЛЬКО возникать, когда вы создаете побочный эффект, когда результат является несущественным.Если вы полагаетесь на это для чего-либо важного или если результат команды должен каким-либо образом изменить состояние программы, вам либо нужно найти внутреннюю библиотеку для ее обработки, либо расширить язык, чтобы сделать это правильно через соответствующий C библиотеки. В противном случае вы настраиваете себя на мир боли.

0

Проблема в том, что первое, что ищет SSH, - это файл конфигурации пользователя. Вы можете использовать флаг -F, чтобы указать местоположение вашего собственного файла конфигурации, который должен решить проблему, хотя я спешу работать прямо сейчас, поэтому я не проверил это дважды. Вам нужно указать местоположение других вещей, таких как файлы идентификаторов, & c., Внутри него, ум. Файл должен иметь правильное право собственности и разрешения, или SSH будет жаловаться.

Это говорит о том, что использование SSH-библиотеки, такой как SSH2, является гораздо лучшим решением для обстрела, если это вообще возможно.

+0

Да, он на самом деле все еще хочет создать его, даже если вы скажете ему искать файл конфигурации в другом месте. – Rafe

0

Вы можете контролировать, где ~/.ssh будет работать с использованием переменной среды HOME. Таким образом, вы можете быть уверены, что это не будет каталог Apache.

Смежные вопросы