Каталог Поиск 0 Сравнить 0 Закладки 0 Корзина Войти
Каталог
105082, Москва, ул. Фридриха Энгельса, 75с21, БЦ Бауманский ИТКОЛ
Пн - Пт: с 09-00 до 18-00 Сб: с 10-00 до 18-00 Вс: выходной
Страницы: 1
RSS
Unifi 3.2.7 уязвим к Fragged CURL SSL V3, UniFi Network
 
Всем привет! В последнее время я много работал с curl и архитектурой PHP, но мой UniFi обновился при очень странных обстоятельствах. Теперь, когда я пытаюсь использовать curl для входа с таким кодом:

curl_setopt($unifi_curl, CURLOPT_SSLVERSION, 3); // ТУТ ВОЗНИКАЕТ ОШИБКА  
curl_setopt($unifi_curl, CURLOPT_SSL_VERIFYHOST, false);  
curl_setopt($unifi_curl, CURLOPT_SSL_VERIFYPEER, false);  
curl_setopt($unifi_curl, CURLOPT_URL, "$unifi_url/login");  
curl_setopt($unifi_curl, CURLOPT_WRITEHEADER, $hdr);  
curl_setopt($unifi_curl, CURLOPT_POST, true);  
curl_setopt($unifi_curl, CURLOPT_POSTFIELDS, http_build_query(array('login' => 'login', 'username' => $unifi_username, 'password' => $unifi_password)));

Мне возвращается ошибка:  
Request error: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

Кто-нибудь знает, как это исправить?
 
curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/s/default/cmd/stamgr'); Предположим, что имя сайта — «default». Как это будет работать, если сайтов несколько? Мне бы не хотелось создавать по несколько экземпляров для каждого сайта.

Если вы пытаетесь использовать одни и те же функции авторизации для нескольких сайтов, то, скорее всего, нужно передавать имя сайта в функции и использовать его для формирования правильного URL. Все URL будут одинаковыми, только вместо «default» будет подставляться имя нужного сайта.
 
Твой скрипт работал до версии 3.2.7 или ты только сейчас начинаешь с ним разбираться? Я написал свой собственный скрипт, поэтому не могу точно сказать, как работает твой, но могу подтвердить, что единственное, что нужно было поменять в этом конкретном вопросе — это переход с SSLv3 на TLS (что и делает значение CURLOPT_SSLVERSION равное "1").

Однако в одной из ранних версий изменили структуру URL сайтов, и API-команды теперь должны соответствовать этой новой структуре. Не могу точно вспомнить, случилось это при переходе с 2.x на 3.x, или уже после выхода 3.x, но сейчас всё настроено так, чтобы поддерживать несколько сайтов на одной установке. Если у тебя только один сайт — скорее всего, его имя "default". Если нет — тебе нужно будет заменить в примерах правильное имя сайта.

Вот, по крайней мере, одно изменение, которое нужно внести в твой скрипт (предполагается, что имя сайта "default"):  
При авторизации гостя замени:  
curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/cmd/stamgr');  
на:  
curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/s/default/cmd/stamgr');

Также, похоже, ты забыл указать номер порта в URL. По умолчанию порт Unifi сервера — 8443, и он должен присутствовать в базовом URL.  
То есть в твоём скрипте строка:  
$unifiServer = "http://192.168.100.33";  
должна стать:  
$unifiServer = "http://192.168.100.33:8443";

Очень полезно посмотреть пример API shell скрипта, который предоставляет Ubiquiti, даже если команды нужно будет перевести на curl и PHP. Убедись, что URL в примере соответствует той версии Unifi сервера, с которой ты работаешь. Скрипт для Unifi v3.2.7 вот тут:  
http://dl.ubnt.com/unifi/3.2.7/unifi_sh_api

curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/s/default/cmd/stamgr');  

Предположим, имя сайта "default" — а как это будет работать, если сайтов несколько? Я бы не хотел создавать отдельные экземпляры для каждого сайта.
 
Тебе правда стоит посмотреть файл paypal_ipn.php для unifi PayPal standard (поищи в гугле unifi PayPal standard implementation). Или загляни в мой скрипт для проверки использования пользователями, который есть в моём профиле. Я вхожу через curl и выполняю разные операции (только не забудь поменять версию ssl).
 
Вот моя собственная тема: https://community.ui.com/questions/ea9febd6-5bcb-4bcd-84f1-9ede1ec75925, и там я выложу все полные файлы аутентификации.
 
