Итак, вот такая ситуация. Похоже, нам нужен открытый TCP-порт 5432 для мира, где у клиента есть доступ к своей базе данных PostgreSQL.
По понятным причинам мы не можем сказать просто «нет», только в крайнем случае.
Какие самые большие проблемы? Как я могу защитить нашу инфраструктуру?
В любом случае: почему не должен быть открытым миру? Я думаю, может быть, это более безопасно, чем какой-то 20-летний необслуживаемый FTP-сервер.
P.S. VPN не подходит. Некоторое шифрование может быть (если я могу дать ему URL-адрес соединения JDBC, который работает).
Требовать SSL, держать SELinux включенным, отслеживать журналы и использовать текущую версию PostgreSQL.
В postgresql.conf
устанавливать ssl=on
и убедитесь, что ваш ключевой файл и файл сертификата установлены надлежащим образом (см. документы и комментарии в postgresql.conf
).
Вам может потребоваться купить сертификат в ЦС, если вы хотите, чтобы ему доверяли клиенты без специальной настройки на клиенте.
В pg_hba.conf
используйте что-то вроде:
hostssl theuser thedatabase 1.2.3.4/32 md5
... возможно, со словом «все» для пользователя и / или базы данных и, возможно, с более широким фильтром IP-адресов источника.
Если возможно, не разрешайте пользователям «всех»; вы не хотите разрешать вход суперпользователя удаленно, если вы можете избежать в этом необходимости.
Ограничьте права пользователей, которые могут войти в систему. Не давайте им CREATEDB
или CREATEUSER
прав.
REVOKE
то CONNECT
прямо из PUBLIC
во всех ваших базах данных, а затем верните его только тем пользователям / ролям, которые должны иметь доступ к этой базе данных. (Группируйте пользователей по ролям и предоставляйте права ролям, а не напрямую отдельным пользователям).
Убедитесь, что пользователи с удаленным доступом могут подключаться только к нужным им БД и имеют права только на те схемы, таблицы и столбцы, которые им действительно нужны. Это хорошая практика и для локальных пользователей, это просто разумная безопасность.
В PgJDBC передайте параметр ssl=true
:
Чтобы указать драйверу JDBC попытаться установить SSL-соединение, вы должны добавить параметр URL-адреса соединения ssl = true.
... и установите сертификат сервера в хранилище доверенных сертификатов клиента или используйте сертификат сервера, которому доверяет один из центров сертификации во встроенном хранилище доверенных сертификатов Java, если вы не хотите, чтобы пользователю приходилось устанавливать сертификат.
Сейчас убедитесь, что вы обновляете PostgreSQL. У PostgreSQL было всего несколько дыр в безопасности до авторизации, но их больше нуля, так что будьте в курсе. В любом случае, вы должны, исправления ошибок - это хорошо.
Добавьте брандмауэр впереди, если есть большие сетевые блоки / регионы, из которых вы знаете, что вам никогда не понадобится доступ.
Журнал подключений и отключений (см. postgresql.conf
). Запросы в журнал, если это возможно. Запустите систему обнаружения вторжений или fail2ban или подобное заранее, если это возможно. Для fail2ban с postgres есть удобная инструкция Вот
Следите за файлами журнала.
Дополнительные шаги, о которых нужно подумать ...
Если хотите, вы также можете использовать pg_hba.conf
требовать, чтобы клиент представил сертификат клиента X.509, которому доверяет сервер. Необязательно использовать тот же ЦС, что и сертификат сервера, вы можете сделать это с помощью доморощенного ЦС openssl. Пользователь JDBC должен импортировать сертификат клиента в свое хранилище ключей Java с помощью keytool
и, возможно, настроить некоторые системные свойства JSSE так, чтобы они указывали Java на их хранилище ключей, чтобы оно не было полностью прозрачным.
Если вы хотите быть действительно параноиком, запустите экземпляр для клиента в отдельном контейнере / виртуальной машине или, по крайней мере, под другой учетной записью пользователя, используя только необходимые им базы данных.
Таким образом, если они скомпрометируют экземпляр PostgreSQL, они не продвинутся дальше.
Мне не следовало говорить это, но ...
Запустите машину с поддержкой SELinux, например RHEL 6 или 7, и не выключайте SELinux и не устанавливайте его в разрешающий режим. Держите его в принудительном режиме.
Безопасность только безвестность - это глупость. Безопасность, которая использует немного неясности после того, как вы сделали разумные вещи, вероятно, не повредит.
Запустите Pg на порту, отличном от порта по умолчанию, чтобы немного усложнить жизнь автоматическим злоумышленникам.
Вы также можете запустить PgBouncer или PgPool-II перед PostgreSQL, выступая в качестве пула соединений и прокси. Таким образом вы можете позволить прокси обрабатывать SSL, а не реальный хост базы данных. Прокси-сервер может находиться на отдельной виртуальной машине или машине.
Использование прокси-серверов пула соединений в любом случае является хорошей идеей для PostgreSQL, если только клиентское приложение не имеет встроенного пула. Большинство серверов приложений Java, Rails и т. Д. Имеют встроенный пул. Даже в этом случае прокси-сервер пула в худшем случае безвреден.
Вот довольно простая конфигурация Fail2ban для PostgreSQL, основанная на HOWTO, ссылка на которую приведена выше, но настроенная для реальной работы с пакетами Ubuntu, выявления другого состояния ошибки и пропуска различных сообщений отладки, чтобы ускорить процесс:
/etc/fail2ban/filter.d/local-postgresql.conf
:
[Definition]
failregex = <HOST>\(\d+\) FATAL: password authentication failed for .+$
<HOST>\(\d+\) FATAL: no pg_hba.conf entry for host .+$
ignoreregex = duration:
/etc/fail2ban/jail.d/local-postgresql.conf
:
[local-postgresql]
enabled = true
filter = local-postgresql
action = iptables[name=PostgreSQL, port=5432, protocol=tcp]
sendmail-whois[name=PostgreSQL, dest=root@localhost]
logpath = /var/log/postgresql/postgresql-9.3-main.log
maxretry = 3
Простое расширение впечатляющего плана действий Крейгса:
Возможно, пользователь использует лишь относительно небольшой набор сетевых провайдеров (например, его мобильный сетевой провайдер во время движения, его кабельная сеть из дома и исходящий IP-адрес с работы).
У большинства сетевых провайдеров много IP-адресов, но не так много подсетей. Итак, вы можете указать фильтр iptables, который ограничивает доступ postgresql к сегментам сети, которые использует ваш клиент. Это значительно снизило возможности атаки случайно выбранных источников проблем в сети.
Простой сценарий поддержки:
tcpdump -i eth0 -p tcp port 5432
команда, откуда он.whois 1.2.3.4
вы можете получить IP-адрес, используемый этим IP. Например, это может быть 1.2.3.0/24
.iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT
(или что-то подобное) вы разрешаете TCP-соединения с его новой подсетью.Есть очень хороший скрипт на Perl под названием uif
который может предоставить постоянные и интуитивно понятные декларируемые наборы правил iptables. (Google для "uif iptables").
Fail2ban - мощный инструмент, но не верьте, что фильтр будет работать как есть. Проверьте любые фильтры с помощью инструмент failregex, и не забудьте избегать кавычек (т.е. "admin" будет \ "admin \"). Например, тестирование следующей строки filter failregex из моего /etc/log/postgresql/postgresql-9.3-main.log у меня не сработало.
fail2ban-regex '2016-09-20 14:30:09 PDT FATAL: password authentication failed for user "admin"' '<HOST>\(\d+\) FATAL: password authentication failed for .+$'
Вышеупомянутое дало мне
Failregex: всего 0
Мне пришлось обновить failregex, чтобы он соответствовал формату журнала.
fail2ban-regex '2016-09-20 14:30:09 PDT FATAL: password authentication failed for user "admin"' 'FATAL: password authentication failed for user \"<HOST>\"'
Это дало мне положительный результат.
Failregex: всего 1
Тест fail2ban-regex также может быть реализован для всех файлов журнала.
fail2ban-regex /var/log/postgresql/postgresql-9.3-main.log /etc/fail2ban/filter.d/postgresql.local
Вышесказанное дало мне следующий положительный результат с обновленным failregex.
Failregex: всего 169