В этой статье я рассказывал, как собрать rpm-пакет. Основой приложения служили php скрипты, которые создавали OpenVPN-сервер, клиентов и могли выслать сертификаты на email. Попробуем прикрутить их к бэкэнду веб-сервера.
Для работы из консоли использовался массив $argv с параметрами команда:ключ. Такой формат записи удобен для форматирования в json. Т.о. чтобы превратить наш core_v1.php в web-api (core_web.php) все что нам нужно — это написать две строчки:
1 2 |
$content = file_get_contents("php://input"); $command = json_decode($content, TRUE); |
По факту чего мы получим тот же массив $command, который формировали из $argv. Также добавим хидер:
1 2 |
header("Content-type: text/txt; charset=utf-8"); |
Полный текст скрипта core_wep.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
<?php $content = file_get_contents("php://input"); $command = json_decode($content, TRUE); header("Content-type: text/txt; charset=utf-8"); if(isset($command['build'])){ $exec = 'php /etc/openvpn/scripts/build_'.$command['build'].'.php --args '; if(!isset($command['server']) || !isset($command['com'])){ helper(); } if($command['build'] == 'server'){ $exec .= '-'.$command['com'] . ' ' . $command['server']; } if($command['build'] == 'client'){ if(!isset($command['client'])){ helper(); } if($command['com'] != 'remove'){ if(!isset($command['email'])){ helper(); } } $exec .= '-'.$command['com'] . ' ' . $command['server'] . ' ' . $command['client']; if(isset($command['email'])){ $exec .= ' ' . $command['email']; } } } if(isset($command['send'])){ if($command['send'] == 'toemail'){ if(!isset($command['server']) || !isset($command['email']) || !isset($command['client'])){ helper(); } $exec = 'php /etc/openvpn/scripts/cert_send_'.$command['send'].'.php --args '.$command['server'].' '.$command['client'].' '.$command['email'].''; } } if(isset($exec)){ exec($exec, $callback); for($i=0;$i<count($callback);$i++){ echo $callback[$i]; if(($i+1)<count($callback)){ echo PHP_EOL; } } echo PHP_EOL; } else { helper(); } function helper(){ echo 'Доступные аргументы:' .PHP_EOL; echo 'Вызов справки: -help' .PHP_EOL; echo 'Создать/удалить openvpn сервер: build:server com:add(или remove) server:1(численный номер сервера)' .PHP_EOL; echo 'Создать/удалить сертификаты клиента: build:client com:add(или remove) server:1(численный номер сервера, к которому будет привязан клиент) email:admin@sergdudko.tk client:1(численный номер клиентского сертификата)' .PHP_EOL; echo 'Отправить сертификаты клиента на email: send:toemail(отправка на email) server:1(численный номер сервера, к которому будет привязан клиент) email:admin@sergdudko.tk client:1(численный номер клиентского сертификата)' .PHP_EOL; echo 'Для настройки программы, наберите -settings' .PHP_EOL; echo PHP_EOL; exit; } function settings($argv){ for($i=0;$i<count($argv);$i++){ if($argv[$i] != '-settings'){ $massive = explode(':', $argv[$i]); if(isset($massive[0]) && isset($massive[1])) { $command[$massive[0]] = $massive[1]; } } } $settings_file = "/etc/openvpn/scripts/settings.php"; if(!file_exists($settings_file)){ echo 'Файл с настройками не найден!' . PHP_EOL; exit; } $handle = @fopen($settings_file, "r"); if ($handle) { $i=0; while (($buffer = fgets($handle, 4096)) !== false) { $str[$i] = $buffer; $i++; } if (!feof($handle)) { echo "Error: unexpected fgets() fail\n"; } fclose($handle); } $current = ''; $flag = 0; for($i=0;$i<count($str);$i++){ if(isset($command['db_host']) && (substr($str[$i], 0, 10) == '$db_ipaddr')){ $str[$i] = '$db_ipaddr = \''.$command['db_host'].'\'; //адрес БД' . PHP_EOL; $flag = 1; } if(isset($command['db_name']) && (substr($str[$i], 0, 8) == '$db_name')){ $str[$i] = '$db_name = \''.$command['db_name'].'\'; //имя БД' . PHP_EOL; $flag = 1; } if(isset($command['db_user']) && (substr($str[$i], 0, 8) == '$db_user')){ $str[$i] = '$db_user = \''.$command['db_user'].'\'; //пользователь БД' . PHP_EOL; $flag = 1; } if(isset($command['db_pass']) && (substr($str[$i], 0, 8) == '$db_pass')){ $str[$i] = '$db_pass = \''.$command['db_pass'].'\'; //пароль' . PHP_EOL; $flag = 1; } if(isset($command['timezone']) && (substr($str[$i], 0, 25) == 'date_default_timezone_set')){ $str[$i] = 'date_default_timezone_set(\''.$command['timezone'].'\');' . PHP_EOL; $flag = 1; } $current .= $str[$i]; } if($flag == 1) { if(file_put_contents($settings_file, $current)){ echo 'Настройки изменены!' . PHP_EOL; } } else { echo 'Параметры: db_host:hostname(адрес БД MySQL или ip) db_name:name(имя БД) db_user:user(пользователь БД) db_pass:password(пароль пользователя БД) encoding:Europe/Minsk(таймзона)' . PHP_EOL; echo '-settings обязательный префикс, лишние параметры можно пропустить' . PHP_EOL; } exit; } exit; ?> |
Т.к. нам нужно работать с системными папками /etc/openvpn с правом записи и возможностью добавлять и удалять сервисы в ОС есть два простых варианта это осуществить:
1) запустить веб-сервер от root
2) запустить собственный веб-сервер php
Первый вариант более, чем не безопасен. Потому я выбрал второй вариант. Создаю веб-сервер с каталогом, в котором лежит core_web.php. Т.к. данный скрипт к каталогу не привязан, можно разместить его в любом месте ОС. Запуск веб-сервера осуществляется командой:
1 |
sudo php -S 127.0.0.1:999 -t /etc/openvpn/scripts/ |
Здесь важно запустить веб-сервер локально, т.е. в firewall доступ к данному порту закрыт или выброшен в другое место для зоны с интерфейсом сетевой карты. Для интерфейса lo (localhost или 127.0.0.1) открываем порт по средствам привязки данного интерфейса к доверенной зоне (ну или разрешив соединения на порту 999 для текущего случая).
Общаться с внутренним веб-сервером будет внешний, например на apache. Для этого добавим скрипт, который будет перебрасывать запросы/ответы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php $json = file_get_contents("php://input"); $url = 'http://127.0.0.1:999/core_web.php'; $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json',) ); $result = curl_exec($ch); echo $result; exit; ?> |
Итого получили веб-сервер на Apache, который пробрасывает команды внутреннему веб-серверу с полными правами работы в ОС.
Сами команды мы уже разбирали в предыдущей статье, они аналогичны консольным, отформатированным в json.
Создать/удалить OpenVPN сервер:
1 2 3 4 5 6 7 8 |
{ "build":"server", "com":"add", "server":"3" } { "build":"server", "com":"remove", "server":"3" } |
Создать/удалить сертификат клиента:
1 2 3 4 5 6 7 8 9 10 11 |
{ "build":"client", "com":"add", "server":"3", "email":"admin@sergdudko.tk", "client":"1"} { "build":"client", "com":"remove", "server":"3", "client":"1"} |
Отправить сертификат на email:
1 2 3 4 5 |
{ "send":"toemail", "email":"admin@sergdudko.tk", "server":"3", "client":"1"} |