Можешь выложить полный код функции authorize после внесённых изменений (естественно, без пароля)? Скорее всего, у меня не будет времени что-либо посмотреть примерно 8-12 часов. Если проблемы сохранятся, лучше создать новую тему, потому что сейчас дело уже не только в SSL.
 
Теперь я заменил свой файл на твой. Сначала гость попадает на файл index.php, который выглядит так:

<?php
//PHP SCRIPT FOR SIMPLE PORTAL
//REQUIREMENTS:
//curl needs to be enabled (php_curl.dll for windows)
session_start();
$_SESSION['id'] = $_GET['id']; // MAC-адрес пользователя
$_SESSION['ap'] = $_GET['ap']; // MAC-адрес точки доступа
$_SESSION['ssid'] = $_GET['ssid']; // SSID, к которому подключен пользователь (POST 2.3.2)
$_SESSION['time'] = $_GET['t']; // время, когда пользователь пытался сделать запрос к порталу
$_SESSION['refURL'] = $_GET['url']; // URL, к которому пользователь пытался обратиться
$_SESSION['loggingin'] = "unique key"; // ключ для проверки, использовал ли пользователь эту форму
// -- предотвращает просто так зайти на /authorized.php?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Portal Page Example</title>
</head>
<script type="text/javascript">
document.submit.submit();
</script>
<meta http-equiv="refresh" content="0.2;url=http://192.168.100.33/guest/s/default/authorized.php">
</html>

Дальше я перенаправляю с index.php на твой "authorize file" с нужными параметрами. Но проблема всё та же — гостя не авторизует. Нужно ли что-то настраивать в контроллере Unifi?
 
Предполагая, что вы измените нужные учетные данные, базовый URL и параметры под вашу среду, моя функция достаточно универсальная и должна работать в большинстве случаев. Обратите внимание, что я также включил опции для ограничения скорости и максимального объёма передачи, и если вы не передадите эти параметры, функция будет использовать значения по умолчанию, указанные в списке параметров. Так что, если вы не хотите никаких ограничений, нужно будет убрать соответствующий код. Кроме того, этот скрипт предполагает, что имя сайта вашего Unifi сервера — «default». Если нет, то код тоже придется подправить.
 
Спасибо за столько подсказок, @angi_g. Лог ошибок показывает только такие сообщения:  
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Дочерний процесс запущен
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Приобретён start mutex.
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Запуск 150 рабочих потоков.
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Запуск потока для прослушивания порта 443.
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Запуск потока для прослушивания порта 80.
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Запуск потока для прослушивания порта 80.
[Thu Dec 18 11:48:58 2014] [notice] Child 3300: Запуск потока для прослушивания порта 443.
[Thu Dec 18 11:50:18 2014] [notice] Parent: Получен сигнал завершения — закрываем сервер.
[Thu Dec 18 11:50:18 2014] [notice] Child 3300: Сигнал выхода получен. Дочерний процесс завершается.
[Thu Dec 18 11:50:19 2014] [notice] Child 3300: Освобожден start mutex
[Thu Dec 18 11:50:21 2014] [notice] Child 3300: Все рабочие потоки завершены.
[Thu Dec 18 11:50:21 2014] [notice] Child 3300: Дочерний процесс завершается
[Thu Dec 18 11:50:21 2014] [notice] Parent: Дочерний процесс успешно завершён.
[Thu Dec 18 11:50:26 2014] [notice] Digest: генерация секрета для Digest-аутентификации...
[Thu Dec 18 11:50:26 2014] [notice] Digest: готово
[Thu Dec 18 11:50:26 2014] [notice] Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1 сконфигурирован — возобновляем работу
[Thu Dec 18 11:50:26 2014] [notice] Сервер собран: Nov 11 2009 14:29:03
[Thu Dec 18 11:50:26 2014] [notice] Parent: Создан дочерний процесс 4264
[Thu Dec 18 11:50:28 2014] [notice] Digest: генерация секрета для Digest-аутентификации...
[Thu Dec 18 11:50:28 2014] [notice] Digest: готово
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Дочерний процесс запущен
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Приобретён start mutex.
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Запуск 150 рабочих потоков.
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Запуск потока для прослушивания порта 443.
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Запуск потока для прослушивания порта 80.
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Запуск потока для прослушивания порта 443.
[Thu Dec 18 11:50:28 2014] [notice] Child 4264: Запуск потока для прослушивания порта 80.

@dlong500 хорошо, я попробую твою функцию авторизации. Извини за следующий вопрос, я в этом совсем новичок, но мне просто заменить свой auth файл твоим? Или я что-то путаю?
 
