Обработка сессий PHP при помощи сервера Redis в Ubuntu 16.04
PHP, Ubuntu | Комментировать запись
Redis – это открытое нереляционное хранилище данных и кэша типа «ключ-значение». Также Redis является сервером преобразования структур данных, предназначенным для расширенной поддержки нескольких типов данных (хэша, списков, множеств, битовых массивов и т.п.). Кроме того, Redis поддерживает кластеризацию, потому его часто используют в высокопроизводительных и масштабируемых средах.
Данное руководство поможет установить и настроить сервер Redis для обработки PHP-сессий приложения в системе Ubuntu 16.04.
Обработчик сессий отвечает за хранение и извлечение данных, сохраненных в сессиях; по умолчанию PHP использует для этого файлы. Вместе с балансировщиком нагрузки обработчик сессий может быть использован для создания масштабируемой среды PHP, в которой все ноды приложения смогут подключаться к ведущему серверу для обмена данными.
Требования
Для выполнения данного руководства использовались два сервера.
Итак, для работы понадобится:
- Сервер 1(в руководстве он будет называться web): предварительно установленный веб-сервер; можно использовать стек LAMP или LEMP.
- Сервер 2 (в руководстве он будет называться redis): свежий сервер Ubuntu 16.04, на котором будет установлен Redis.
- Доступ SSH.
- Пользователь с доступом к sudo на каждом сервере (инструкции по настройке такого пользователя – здесь).
- Базовый брандмауэр.
1: Установка сервера и клиента Redis
Сначала нужно установить Redis на оба сервера: на сервер redis установите пакет Redis server, а на сервер web – PHP-расширение Redis для обработки сессий и клиент командной строки.
Установка Redis Server
Подключитесь к машине redis и установите необходимый пакет. Для этого подойдёт репозиторий PPA. Используйте наиболее актуальную версию Redis.
Примечание: Используйте PPA только из надёжных и безопасных источников.
Добавьте PPA:
sudo apt-add-repository ppa:chris-lea/redis-server
Чтобы подтвердить, нажмите Enter.
Обновите индекс пакетов и установите сервер Redis:
sudo apt-get update
sudo apt-get install redis-server
Чтобы убедиться, что установка прошла успешно, введите команду:
redis-cli ping
Команда создаст подключение к Redis с локального хоста на порт 6379. Если установка прошла успешно, команда вернёт:
PONG
Установка клиента и PHP-расширения Redis
Перейдите на сервер web. Здесь нужно установить клиент командной строки (для проверки подключения) и PHP-расширения Redis (для хранения данных).
Обновите индекс пакетов и установите программы:
sudo apt-get update
sudo apt-get install redis-tools php-redis
Теперь у вас есть доступ к инструменту redis-cli, но пока что сервер не принимает внешних соединений.
2: Настройка Redis для поддержки внешних соединений
По умолчанию Redis поддерживает подключения только с локального хоста. Это значит, что Redis доступен только с того сервера, на котором он установлен. Эту настройку нужно изменить.
По умолчанию Redis не предоставляет шифрования, поскольку предполагает развёртывание в изолированной сети заведомо безопасных серверов. Следовательно, чтобы все внешние соединения были безопасными, оба сервера должны находиться в изолированной сети, либо же вы должны защитить трафик между серверами при помощи специальных инструментов шифрования.
Изолированная сеть
Если серверы находятся в изолированной сети, достаточно просто отредактировать конфигурационный файл Redis и добавить IP-адрес сети.
Перейдите на сервер redis, создайте резервную копию конфигурационного файла Redis и откройте его:
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.bak
sudo nano /etc/redis/redis.conf
Найдите строку bind и вставьте IP-адрес сети, в которой находится сервер Redis.
bind 127.0.0.1 isolated_IP_address
Сохраните и закройте файл. Перезапустите сервис:
sudo systemctl restart redis-server.service
Откройте доступ к порту в брандмауэре.
sudo ufw allow 6379
Теперь сервер Redis может принимать внешние соединения в изолированной сети.
Инструменты шифрования
Если сервер развёрнут вне изолированной среды, обязательно нужно защитить трафик между серверами. Существует несколько способов сделать это:
- Инструмент stunnel – инструмент для туннелирования. Позволяет настроить входящий туннель на сервере redis и исходящий туннель на сервере web. Сервер web будет подключаться к локальному порту для связи с удаленным сервисом Redis.
- Инструмент spiped: сервер web будет использоваться в качестве клиента spiped.на каждом сервере нужно создать юнит-файл system. Сервер web будет подключаться к локальному порту для связи с удаленным сервисом Redis.
- PeerVPN: оба сервера будут помещены в VPN. Сервер web будет подключаться к серверу redis с помощью IP-адреса VPN.
Выберите один из предложенных методов и зашифруйте трафик между серверами.
3: Пароль для сервера Redis
Чтобы повысить уровень безопасности сервера Redis, нужно защитить его данные паролем. Отредактируйте конфигурационный файл /etc/redis/redis.conf.
sudo nano /etc/redis/redis.conf
Раскомментируйте строку requirepass и установите надёжный пароль. Этот пароль необходим для аутентификации Redis. Выберите сложный фразовый пароль, чтобы предотвратить brute force атаки.
requirepass yourverycomplexpasswordhere
Сохраните и закройте файл. Перезапустите сервис Redis:
sudo systemctl restart redis-server.service
4: Тестирование подключения и авторизации Redis
Чтобы убедиться в том, что все настройки работают должным образом, подключитесь к Redis с сервера web.
По умолчанию сервис Redis прослушивает порт 6379 на локальном интерфейсе. Однако данные могут отличаться в зависимости от настроек безопасности трафика Redis (раздел 2). С помощью клиента redis-cli и флага –h можно указать IP-адрес, с помощью флага –p – задать порт удалённого сервиса, к которому нужно подключиться.
Примечание: Если вы используете нестандартные параметры, замените 127.0.0.1 и порт 6379 соответствующими данными.
Итак, если серверы работают в изолированной среде, вам нужно использовать IP-адрес этой сети и стандартный порт 6379 (его можно не указывать).
redis-cli -h redis_isolated_IP
Если вы используете stunnel или spiped, укажите номер локального порта, который подключен к удаленному сервису Redis:
redis-cli -p 8000
Если вы используете PeerVPN, укажите IP-адрес VPN:
redis-cli -h 10.8.0.1
Общий синтаксис команды выглядит так:
redis-cli -h ip_to_contact_redis -p port_to_contact_redis
Теперь вы можете подключиться к удалённому сервису Redis с сервера web.
Если вы определили пароль, вы не получите доступа к данным, а на экране появится ошибка AUTH:
keys *
(error) NOAUTH Authentication required.
Чтобы пройти аутентификацию, нужно запустить команду AUTH и указать пароль, указанный в файле /etc/redis/redis.conf.
AUTH yourverycomplexpasswordhere
Если всё сработало, на экране появится вывод:
OK
Теперь снова запустите:
keys *
На экране появится примерно такой вывод:
(empty list or set)
Это значит, что на сервере Redis пока что нет никаких данных; это нормальное поведение сервера, поскольку сервер web пока что не может использовать его в качестве обработчика сессий.
Вернитесь в командную строку:
exit
5: Настройка обработки сессий
Оставайтесь на сервере web. Откройте файл php.ini, в котором можно определить стандартный обработчик сессий PHP. Место хранения файла зависит от используемого программного стека.
В стеке LAMP в Ubuntu 16.04 этот файл обычно находится в /etc/php/7.0/apache2/php.ini. В стеке LEMP в системе Ubuntu 16.04 файл, как правило, хранится в /etc/php/7.0/fpm/php.ini.
Поиск файла php.ini (опционально)
Примечание: Если вы уже нашли файл php.ini, пропустите этот раздел.
Если вы не знаете точного пути файла php.ini, его можно быстро узнать при помощи функции phpinfo(). Просто откройте в каталоге /var/www/html файл info.php:
sudo nano /var/www/html/info.php
и поместите в него следующий код:
<?php
phpinfo();
Затем откройте скрипт в браузере и найдите строку Loaded Configuration File. В ней указано местонахождение нужного файла.
http://web_server_domain_or_IP/info.php
Примечание: После этого рекомендуется удалить файл info.php, поскольку он открывает доступ к конфиденциальным данным о сервере.
Изменение настроек
Откройте файл php.ini.
Стек LAMP:
sudo nano /etc/php/7.0/apache2/php.ini
Стек LEMP:
sudo nano /etc/php/7.0/fpm/php.ini
Примечание: Если путь к файлу php.ini отличается, укажите правильный путь.
В файле php.ini найдите строку session.save_handler. По умолчанию она имеет значение files. Замените значение на redis, чтобы использовать PHP-расширение Redis вместо файлов.
session.save_handler = redis
Теперь вы должны найти строку session.save_path. Раскомментируйте ее и измените значение, указав строку подключения Redis в таком формате:
tcp://IP_address:port?auth=redis_password
Опять же, правильные значения зависят от выбранного вами метода защиты данных. используйте те же данные, что и в разделе 4. Например, если вы используете stunnel или spiped, строка session.save_path будет иметь такой вид:
session.save_path = "tcp://127.0.0.1:8000?auth=yourverycomplexpasswordhere"
Сохраните и закройте файл.
Затем перезапустите сервер PHP.
В LAMP:
sudo systemctl restart apache2
В LEMP:
sudo systemctl restart php7.0-fpm
6: Тестирование обработки сессий
Чтобы убедиться в том, что Redis успешно обрабатывает сессии PHP, создайте PHP-скрипт или приложение, хранящее информацию в сессиях. В данном руководстве используется простой скрипт-счётчик: он увеличивает номер при каждой перезагрузке страницы.
На сервере web создайте файл test.php и поместите его в каталог document root.
sudo nano /var/www/html/test.php
Примечание: Если ваш каталог document root находится в другом месте, откорректируйте эту команду.
Добавьте в файл такой код:
<?php
//simple counter to test sessions. should increment on each page reload.
session_start();
$count = isset($_SESSION['count']) ? $_SESSION['count'] : 1;
echo $count;
$_SESSION['count'] = ++$count;
Сохраните и закройте файл.
Чтобы получить доступ к скрипту в браузере, откройте ссылку:
http://web_server_public_IP/test.php
Номер на странице должен увеличиваться после каждого обновления страницы.
Это значит, что теперь данные сессий хранятся в Redis. Чтобы убедиться в этом, откройте новую сессию с помощью redis-cli на сервере redis. При подключении к локальному интерфейсу IP указывать не нужно:
redis-cli
Укажите пароль Redis:
AUTH yourverycomplexpasswordhere
OK
Извлеките данные при помощи команды keys *:
keys *
Вы увидите новую запись PHP-сессии:
1) "PHPREDIS_SESSION:2ofnvhhr6gdvp88u0c4e7kb800"
Если вы запросите значение ключа, вы увидите текущее значение счётчика:
get PHPREDIS_SESSION:2ofnvhhr6gdvp88u0c4e7kb800
"count|i:6;"
Это значит, что информация сессии хранится на сервере Redis. Аналогичным образом к серверу Redis можно подключить дополнительные веб-серверы.
Tags: PHP, Redis, Ubuntu 16.04