Аутентификация и шифрование
В этой главе рассматриваются базовые принципы аутентификации и шифрования клиентских сеансов на сервере PostgreSQL В частности, описаны настройка файла pg_hba.conf для различных схем аутентификации и некоторые распространенные способы шифрования клиентских подключений.
Аутентификация клиента
Аутентификация клиентов занимает центральное место в PostgreSQL. Без нее пришлось бы либо пожертвовать возможностью удаленного подключения, либо слепо разрешать каждому, кто подключается к серверу, выборку и даже модификацию данных. PostgreSQL предоставляет в ваше распоряжение несколько механизмов аутентификации клиентов, и вы как администратор базы данных должны выбрать тот механизм, который лучше подходит для вашей системы.
В PostgreSQL 7.1.x клиентский доступ на уровне хоста задается в файле pg_hba.conf. Права и ограничения, описанные в этом файле, не следует путать с правами доступа к объектам базы данных, установленными для пользователей PostgreSQL. Файл pg_hba.conf позволяет задать тип аутентификации на уровне хоста, выполняемой перед подключением к базе данных, после которого вступают в силу права пользователей.
ПРИМЕЧАНИЕ
Файл pg_hba.conf находится в каталоге данных PostgreSQL (например, /usr/local/pgsql/data) и создается автоматически при выполнении команды initdb в процессе установки PostgreSQL.
Аутентификация PostgreSQL на уровне хоста отличается высокой гибкостью и большим разнообразием настраиваемых параметров. Например, доступ к базе данных можно ограничить отдельными хостами или предоставить его семейству IP-адресов при помощи сетевых масок. С каждым хостом связывается специальная запись, представленная отдельной строкой в файле pg_hba.conf.
Используя хостовые записи, можно ограничить доступ пользователя одной конкретной базой данных или разрешить ему доступ ко всем базам. Более того, при поступлении запроса на подключение пользователя с заданного хоста можно потребовать, чтобы пользователь прошел аутентификацию по таблице пользователей PostgreSQL.
Проще говоря, файл pg_hba.conf определяет, кому, с какого компьютера и к каким базам данных разрешено подключение, а также каким образом должна проходить проверка для предоставления доступа.
ВНИМАНИЕ
В механизме удаленной аутентификации пароли могут пересылаться по сети в обычном текстовом виде. Все зависит от того, организовали ли вы шифрование клиентского сеанса. Прежде чем разрешать пользователям удаленное подключение к базам данных PostgreSQL, необходимо хорошо разобраться в том, как ваше приложение взаимодействует с PostgreSQL.
Аутентификация с использованием паролей
Пароли используются для подтверждения личности пользователей PostgreSQL и предотвращения посторонних подключений. В PostgreSQL 7.1.x пароли хранятся в текстовом виде в системной таблице pg_shadow, структура которой описана в табл. 8.1. Хотя пароли хранятся в виде простого текста, просмотр содержимого таблицы pg_shadow разрешен только суперпользователям PostgreSQL.
Таблица 8.1. Структура таблицы pg_shadow
Поле |
Тип |
usenatne |
name |
usesysld |
integer- |
usecreatedb |
boolean |
usetrace |
boolean |
usesuper |
boolean |
usecatupd |
boolean |
passwd |
text |
val until |
abstime |
Системная таблица pg_shadow доступна из любой базы данных. Из этого следует, что пользовательский доступ не ограничивается конкретной базой. Если данные некоторого пользователя присутствуют в таблице pg_shadow, то этот пользователь сможет подключиться к любой базе данных на серверном компьютере (конечно, если ему вообще разрешено подключение).
Пароли обычно задаются в PostgreSQL при создании учетной записи пользователя (командой CREATE USER) или при ее дальнейших модификациях (командой ALTER USER). Кроме того, пароль можно изменить вручную командой UPDATE. Дополнительная информация о назначении паролей приведена в главе 10.
Если пароль не задан, по умолчанию используется псевдозначение NULL. При включении парольной аутентификации в файле pgjiba.conf попытки подключения со стороны пользователей, не имеющих паролей, всегда завершаются неудачей. С другой стороны, если подключение устанавливается с доверенного хоста (как, например, local host по умолчанию), любой пользователь сможет подключиться с паролем NULL. Для доверенных хостов пароли полностью игнорируются.
ПРИМЕЧАНИЕ
Команда GRANT ограничивает доступ к таблицам в базе данных. За дополнительной информацией обращайтесь к главе 10.
Если ваши требования к безопасности выходят за рамки абсолютного минимума, одной парольной аутентификации на сервере PostgreSQL будет недостаточно. Любой аутентифицироваыный пользователь сможет обратиться к любой базе данных в системе, а передаваемые в текстовом виде пароли могут попасть в посторонние руки. Если вы планируете организовать доступ к базе данных через Интернет, обязательно прочитайте следующие подразделы. В них рассматриваются файл pg_hba.conf и шифрование сеансов.
Файл pg_hba.conf
В начале главы уже упоминалось о том, что файл pg_hba.conf обеспечивает аутентификацию клиента на сервере PostgreSQL. Файл состоит из записей, описывающих хосты и предоставляемые им права (например, база данных, к которой разрешено подключение, метод аутентификации и т. д.).
Когда приложение обращается к серверу с запросом на подключение, в этот запрос включается имя пользователя PostgreSQL и база данных, к которой он намеревается подключиться. В зависимости от настройки хоста также может передаваться пароль.
ПРИМЕЧАНИЕ
PostgreSQL ведет собственные таблицы пользователей и паролей, не имеющие отношения к системным таблицам. Данные пользователей PostgreSQL не обязаны совпадать с данными пользователей операционной системы.
Получив запрос на подключение, PostgreSQL обращается к файлу pgjiba.conf и проверяет, разрешен ли доступ к указанной базе данных хосту, на котором работает приложение. Если подключения с этого хоста разрешены, PostgreSQL проверяет условия, которым должно удовлетворять приложение для успешного подключения. Это относится как к локальным, так и к удаленным подключениям.
Для каждого запроса на подключение сервер читает из файла pgjiba.conf сведения о способе аутентификации. Проверка производится при каждом подключении к серверу PostgreSQL, поэтому после добавления, изменения или удаления записей из файла pg_hba.conf перезапускать PostgreSQL не нужно. В листинге 8.1 приведен простой пример файла pgjiba.conf.
Листинг 8.1. Простой файл pgjiba.conf
# PostgreSQL HOST ACCESS CONTROL FILE f
# Configured Hosts:
local all trust
host all 127.0.0.1 255.255.255.255 trust
host booktown 192.168.1.3 255.255.255.255 ident sales
host all 192.168.1.4 255.255.255.255 ident audit
При инициализации подключения PostgreSQL читает файл pg_hba.conf сверху вниз по одной записи. Как только найдена подходящая запись, PostgreSQL прекращает поиск и разрешает или отвергает подключение в зависимости от результата. Если PostgreSQL не находит подходящей записи в файле pg_hba.conf, подключение автоматически отвергается.
Даже если пользователю разрешается подключение к базе данных, права доступа к таблицам по-прежнему продолжают действовать. Если пользователь подключается к базе данных, но не может получить данные из таблицы, проверьте, что ему разрешено выполнение команды SELECT для этой таблицы. В клиенте командной строки psql права доступа к таблицам базы данных проверяются при помощи команды \z. В любом другом интерфейсе к PostgreSQL для получения этой информации можно воспользоваться запросом, приведенным в листинге 8.2.
Листинг 8.2. Проверка прав доступа
testdb=# SELECT relname as "Relation", relacl as "Access permissions"
testdb-# FROM pg_class
testdb-# WHERE relkind IN Cr', 'V. 'S')
testdb-# AND relname !- '*pg_'
testdb-# ORDER BY relname;
Relation I Access permissions
foo {"=arwR"."jdrake=arwR"}
myjlist {"=","jdrake=arwR"."jworsley=r"}
(2 rows)
Структура файла pg_hba.conf
Конфигурационный файл pg_hba.conf содержит серию записей, определяющих параметры аутентификации клиентов с заданных хостов. Структура этого файла позволяет легко изменить его в соответствии с вашими требованиями.
В этом файле IP-адрес хоста (или интервал адресов) связывается с некоторой базой данных (или всеми базами) и одним из нескольких методов аутентификации. Для локальных подключений вместо внешнего IP-адреса используется обозначение local host или 127.0.0.1. Синтаксис файла pg_hba.conf должен удовлетворять ряду правил.
Во-первых, каждая строка файла содержит одну хостовую запись, при этом перенос записей на следующую строку не разрешен. Во-вторых, каждая запись содержит несколько полей, разделенных табуляциями или пробелами. Количество полей определяемой хостовой записи напрямую связано с ее типом. В листинге 8.3 приведены две записи; в первой поля разделены пробелами, а во второй — символами табуляции.
Листинг 8.3. Разделение полей в записях pg_hba.conf пробелами и табуляциями
host all 127.0.0.1 255.255.255.255 trust
host all 127.0.0.1 255.255.255.255 trust
Файл pg_hba.conf может содержать комментарии, строки которых начинаются с символа #. Примеры комментариев приведены в листинге 8.4.
Листинг 8.4. Комментарии в файле pgjiba.conf
# Book Town host entries
#
#
host all 127.0.0.1 255.255.255.255 trust
Хостовые записи, содержащиеся в файле pg_hba.conf, делятся на три общих типа (тип всегда задается первым словом каждой записи).
host. Записи типа host описывают удаленные хосты, которым разрешено подключаться к серверу PostgreSQL. Для правильной работы записей типа host серверный модуль PostgreSQL postmaster должен быть запущен с ключом -i (TCP/IP). local. С семантической точки зрения запись типа local аналогична записи типа host. Тем не менее в ней не нужно указывать хосты, которым разрешено подключение. Запись local используется для клиентских подключений с того компьютера, на котором работает сервер PostgreSQL. hostssl. Запись типа hostssl используется для указания хостов (удаленных или локальных), которым разрешено подключение к серверу PostgreSQL с использованием протокола SSL, обеспечивающего шифрование всех взаимодействий между клиентом и сервером. Протокол SSL должен поддерживаться как клиентом, так и сервером. Серверный процесс postmaster должен быть запущен с ключами -1 (SSL) и -1 (TCP/IP).ПРИМЕЧАНИЕ
Ключи, с которыми запускается процесс postmaster, описаны в главе 9.
В листинге 8.5 приведен обобщенный синтаксис всех типов записей файла pg_hba.conf. Обратите внимание: все типы записей практически идентичны, разве что в записях типа local не нужно указывать IP-адрес или сетевую маску — подключение заведомо осуществляется с компьютера, на котором работает PostgreSQL.
Листинг 8.5. Синтаксис записей файла pg_hba.conf
# Запись типа "local"
local база_дднных метод^аутентификации [ параметр ]
# Запись типа "host"
host база_данных 1р_адрес сетевая_наска метод_аутентификации [ параметр ]
# Запись типа "hostssl"
hostssl база_данных тр_адрес сетевая_маска метод_аутентификации [ параметр ]
ПРИМЕЧАНИЕ
Помните, что каждая запись в файле pg_hba.conf должна полностью умещаться в одной строке. Перенос записей на другую строку запрещен.
Ниже перечислены компоненты записей pg_hba.conf, упоминаемые в листинге 8.5.
база_данных. Имя базы данных, к которой разрешено подключаться заданному хосту. Возможны три варианта: ключевое слово al 1 означает, что клиент может подключиться к любой базе данных, обслуживаемой сервером PostgreSQL; ключевое слово sameuser означает, что клиент может подключаться только к базе данных, имя которой совпадает с именем аутентифицироваиного пользователя; если в записи указывается конкретное имя базы данных, клиент сможет подключиться только к этой базе. ip_adpec, сетевая ^маска. Поля ip_adpec и сетевая_маска определяют либо конкретный IP-адрес, либо интервал IP-адресов, которым разрешено подключение к серверу PostgreSQL. Интервал задается в виде сетевой маски, описывающей IP-сеть. При указании отдельного IP-адреса поле сетевой маски должно быть равно 255.255~. 255.255.ПРИМЕЧАНИЕ
За информацией о сетевых масках обращайтесь на сайт Linux Networking HOWTO (http://www. thelinuxreview.com/howto/networking) или к системному администратору.
метод_аутентификации. Метод аутентификации, который должен использоваться сервером при подключении пользователя к PostgreSQL. Ниже перечислены допустимые значения этого поля. trust. Хост объявляется доверенным, то есть любой пользователь с него подключается к базе данных PostgreSQL без пароля. Таким образом, вы автоматически доверяете всем пользователям хоста. Естественно, это весьма рискованный метод, если заданный хост недостаточно хорошо защищен или предоставляет доступ посторонним пользователям. reject. Доступ к PostgreSQL для соответствующего хоста/пользователя автоматически отклоняется. Такая настройка подходит лишь в том случае, если хост заведомо не должен получать доступ к серверу PostgreSQL. password. Для получения доступа пользователь должен ввести пароль, который совпадает с паролем, хранящимся в глобальной системной таблице pg_shadow с именем этого пользователя. Пароль пересылается в текстовом виде. crypt. Этот метод аналогичен методу password, но в нем пароль пересылается не в простом текстовом виде, а с применением простой схемы шифрования, которая не обеспечивает надежной защиты, но это все же лучше, чем простая пересылка пароля в текстовом виде, как в методе password. krb4, krb5. Используется система аутентификации Kerberos версий 4 и 5. Вопросы установки и настройки Kerberos выходят за рамки темы книги, но если вы захотите организовать аутентификацию с использованием Kerberos, такой вариант существует. ident. При запросе на подключение от хоста с IP-адресом, заданным в файле pg_hba.conf, должна применяться карта идентификации. У метода имеется один обязательный параметр, значением которого является либо специальное ключевое слово sameuser, либо имя карты, определенной в файле pgjdent.conf. Дополнительная информация о картах идентификации приведена в пункте «Файл pg_ident.conf>>. параметр. Поле параметра может быть обязательным или необязательным в зависимости от выбранного метода аутентификации. В PostgreSQL 7.1.x оно обязательно только для метода Ident.ВНИМАНИЕ
Методы password и crypt рекомендуется использовать лишь в сочетании с внешним механизмом шифрования. Информация о применении единого механизма шифрования для всего трафика PostgreSQL приведена в разделе «Шифрование сеанса».
Примеры записей в файле pg_hba.conf
В этом разделе приведены некоторые примеры записей в файле pg_hba.conf.
Запись, приведенная в листинге 8.6, разрешает подключиться к любой (all) базе данных без пароля (trust) всем пользователям хоста с IP-адресом 192.168.1.10.
Листинг 8.6. Один доверенный хост
host all 192.168.1.10 255.255.255.255 trust
Следующая запись (листинг 8.7) запрещает подключение всем пользователям с IP-адреса 192.168.1.10. Для этого в режиме аутентификации reject вместо базы данных указывается ключевое слово all.
Листинг 8.7. Запрет доступа с одного хоста
host all 192.168.1.10 255.255.255.255 reject
Следующая запись (листинг 8.8) разрешает подключение к базе данных templatel с хоста 192.168.1.10 любому пользователю, указавшему правильный пароль. Режим crypt обеспечивает шифрование пароля в процессе аутентификации.
Листинг 8.8. Один хост, одна база данных
host templatel 192.168.1.10 255.255.255.255 crypt
Запись в листинге 8.9 разрешает доступ к базам данных без пароля из небольшой подсети. Подсеть состоит из всех IP-адресов в интервале от 192.168.1.1 до 192.168.1.15. Как упоминалось ранее, за информацией о сетевых масках следует обращаться на сайт Linux Networking HOWTO (http://www.thelinuxreview.com/howto/ networking) или к администратору сети.
Листинг 8.9. Доверенная подсеть
host all 192.168.1.0 255.255.255.240 trust
Запись, приведенная в листинге 8.10, разрешает доступ с любого хоста из блока 192.168.1 к базе данных booktown без указания пароля.
Листинг 8.10. Доверенная подсеть
host booktown 192.168.1.0 255.255.255.0 trust
Вспомните, о чем говорилось выше: при проверке очередного подключения записи файла pg_hba.conf последовательно читаются от начала к концу, и режим аутентификации определяется первой найденной записью. Если в файле не обнаруживается ни одного совпадения, подключение полностью запрещается.
Файл pgjdent.conf
Если в хостовой записи указан метод аутентификации ident, PostgreSQL использует файл pgjdent.conf для отображения идентификационного имени пользователя на имя пользователя PostgreSQL. «Идентификационное имя пользователя» предоставляется службой identd (RFC 1413) и определяет имя системной учетной записи, инициировавшей подключение. В целом этот метод аутентификации аналогичен методу trust, но с ограничением доступа по идентификационному имени пользователя.
Как сказано в спецификации протокола ident, «Идентификационный протокол не предназначен для аутентификации или управления доступом». Он всего лишь является удобным средством идентификации в сетях, состоящих из защищенных, хорошо контролируемых компьютеров, и не обеспечивает надежной защиты при внешнем доступе. Дело в том, что демон identd всего лишь возвращает имя, описывающее текущего пользователя системы. Например, предоставление пользователю jworsl ey доступа из подсети IP-адресов создает серьезную угрозу для безопасности системы, поскольку любой пользователь компьютера, входящего в эту подсеть, сможет создать учетную запись jworsl еу и успешно пройти «аутентификацию».
Файл pgjdent.conf должен находиться в одном каталоге с файлом pg_hba.conf. Путь к этому каталогу определяется переменной среды PGDATA (например, /usr/local/ pgsql/data). Как и в случае с pg_hba.conf, внесение изменений в pgjdent.conf не требует перезапуска PostgreSQL.
Содержимое файла pgjdent.conf связывает идентификационные имена с именами пользователей PostgreSQL при помощи особых определений, называемых картами идентификации. Карты идентификации обычно применяются в системах, в которых системные имена пользователей не совпадают с именами пользователей PostgreSQL. Основные правила определения и использования карт идентификации перечислены ниже.
Каждая запись файла определяется в отдельной строке и связывает имя карты, идентификационное имя пользователя и имя пользователя PostgreSQL. Файл pgjdent.conf может содержать несколько карт. Каждая группа строк, в которых указано общее имя карты, рассматривается как одна карта. Типы подключений, относящихся к пользователям данной карты, определяются содержимым файла pg_hba.conf.Отдельная запись файла pgjdent.conf состоит из трех полей: имени карты, идентификационного имени пользователя и преобразованного имени пользователя PostgreSQL:
HMfljopibi идентификационное_имя KKfl_PostgreSQL
Поля разделяются пробелами или символами табуляции.
имя_карты. Имя, используемое для ссылок на карту идентификации в файле pgjiba.conf. идентификационное_имя. Идентификационное имя обычно совпадает с именем пользователя системы, подключающегося к базе данных. Предоставляется демоном identd, работающим в системе, пытающейся установить связь с сервером. uмя_PostgreSQL. Имя пользователя PostgreSQL, соответствующее заданному идентификационному имени. Файл может содержать несколько строк с одинаковыми идентификационными именами, но разными именами PostgreSQL. Это позволяет сопоставить одной учетной записи системного пользователя несколько учетных записей пользователей PostgreSQL, относящихся к разным базам данных.Допустим, на сервере базы данных booktown имеются учетные записи системных пользователей jdrake, jworsl ey и auditor, принадлежащие соответственно двум специалистам по сбыту и аудитору.
Для двух групп пользователей было бы логично создать пару карт идентификации. Предположим, рабочая станция отдела сбыта имеет IP-адрес 192.168.1.3 и ей необходим доступ только к базе данных booktown. Рабочая станция аудитора имеет IP-адрес 192.168.1.4 и требует доступа ко всем базам данных. Файл pgajiba.conf для такого сценария приведен в листинге 8.11.
Листинг 8.11. Выбор режима аутентификации ident в файле pgajiba.conf
host booktown 192.168.1.3 255.255.255.255 ident sales
host all 192.168.1.4 255.255.255.255 ident audit
Содержимое этого конфигурационного файла означает, что компьютер sales подключается к базе данных booktown с использованием карты идентификации sales, а компьютер audit может подключаться к любой базе данных с использованием карты audit. Обе карты должны быть соответствующим образом настроены в файле pgjdent.conf. Пример настройки приведен в листинге 8.12.
Листинг 8.12. Пример файла pgjdent.conf
# MAP IDENT POSTGRESQLJJSERNAME
sales jdrake sales
sales jworsley sales
audit, auditor sales
audit auditor postgres
Файл, приведенный в листинге 8.12, разрешает системным пользователям jdrake и jworsley подключение в качестве пользователя PostgreSQL sales. Системному пользователю auditor разрешается подключение к PostgreSQL в качестве пользователя sales или postgres.
ПРИМЕЧАНИЕ
Идентификационное имя пользователя может связываться с несколькими именами пользователей PostgreSQL, как показано для пользователя auditor в листинге 8.12.>
Если вы ограничиваетесь автоматической идентификацией удаленных пользователей по методу ident, файл pgjdent.conf вам не понадобится. В этом случае вместо имени карты в файле pgjiba.conf указывается специальное ключевое слово sameuser.
Стоит напомнить, что этот вариант в целом аналогичен методу trust, но в методе ident sameuser подключения ограничиваются по имени пользователя, предоставленному демоном identd. Попытка задания имени пользователя PostgreSQL (например, при помощи ключа -U клиента psql), отличающегося от имени, передаваемого identd, приводит к отказу в подключении.
Пример использования ключевого слова sameuser приведен в листинге 8.13.
Листинг 8.13. Конфигурирование с использованием ключевого слова sameuser
host booktown 192.168.1.0 255.255.255.0 ident sameuser
В этой конфигурации любой компьютер из сетевого блока 192.168.1 может подключиться к базе данных booktown с именем PostgreSQL, совпадающим с именем пользователя, предоставленным службой identd. Ключевое слово sameuser заставляет PostgreSQL сравнивать имя пользователя PostgreSQL с именем, предоставленным identd.
Отказ в аутентификации
Если попытка аутентификации завершается неудачей, PostgreSQL обычно предоставляет содержательную информацию об ошибке, не ограничиваясь простым отказом. Ниже перечислены некоторые распространенные сообщения об ошибках с краткими пояснениями.
FATAL I: user "testuser" does not exist. Имя пользователя не найдено в системной таблице pg_shadow; это означает, что учетная запись пользователя не существует. Создание новых пользователей описано в главе 10. FATAL I: Database "testdb" does not exist In the system catalog. Указанная база данных не существует. Если при подключении к PostgreSQL имя базы данных не указано, по умолчанию используется имя текущего пользователя. No pg_hba.conf entry for host 123.123.123.1. user testuser, database testdb. Связь с сервером была установлена, но сервер не принял подключение. Причина отказа заключается в том, что сервер не находит в файле pg_hba.conf запись для пользователя testuser, обращающегося к базе данных testdb со своего IP-адреса (123.123.123.1). Password authentication failed for user 'testuser1. Связь с сервером была установлена, но в подключении отказано из-за неправильного пароля. Проверьте введенный пароль и убедитесь в его правильности. Далее следует проверить настройку аутентификационных пакетов (например, Kerberos или Ident), если они используются в вашей системе.Проверьте, назначен ли пароль указанному пользователю. Если файл pg_hba.conf настроен на проверку паролей, эта проверка производится в любом случае, даже если пароль не указан. Всем пользователям без пароля присваивается пароль NULL. Когда такой пользователь пытается подключиться без указания пароля, пароль NULL сравнивается с NULL — результат равен false.
С другой стороны, если пользователь пытается ввести пароль (пусть даже пустую строку), введенное значение также сравнивается с NULL и результат по-прежнему остается равным false. Если в системе требуется аутентификация с помощью паролей, вы должны назначить пароли всем пользователям. Если какому-либо пользователю не будет назначен пароль, аутентификация всегда будет завершаться неудачей и пользователь не сможет подключиться к серверу.
Шифрование сеанса
В эпоху электронных коммуникаций приходится уделять особое внимание вопросам конфиденциальности и защиты данных. Едва ли не каждый день приходится слышать о новых жертвах хакеров или пробелах в системе безопасности приложений, которым вы привыкли доверять.
В то же время шифрование обмена данными стало вполне обыденным явлением. На всех солидных коммерческих сайтах пересылка конфиденциальных данных (номера кредитной карты, домашнего адреса) защищается при помощи протокола SLL (Secure Sockets Layer).
Самый распространенный тип компьютерных преступлений вообще не связан со «взломом». Многие беспечные пользователи доверяют пересылку информации по Интернету таким протоколам, как POP и FTP. При этом пользователь может непреднамеренно передать свое имя и пароль в текстовом (не зашифрованном) виде.
Пересылка конфиденциальных данных в текстовом виде означает, что любой злоумышленник с программоп-сниффером (приложение, перехватывающее сетевой трафик между двумя сторонами) теоретически сможет получить доступ к секретной информации. Все сказанное относится и к области баз данных.
Удаленное подключение к PostgreSQL без шифрования данных открывает потенциальные возможности для злоупотреблений. Если хакер установит сниффер в вашей сети или в сети между клиентом и сервером, к которому вы подключаетесь, он сможет получить полный доступ ко всей информации, хранящейся в PostgreSQL.
В этом разделе мы рассмотрим три общих способа шифрования данных между PostgreSQL и клиентом.
Встроенная поддержка SSL. Поддержка SSL в PostgreSQL активизируется при компиляции с ключом --with-ssl. Это позволяет psql (или любому клиенту, написанному с учетом возможности подключения к PostgreSQL через SSL) установить защищенное подключение к PostgreSQL. SSH/OpenSSH. Сеанс SSH (Secure SHell) позволяет создать туннель (tunnel) к удаленному серверу — при условии, что демон SSH (например, sshd) установлен в системе и доступен для подключающегося пользователя. Для этого в системе, в которой работает PostgreSQL, создается учетная запись для каждого пользователя. Stunnel. Приложение Stunnel создает шифрованный туннель для обмена данными между клиентом и сервером PostgreSQL. Для пользователей, не имеющих прямого доступа к удаленному серверу, Stunnel можно настроить на работу в клиентской системе.Встроенная поддержка SSL
В PostgreSQL предусмотрена возможность активизации встроенной поддержки SSL при помощи ключа конфигурации - -with-ssl. Этот вариант особенно удобен в тех случаях, когда для работы с PostgreSQL вы собираетесь в основном использовать psql, потому что в этом клиенте предусмотрена внутренняя поддержка подобного способа подключения.
Большинство пользователей предпочитает работать с PostgreSQL при помощи всевозможных клиентских приложений. В этом случае вам придется либо самостоятельно написать клиента, поддерживающего SSL-подключение к PostgreSQL, либо выбрать внешнюю схему шифрования сеансов между клиентом/приложением и сервером PostgreSQL (например, SSH или Stunnel).
SSH/OpenSSH
OpenSSH является превосходным средством внешнего шифрования обмена данными между клиентом и сервером. Профессионалы в области безопасности и системные администраторы фактически приняли OpenSSH как стандарт в области шифрования. Чаще всего OpenSSH используется в терминальных приложениях или в программах пересылки файлов. Протокол SSH обеспечивает обобщенный механизм шифрования, применимый практически в любой области.
Имея доступ к системной учетной записи на удаленном сервере, можно пройти аутентификацию и открыть туннель между удаленным и локальным хостами с ключом -L. Туннель прослушивает заданный порт локального компьютера, шифрует поступающие пакеты данных и отправляет их на удаленный сервер в зашифрованном виде. Там данные расшифровываются и передаются на указанный порт удаленного сервера.
Подобная схема позволяет легко создать обобщенный туннель для обмена шифрованными данными между клиентом и сервером. Более того, весь процесс остается прозрачным для системы PostgreSQL, полагающей, что пакетные входные данные поступают с локального компьютера от пользователя, создавшего туннель. Обратите внимание на это обстоятельство, поскольку оно требует внесения соответствующих изменений в файл pg_hba.conf.
Исполняемый файл SSH обычно называется ssh, а туннель создается командой следующего вида:
ssh -L лок_порт:уддл_хост:удал_порт пользователь@удал_хост
Параметрлок_порт содержит произвольный номер порта, по которому организуется локальное прослушивание. Номер порта должен быть больше 1024 (если команда не выполняется с правами root, чего делать не рекомендуется). Заданное число определяет тот номер порта, по которому, как полагает ваш клиент, он подключен к PostgreSQL. В действительности данные, передаваемые через этот порт, попадают на порт прослушивания SSH (обычно порт 22) удаленного хоста, расшифровываются и затем передаются на заданный порт удаленного хоста.
Секция полъзователь@удал_хост необходима для аутентификации системных пользователей. Без действительной учетной записи на удаленном хосте создать туннель SSH не удастся. Весь процесс создания туннеля продемонстрирован в листинге 8.14, в котором два терминальных сеанса разделены многоточием. Первое терминальное подключение создает туннель SSH и остается активным, чтобы туннель продолжал существование. Второе терминальное подключение использует туннель для установки связи с локальным портом и последующей пересылки данных на удаленный хост, их расшифровки и передачи серверу PostgreSQL.
Листинг 8.14. Создание туннеля SSH на сервере PostgreSQL
[user@local ~]$ ssh -L 4001:remotehost:5432 userPremotehost
user@remotehost's password: [user@remote -]$
[user@local -]$ psql -h localhost -p 4001 tempiatel
Welcome to psql, the PostgreSQL Interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
tempiatel=#
ПРИМЕЧАНИЕ
Если после создания туннеля SSH вам не нужно переходить в режим командной строки, как это происходит по умолчанию, включите в команду ssh ключ -Т. В этом случае после аутентификации терминал перестает реагировать на действия пользователя. После завершения сеанс прерывается комбинацией клавиш Ctrl+C.
Единственный недостаток механизма туннелей SSH заключается в том, что он требует наличия системной учетной записи для пользователя, подключающегося к PostgreSQL. SSH не предоставляет абсолютно прозрачного доступа к шифрованным потокам данных до тех пор, пока пользователь не инициирует соединение и не пройдет аутентификацию у демона ssh, обычно называемого sshd. В зависимости от ситуации это ограничение может приносить как пользу, так и вред.
Тем, кто захочет создать туннель шифрования данных еще более общего характера, стоит рассмотреть возможность использования пакета Stunnel.
Настройка и использование пакета Stunnel
Хотя встроенная поддержка SSL и OpenSSH обеспечивают надежный, хорошо защищенный обмен данными с PostgreSQL, у этих инструментов имеются свои особенности и недостатки. Многие пользователи PostgreSQL интересуются, существует ли другой способ шифрования с полностью прозрачным удаленным доступом к серверу. Если вы хотите обеспечить прозрачное шифрование сеанса для любого клиента, без обязательной привязки к SSH, в вашем распоряжении два общедоступных средства: OpenSSL и Stunnel.
Системные администраторы Unix и Linux обычно знакомы с одним или обоими пакетами, поскольку они часто используются в других областях (в конце концов, шифрование применяется не только в контексте PostgreSQL). А если вы еще не сталкивались с шифрованием обмена данными, с этой проблемой стоит познакомиться поближе.
OpenSSL
Программный пакет OpenSSL был разработан группой, входящей в сообщество Open Source. Это довольно мощный инструментарий, позволяющий реализовать в системе протокол SSL (Secure Sockets Layer) и другие протоколы, применяемые в области безопасности данных — например, TLS (Transport Layer Security). Кроме того, в OpenSSL входит библиотека криптографических функций. Этот пакет пригодится всем, кто уделяет внимание проблемам безопасности системы Linux (его область применения не ограничивается PostgreSQL, хотя ниже основное внимание будет уделяться именно этому аспекту). Пакет распространяется с открытыми исходными текстами, поэтому вы сможете загрузить его бесплатно, тогда как коммерческие пакеты SSL потребуют расходов на приобретение и/или лицензирование.
За последней версией OpenSSL обратитесь на web-страницу OpenSSL по адресу http://www.openssl.org. Здесь вы найдете список существующих версий со ссылками для загрузки. Существует две разновидности версий: рабочие и бета-версии. Также имеются ссылки на более старые версии с исправленными ошибками. Вероятно, вас заинтересует последняя рабочая версия или подобная версия с исправленными ошибками.
Рабочие версии выглядят в списке примерно так:
09-Jul-2001: OpenSSL 0.9.6b is now available, a major release
Откройте страницу по ссылке available. На ней можно загрузить новейшую версию OpenSSL, помеченную словом [LATEST].
Загрузите файл выбранной версии и сохраните его в домашнем каталоге (или другом каталоге, в котором вы обычно сохраняете файлы). После завершения пересылки откройте консольное окно и перейдите в этот каталог командой cd. Файл запакован и заархивирован, поэтому его необходимо извлечь следующей командой (поле [версия]заменяется номером версии продукта — например, 0.0.6b):
gzip -d openssl-<f версияj.tar.gz
Затем введите следующую команду:
tar xf openssl-/"версия.?.tar
Эти команды распаковывают файлы OpenSSL в каталог с именем openssl-[версия], где [версия] — номер версии продукта.
ПРИМЕЧАНИЕ
Если вы используете GNU-версию tar, вместо отдельных команд gzip и tar достаточно ввести команду tar -xzf openssl -[версия].tar.gz.
Чтобы завершить установку OpenSSL, перейдите в каталог установки. OpenSSL поставляется в виде исходных текстов, поэтому продукт необходимо откомпилировать. Прежде чем переходить к компиляции, убедитесь в наличии следующих компонентов:
утилита gmake (или make); Perl версии 5 и выше; компилятор ANSI С; среда разработки (библиотеки разработки, заголовочные файлы С); поддерживаемая Unix-совместимая операционная система.Если у вас имеется все необходимое, можно переходить к компиляции. В противном случае перед установкой OpenSSL придется загрузить и установить недостающие продукты.
Последовательность установки описана ниже. Если у вас возникнут проблемы, обратитесь к файлу INSTALL (из которого взята приведенная инструкция).
. Указанной ниже командой запустите сценарий конфигурирования, который собирает информацию о системе и производит настройку установочных сценариев OpenSSL. Сбор информации потребует некоторого времени, хотя продолжительность его работы зависит от производительности системы.Откомпилируйте пакет OpenSSL следующей командой (после завершения конфигурирования эта команда начинает компиляцию исходных текстов, что даже на быстрых компьютерах занимает много времени):$ ,/config
После завершения компиляции запустите тест (команда проверяет, успешно ли прошла компиляция; при обнаружении ошибок обращайтесь к файлу INSTALL):$ make
Если тестирование прошло успешно, установите двоичные файлы OpenSSL:$ make test
$ make install
На этом установка OpenSSL завершается. Если у вас возникнут проблемы, обращайтесь к документации (а именно к файлам INSTALL и README).
Stunnel
Stunnel представляет собой оболочку SSL, то есть позволяет наделить поддержкой SSL демона, не рассчитанного на безопасный обмен данными. При помощи Stunnel можно установить защищенный канал связи с базой данных PostgreSQL, улучшить общую безопасность системы и защитить данные.
Пакет Stunnel распространяется с сайта http://www.stunnel.org. Перейдите по этому адресу, откройте страницу загрузки и щелкните на ссылке Get the source code. Начнется загрузка последней версии пакета. Сохраните файл в домашнем или любом другом каталоге файловой системы. Завершив загрузку Stunnel, откройте консольное окно и перейдите в каталог с принятым файлом. Распакуйте файл следующими командами:
$ gzip -d stunnel-[версия].tar.gz $ tar xf stunnel-[версия].tar
Файлы Stunnel распаковываются в каталог с именем st\mne\-[версия], где [версия] — номер версии продукта. К счастью, установка Stunnel обычно проходит быстрее, чем установка OpenSSL. После распаковки файлов перейдите в созданный каталог с помощью команды cd. Помните, что пакет OpenSSL должен быть уже установлен в системе, без него установка Stunnel не работает. Процедура построения и установки Stunnel описана ниже.
Запустите сценарий конфигурации, который собирает информацию о системе и производит настройку установочных сценариев Stunnel:Откомпилируйте исходные тексты Stunnel следующей командой make, которая создает исполняемые файлы по исходным текстам Stunnel. В процессе компиляции вам будет предложено ввести сведения о местонахождении и имени домена. Введенные данные используются для построения файла stunnel.pern. В этом файле хранится сертификат, при помощи которого шифруются данные.$ ./configure
Если компиляция прошла успешно, установите двоичные файлы OpenSSL следующей командой, которая устанавливает откомпилированные файлы:$ make
$ make install
Запуск Stunnel
Существует два варианта работы Stunnel в системе: использование inetd или запуск двоичного файла Stunnel в режиме демона. Второй вариант считается пред-лочтительным, поскольку использование inetd накладывает на работу пакета некоторые ограничения, связанные с особенностями SSL, в том числе:
для каждого подключения необходимо инициализировать Stunnel демоном inetd; кэширование сеанса невозможно; использование inetd сопровождается порождением новых процессов, что требует дополнительных затрат процессорного времени.Пакет Stunnel позволяет устанавливать защищенные подключения как к удаленным, так и к локальным базам данных. Если клиент psql обращается к базе данных, обслуживаемой другим хостом, создается защищенный канал обмена данными между psql и этой базой данных. Если база данных находится на одном компьютере с клиентом psql, можно создать защищенный канал обмена данными между двумя локальными программами (на случай, если вы опасаетесь прослушивания локальных подключений через сокеты TCP/IP).
В каталоге Stunnel должен находиться файл с именем stunnel; это исполняемый файл программы. Далее предполагается, что исполняемый файл хранится в этом каталоге, однако вы можете скопировать его в каталог /usr/local/sbin или любой другой каталог по своему усмотрению. Кроме того, ссылку на этот файл можно включить в стартовый сценарий, чтобы он автоматически запускался (в виде одного или двух процессов по вашему выбору) во время загрузки системы.
ПРИМЕЧАНИЕ
Если Stunnel используется с inetd, запускать файл в стартовом сценарии не нужно.
Запуск Stunnel в режиме демона
Запуск Stunnel в режиме демона не вызывает проблем при подключении как к локальным, так и к удаленным базам данных. Чтобы использовать Stunnel для подключения к локальной базе данных, следует запустить пакет в режиме клиента и сервера (два разных процесса одной программы, работающих на разных портах). Затем вы приказываете psql подключиться к номеру порта, на котором работает клиентская часть Stunnel.
После того как psql подключится к клиенту, все данные автоматически шифруются и передаются серверу Stunnel, работающему на другом порте, номер которого сообщается клиенту при запуске. Сервер расшифровывает данные и пересылает их серверу PostgreSQL. Клиент должен знать свой номер порта, а также номер порта, на котором работает сервер, чтобы передать ему зашифрованные данные.
Впрочем, Stunnel чаще применяется для передачи данных от локального клиента удаленному серверу. Для этого следует запустить локальный клиентский процесс Stunnel либо включением в стартовый сценарий (например, /etc/rc.d/rc.local), либо непосредственным запуском из каталога. Затем удаленный процесс Stunnel запускается на хосте, на котором работает PostgreSQL. Сервер, как и клиент, обычно запускается автоматически в процессе загрузки системы.
Примеры запуска клиентской и серверной частей Stunnel приведены в листинге 8.15. Если исполняемый файл stunnel не был скопирован в каталог /usr/sbin, Stunnel следует запускать из каталога установки.
Листинг 8.15. Использование Stunnel при удаленных подключениях
[user@remote -]$ # Запуск сервера на удаленном компьютере
[user@remote -]$ stunnel -P/tmp/ -p -/stunnel.pern -d 9000 -г local host:5432
[user@local -]$ # Запуск клиента на локальном компьютере
[user@local -]$ stunnel -P/tmp/ -c -d 5432 -г 192.168.1.2:9000
Первая команда в листинге 8.15 приказывает серверу использовать в качестве сертификата для шифрования файл ~/stunnel.pem и запустить процесс Stunnel в режиме демона. Параметр -d 9000 означает, что демон должен прослушивать порт 9000. Параметр - г 1 оса! host: 5432 сообщает процессу-демону, что при получении зашифрованных данных на прослушиваемом порте (в данном примере — 9000) эти данные необходимо расшифровать и передать локальному хосту на порт 5432 (номер порта PostgreSQL). Таким образом, расшифрованные данные будут переданы серверу базы данных на локальном хосте.
Вторая команда запускает экземпляр Stunnel на клиентском компьютере в режиме клиента (на что указывает ключ -с) с прослушиванием порта 5432. Параметр -г 192.168.1.2:9000 сообщает процессу, что сервер работает по адресу 192.168.1.2:9000 и прослушивает зашифрованные пакеты на порте 9000.
В обоих режимах обязательный ключ -P/tmp/ сообщает путь к временному файлу PID, в котором хранится системный идентификатор процесса Stunnel. Указывать имя файла не обязательно, достаточно пути (по умолчанию используется имя вида stunnel.localhost.9000.pid), хотя при желании можно задать полное имя.
После того как оба процесса Stunnel заработают на своих хостах, клиент psql направляется на порт 5432 клиентского компьютера. Пакеты, отправляемые на этот порт, проходят прозрачное шифрование, перенаправляются на порт 9000 серверного компьютера, расшифровываются и передаются PostgreSQL на порт 5432. Происходящее напоминает туннели SSH, о которых говорилось в подразделе «SSH/ OpenSSH», но между ними существует одно важное различие: клиентский процесс Stunnel может создаваться без аутентификации на удаленном сервере. Таким образом, любой пользователь может создать защищенного «отправителя» на сервере базы данных, хотя при этом все равно потребуется создать защищенного «получателя», принимающего зашифрованные данные.
Шифрование полностью отделено от обычной процедуры аутентификации PostgreSQL; с точки зрения серверного процесса postmaster данные поступают в текстовом виде, поскольку они проходят предварительную расшифровку. Stunnel идеально работает в сочетании с парольной аутентификацией — пароли обеспечивают необходимое ограничение доступа и пересылаются по сети в зашифрованном виде.
Кроме того, как упоминалось выше, локальный запуск двух процессов Stunnel позволяет шифровать пакеты, передаваемые между двумя локальными портами TCP/IP. В листинге 8.16 приведен пример запуска клиентского и серверного процессов на одном компьютере.
Листинг 8.16. Локальный запуск Stunnel
[user@local -]$ stunnel -P/tmp/ -p -/stunnel-3.15/stunnel.pern -d 9000 -r 5432
[user@local -]$ stunnel -P/tmp/ -c -d 5433 -r local host:9000
Первая команда запускает серверный процесс, использующий файл сертификата ~/stunnel-3.15/stunnel.pem. Демон прослушивает подключения на порте 9000 и передает расшифрованные данные с этого порта на порт 5432. В примере использован номер 5432, потому что сервер PostgreSQL работает на этом порте.
Вторая команда запуска Stunnel в листинге 8.16 открывает клиентский процесс Stunnel на порте 5433 (порт выбирается произвольно; в данном примере он напоминает номер порта PostgreSQL). Демон шифрует входящие данные и передает их серверному процессу на порт 9000 локального хоста.
Запуск Stunnel с использованием inetd
Если вы предпочитаете, чтобы на серверной стороне экземпляры Stunnel запускались по запросу, вместо режима демона можно воспользоваться службой inetd (или xinetd в новых системах). Как упоминалось выше, это может привести к снижению быстродействия. Но если вы готовы смириться с этим, задача решается относительно легко. Сначала нужно отредактировать файл /etc/services и добавить в него строку для серверного процесса. Достаточно строки следующего вида:
pgssl 9000/tcp # Оболочка stunnel для PostgreSQL
В зависимости от того, какая служба используется в вашей системе, inetd или xinetd, следует либо включить новую службу в файл /etc/inetd.conf, либо создать новый файл службы в каталоге /etc/xinetd.d/. В том и другом случае требуется ввести полную команду (со всеми аргументами, передаваемыми программе). Команда должна иметь следующий формат:
stunnel -P/tmp/ -р путь!stunnel.pern -г порт
В этой команде путь означает каталог, в котором находится файл сертификата (первоначально он находится в каталоге, в котором был откомпилирован пакет Stunnel), а порт — порт, по которому прослушивает PostgreSQL (обычно порт 5432). Главное различие в синтаксисе вызова stunnel при помощи службы inetd и в режиме демона заключается в том, что в первом случае ключ -d не указывается.
В листинге 8.17 показано, как выглядит примерная запись в файле inetd.conf. Запись должна полностью помещаться в одной строке. Конечно, в этой записи необходимо указать каталог с файлом сертификата, используемый в вашей системе, причем этот каталог должен быть доступен для чтения пользователем, указанным в файле inetd.conf. Строка /usr/bln/stunnel содержит полный путь к двоичному файлу Stunnel.
Листинг 8.17. Примерная запись inetd
pgssl stream tcp nowait root /usr/sbin/stunnel -P/tmp/ -p /root/my.pern -r 5432
В листинге 8.17 указан пользователь root, но по соображениям безопасности лучше задать пользователя, обладающего меньшими правами. Для незарезервированных портов может быть указан любой пользователь, имеющий право доступа для чтения к файлу сертификата и право исполнения для двоичного файла stunnel.
Примерная конфигурация для xinetd приведена в листинге 8.18. В системах, использующих xinetd, эти данные будут храниться в файле /etc/xinetd.d/pgssl. Также следует проверить, что каталог, указанный после ключа -р, соответствует фактическому расположению файла сертификата. Как и в случае с inetd, запускать stunnel с правами root не рекомендуется.
Листинг 8.18. Примерная запись xinetd
# Конфигурация xinetd для pgssl.
service pgssl
{
disable = no
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/sbin/stunnel
server_args = -P/tmp/ -p /root/stunnel.pern -r 5432
}
После настройки конфигурации inetd или xinetd следует перезапустить соответствующую службу (в системах Red Hat это обычно делается командой service):
root@host -]# service xinetd restart
Stopping xinetd: [ OK ]
Starting xinetd: [ OK ]
[root(?host -]#
<
Если команда service недоступна, того же результата обычно можно добиться при помощи команды killall с параметрами -HUP и именем процесса, например:
kill all -HUP xinetd
ВНИМАНИЕ
Проследите за тем, чтобы файл сертификата был доступен для чтения только со стороны пользователя, запустившего серверный процесс stunnel.
Выводы
После завершения всех описанных действий вы сможете установить защищенное подключение к базе данных PostgreSQL из любого клиента PostgreSQL. В psql можно воспользоваться следующей командой:
psql -р порт -h хост -и пользователь база_данных
Сначала указывается номер порта, по которому ведет прослушивание клиент Stunnel, затем хост (localhost в данном случае), имя пользователя и база данных, к которой вы хотите подключиться. В результате клиент подключается к базе данных точно так же, как если бы она была открыта в psql локально.
ПРИМЕЧАНИЕ
Чтобы процесс postmaster взаимодействовал с Stunnel, он должен быть запущен с ключом -i. Ключ -i активизирует поддержку TCP/IP, необходимую для работы Stunnel.