@tgrafen1

Вот одна из моих функций авторизации (с удалёнными учётными данными и информацией о сайте) для справки:

function AuthorizeDevice($mac, $minutes = 1440, $rateup = 512, $ratedown = 2048, $MBlimit = 150)
{
   $username="<user>";
   $password="<password>";
   $baseurl="https://unifi.test.local:8443";

   # инициализируем curl и задаём опции для всей сессии
   $ch = curl_init();
   ob_start(); // предотвращаем любой вывод
   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
   curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
   curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/unifi_cookie");
   curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/unifi_cookie");
   curl_setopt($ch, CURLOPT_SSLVERSION, 1); // ставим TLSv1 (SSLv3 больше не поддерживается)

   # авторизация на unifi контроллере
   curl_setopt($ch, CURLOPT_URL, "$baseurl/login");
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, "login=login&username=$username&password=$password");
   curl_exec ($ch);

   # разрешаем гостю доступ на $minutes с лимитами по скорости $rateup/$ratedown и максимальным трафиком $MBlimit МБ
   curl_setopt($ch, CURLOPT_URL, "$baseurl/api/s/default/cmd/stamgr");
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, "json={'cmd':'authorize-guest', 'mac':'$mac', 'minutes':$minutes, 'up':$rateup, 'down':$ratedown, 'bytes':$MBlimit}");
   $response = curl_exec ($ch);

   # выход из сессии
   curl_setopt($ch, CURLOPT_URL, "$baseurl/logout");
   curl_setopt($ch, CURLOPT_POST, 0);
   curl_setopt($ch, CURLOPT_POSTFIELDS, NULL);
   curl_setopt($ch, CURLOPT_HTTPGET, TRUE);
   curl_exec ($ch);

   ob_end_clean();  // прекращаем подавление вывода
   curl_close ($ch);
   unset($ch);
   
   if ($response !== false) {
       return $response;
   } else {
       return 0;
   }
}
 
Я не знаю, что еще могу тебе сказать. Если твой скрипт работал с версией v3.2.1, то единственное, что возможно нужно поменять — это CURLOPT_SSLVERSION. Но, пожалуйста, ещё раз внимательно прочитай мой первый ответ, потому что кажется, что твои команды больше соответствуют API версии 2.x. Я не вижу в API-командах упоминания имени сайта, да и непонятно, как они могут связаться с сервером, если не указан порт (если только ты не сменил порт сервера Unifi на 80).
 
Вам всего лишь нужно изменить версию SSL на 1, а не на 3, все остальные ошибки стоит искать в журнале ошибок. Если вы запускаете скрипты через apache2, то откройте файл журнала ошибок apache2 — там будет указана проблема. Кстати, помните, что команды curl в большинстве случаев чувствительны к регистру, и «curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, False);» меня раздражает.
 
привет dlong500, скрипт отлично работает на версии 3.2.1, а сейчас я обновился до версии 3.2.7 и пользователь теперь не авторизуется... Думаю, что последний шаг, последняя команда, которая авторизует гостя, не работает, но моих навыков пока недостаточно, чтобы понять, какая именно команда отвечает за авторизацию гостя.
 
Твой скрипт работал до версии v3.2.7 или ты только начинаешь с ним разбираться? Я сделал свой собственный скрипт, поэтому не могу точно сказать, что делает твой, но могу подтвердить, что единственное, что требовалось изменить по данной проблеме — перейти с SSLv3 на TLS (что и делает CURLOPT_SSLVERSION с значением «1»).

Однако в одной из предыдущих версий изменили структуру URL-адресов сайтов, и теперь API-команды должны это учитывать. Не могу точно вспомнить, произошло ли это при переходе с 2.x на 3.x или сразу после выхода 3.x, но сейчас всё настроено так, чтобы можно было использовать несколько сайтов в одной установке. Если у тебя один сайт, скорее всего, его название — «default». Если нет — нужно поменять примеры на правильное имя сайта.

Вот хотя бы одно изменение, которое нужно внести в твой скрипт (предполагая, что сайт называется «default»):  
При авторизации гостя поменяй:  
curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/cmd/stamgr');  
на:  
curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/s/default/cmd/stamgr');

Похоже, у тебя в URL может отсутствовать номер порта. По умолчанию Unifi-сервер использует порт 8443, и его нужно указать в базовом URL.  
То есть в твоём скрипте строка:  
$unifiServer = "http://192.168.100.33";  
должна выглядеть так:  
$unifiServer = "http://192.168.100.33:8443";

