Тема: Как сделать API из любой команды
Намедни понадобилось выполнять команды на другом сервере. Можно конечно и через SSH, но захотелось чего-то новенького. Тут просто пример, нет никакой защиты так как создано для общения двух внутренних систем где все строго ограничивается фаерволом, но добавить SSL и авторизацию с ограничением IP с которых можно посылать запросы не составит никакого труда...
Для реализации я применил PHP, не потому что я его люблю, просто когда я что-то делаю с perl'ом на меня очень криво смотрят, да и программировать на нем мало кто умеет.
Идея достаточно просто, подать команды в бинарник на удаленном сервере и полечить обратно ответ о результате выполнения. Реализация первая и последняя так как в последствии выяснилось что есть нормальный API интерфейс HTTP+XML. Но не пропадать же добру кому надо - пользуйтесь...
#!/usr/bin/php
<?php
/*
how to use
echo "-m module_name -o json pricelist" | base64 | awk '{print "1234567890"$1}' | nc 127.0.0.1 1001
*/
$pass = "1234567890";
$server = stream_socket_server("tcp://127.0.0.1:1001", $errno, $errorMessage);
if ($server === false) {
throw new UnexpectedValueException("Could not bind to socket: $errorMessage");
}
while ($conn = @stream_socket_accept($server,-1)) {
$auth = false;
$msg=fread($conn, 1024);
if (strlen ($msg) > 10) {
$pass2="";
for ($i=0; $i<10; $i++) {
$pass2 .= $msg[$i];
}
if ($pass==$pass2) {
$auth=true;
$msg = base64_decode(substr($msg, 10));
}
}
if ($auth === true) {
exec ("/path/to/mgrctl ".$msg,$mgrctl_out);
$back_text = "";
foreach ($mgrctl_out as $val) {
$back_text .= $val."\n";
}
stream_socket_sendto ($conn,base64_encode($back_text));
fclose($conn);
} else {
stream_socket_sendto ($conn,"Auth error\n");
fclose($conn);
}
}
fclose($conn);
?>
Коротко о скрипте, его надо демонезировать и повесить на любой порт/ip по вкусу. Скрипт открывает TCP сокет и принимает запросы в формате пароль+base64(команда) возвращает ответ в base64 формате.
Пример как посылать запросы
<?php
error_reporting(E_ALL);
$service_port = "1001";
$address = "111.111.111.111";
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) die ("socket_create() failed: reason: ".socket_strerror(socket_last_error())."\n");
$result = socket_connect($socket, $address, $service_port);
if ($result === false) die ("socket_connect() failed.\nReason: ($result) ".socket_strerror(socket_last_error($socket))."\n");
$in = "1234567890LW0gbW9kdWxlX25hbWUgLW8ganNvbiBwcmljZWxpc3QK\r\n";
$out = '';
socket_write($socket, $in, strlen($in));
while ($out = socket_read($socket, 2048)) {
echo $out;
}
socket_close($socket);
?>
формируем запрос и отправляем на нужный IP и порт, получаем строку в формате base64, дальше ее нужно раскодировать и использовать...