Очень полезно посмотреть пример скрипта для API, который предоставляет Ubiquiti, даже если команды нужно переводить в curl и PHP. Убедись, что в примере URL соответствует нужной версии Unifi-сервера.  
Вот скрипт для Unifi v3.2.7:  
http://dl.ubnt.com/unifi/3.2.7/unifi_sh_api
 
Привет, у меня такая же проблема. Я поменял число с 3 на 1:  
curl_setopt($ch, CURLOPT_SSLVERSION, 3); → curl_setopt($ch, CURLOPT_SSLVERSION, 1);  
Но гостя всё равно не авторизуют. Что ещё можно сделать?  

Вот мой полный скрипт:

session_start();  
function sendAuthorization($id, $minutes){  
 $unifiServer = "http://192.168.100.33";  
 $unifiUser = "administrator";  
 $unifiPass = "******";  
 
 // Запускаем Curl для логина  
 $ch = curl_init();  
 // Отправляем данные методом POST  
 curl_setopt($ch, CURLOPT_POST, TRUE);  
 // Настраиваем куки  
 $cookie_file = "/tmp/unifi_cookie";  
 curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);  
 curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);  
 // Разрешаем самоподписанные сертификаты  
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);  
 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);  
 // Форсим использование только SSL3  
 curl_setopt($ch, CURLOPT_SSLVERSION, 1);  
 // Логин в контроллер UniFi  
 curl_setopt($ch, CURLOPT_URL, "$unifiServer/login");  
 curl_setopt($ch, CURLOPT_POSTFIELDS, "login=login&username=$unifiUser&password=$unifiPass");  
 // Отправляем команду логина  
 curl_exec($ch);  
 curl_close($ch);  
 
 // Отправляем пользователя на авторизацию и задаём время доступа  
 $data = json_encode(array('cmd'=>'authorize-guest','mac'=>$id,'minutes'=>$minutes));  
 // Отправляем команду к API  
 curl_setopt($ch, CURLOPT_URL, $unifiServer.'/api/cmd/stamgr');  
 curl_setopt($ch, CURLOPT_POSTFIELDS, 'json='.$data);  
 curl_exec($ch);  
 
 // Выход из контроллера UniFi  
 curl_setopt($ch, CURLOPT_URL, $unifiServer.'/logout');  
 curl_exec($ch);  
 curl_close($ch);  
 unset($ch);  
}  

if ($_SESSION['loggingin'] == "unique key") // Проверяем, отправлена ли форма
{  
 ob_start();  
 sendAuthorization($_SESSION['id'], (24*60)); // авторизуем пользователя на 12 часов
 ob_end_clean();  
 unset($_SESSION['loggingin']);
}  

?>

<center>

<img src="RekordWlan.jpg" alt="RekordLogo">

</center>  
<script>  
// даём время для прохождения авторизации  
setTimeout("location.href='http://www.google.com'",2000);  
</script>
 
Полностью с вами согласен, я не мог понять, в чем была ошибка PHP, настолько, что потратил два дня на поиск проблемы. Мой Unifi обновился автоматически, и я не знал о смене версии SSL.
 
Было бы здорово, если бы заранее предупреждали, что обновление до версии v3.2.7 ломает API-команды, которые работали ещё с v2.X. В итоге эти команды просто молча не срабатывают, и гостям не даётся доступ. На мой взгляд, это совсем непрофессионально. В заметках к релизу просто написано «Исправлена уязвимость Poodle/SSLv3», и ни слова о том, что теперь нужно обновлять API-команды, потому что поддержка SSLv3 полностью убрана. Такие серьёзные изменения точно стоило бы разослать всем участникам форума хотя бы по электронной почте.

Поскольку я даже не знал, с чего начать, мне пришлось тратить время на тестирование отдельных curl-команд, чтобы обнаружить проблему с SSLv3, а потом искать темы вроде этой, чтобы понять, почему всё ломается.

ПРОШУ, хотя бы вышлите письмо, а лучше — разместите крупное предупреждение в заметках к релизу, если в будущем планируются такие обратимо несовместимые изменения.
 
На этот пост уже оставили комментарий по другому заявлению... Не нужно создавать новую тему... Расслабьтесь...
 
Почему люди продолжают будить этот давно решённый пост? cURL требует смены SSL с v3 на v1, всё просто. Если у вас другой вопрос — создайте новую тему.
Страницы: 1
Читают тему (гостей: 1)