АйТи Фреш
Главная / Статьи / 1С и базы данных
1С и базы данных

Дописал reject в конец pg_hba.conf, а человек всё равно заходит: как на самом деле работает порядок правил в PostgreSQL 18

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~27 мин чтения
Дописал reject в конец pg_hba.conf, а человек всё равно заходит: как на самом деле работает порядок правил в PostgreSQL 18
Иллюстрация к статье «Дописал reject в конец pg_hba.conf, а человек всё равно заходит: как на самом деле работает порядок правил в PostgreSQL 18».

Уволился аналитик, на ноутбуке остался DBeaver с сохранённым паролем к боевой базе. Админ дописывает в конец pg_hba.conf строку с reject, сохраняет и закрывает вопрос. Через неделю в логах видно, что с того же адреса кто-то спокойно работает. Разбираю, почему точный запрет проигрывает общему разрешению, как за пять минут понять, читает ли сервер тот файл, который вы правите, и как выстроить pg_hba.conf так, чтобы порядок строк не приходилось держать в голове.

reject в конце файла не запрещает ничего

Начну с механики, потому что она объясняет 90 % таких обращений. PostgreSQL читает pg_hba.conf сверху вниз и останавливается на первой строке, которая совпала одновременно по четырём параметрам: тип подключения, адрес клиента, запрошенная база данных и имя пользователя. Дальше он не смотрит вообще. В документации 18-й версии это написано прямым текстом: «The first record with a matching connection type, client address, requested database, and user name is used to perform authentication. There is no „fall-through“ or „backup“: if one record is chosen and the authentication fails, subsequent records are not considered. If no record matches, access is denied». То есть никакого «отката» на следующее подходящее правило нет: выбрали строку — работаем по ней, чем бы это ни закончилось.

Ошибка почти всегда одна и та же и она не в синтаксисе. Человек переносит на pg_hba логику маршрутизации, где выигрывает самый длинный префикс, и ждёт, что /32 окажется важнее /0 независимо от места в файле. В pg_hba такого нет. Здесь всё решает физический порядок строк, как в списке ACL, который просматривается последовательно. Если выше уже стоит host all all 0.0.0.0/0 scram-sha-256, то любая последующая строка про конкретный хост — мёртвый текст. Она формально валидна, она видна в pg_hba_file_rules, она даже получит свой номер правила — и никогда не будет выбрана.

Смотрите на типичный «до» и «после». Файл слева выглядит логично для человека и не работает; файл справа выглядит некрасиво и работает.

# НЕ РАБОТАЕТ: точный запрет ниже общего разрешения
local   all             all                                     peer
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             192.168.10.0/24         scram-sha-256
host    all             all             192.168.10.77/32        reject

# РАБОТАЕТ: запрет выше разрешения
local   all             all                                     peer
host    all             all             192.168.10.77/32        reject
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             192.168.10.0/24         scram-sha-256
host    all             all             all                     reject

Документация формулирует это как рекомендацию по стилю: «Typically, earlier records will have tight connection match parameters and weaker authentication methods, while later records will have looser match parameters and stronger authentication methods». Читайте так: сверху узкое и точное, снизу широкое и общее. Всё, что вы хотите запретить адресно, живёт в верхней трети файла. Всё, что разрешаете массово, — в нижней.

reject не делает исключений ни для кого, включая суперпользователя postgres. Если вы поставите его первой строкой с адресом all, вы закроете себе доступ по TCP до следующего reload. Оставляйте себе живую строку local или сессию, открытую заранее.

Диагностика за пять минут: тот ли файл, та ли строка, применён ли он

Прежде чем спорить о порядке правил, я всегда проверяю три вещи в таком порядке: какой файл сервер реально читает, как он разобрал строки и перечитал ли он их после правки. Три запроса, меньше минуты. На Debian и Ubuntu конфиги живут в /etc/postgresql/18/main/, на RHEL-подобных — прямо в каталоге данных /var/lib/pgsql/18/data/, а если кластеров на машине несколько, шансы отредактировать чужой файл резко растут. Спрашивайте у сервера, а не у файловой системы.

# 1. Какой именно файл читает ЭТОТ инстанс
psql -p 5432 -c 'SHOW hba_file;'
psql -p 5432 -c 'SHOW config_file;'

# 2. Как сервер разобрал правила (только суперпользователь)
psql -x -c "SELECT rule_number, file_name, line_number, type, database, user_name, address, auth_method, error FROM pg_hba_file_rules ORDER BY rule_number;"

# 3. Только сломанные строки
psql -c "SELECT file_name, line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;"

В представлении pg_hba_file_rules колонка rule_number — это и есть номер, «indicates the order in which each rule is considered until a match is found during authentication». Если у строки rule_number пустой, а error заполнен — строка не разобралась и в правилах её нет вообще. Это второй по частоте случай после порядка: опечатка в маске, лишний пробел внутри списка баз, не закавыченное имя с дефисом. Файл выглядит правильным, сервер молча его пропустил. Обратите внимание, что представление показывает содержимое файла на диске, а не то, что сейчас в памяти постмастера, — оно как раз для предварительной проверки перед reload.

И третье: применение. На Unix изменения подхватываются при старте и по SIGHUP — «you will need to signal the postmaster (using pg_ctl reload, calling the SQL function pg_reload_conf(), or using kill -HUP) to make it re-read the file». На Windows отдельная история: там правки применяются сразу к последующим новым подключениям, сигнал слать не нужно. Я видел, как из-за этой разницы админ, привыкший к Windows-стенду, две недели правил файл на Linux-сервере и искренне считал, что настройка не работает.

reload с битым pg_hba.conf не роняет сервер: постмастер оставляет в силе прежние правила и пишет в лог «pg_hba.conf was not reloaded». Поэтому «я перезагрузил конфиг» и «новые правила действуют» — это два разных утверждения, проверяйте оба.
Дописал reject в конец pg_hba.conf, а человек всё равно заходит: как на самом деле работает порядок правил в PostgreSQL 18 — схема
Схема к статье. Открыть схему в полном размере

Разбор из практики: хостел «Гавань», 14 рабочих мест, запрет, который ничего не запретил

Хостел «Гавань»: 14 рабочих мест — ресепшен в две смены, бухгалтерия, управляющий и пара ноутбуков у приходящих специалистов. 1С:Управление нашей фирмой на PostgreSQL, сервер 1С и СУБД на одной физической машине в подсобке, рядом отдельная база с выгрузками из системы бронирования. На момент разбора — PostgreSQL 18.6, в кластере четыре базы, боевая 1С занимает около 30 ГБ, рабочие процессы сервера 1С держат десяток постоянных соединений. Обратились с формулировкой «бывший подрядчик ходит в базу, хотя мы его заблокировали»: человек полгода строил отчёты по загрузке номеров напрямую из PostgreSQL через DBeaver, договор закончился, а в журнале продолжали появляться его запросы.

Блокировали так: в конец pg_hba.conf дописали строку host all all 192.168.10.77/32 reject и на этом остановились. Дальше по пунктам, что показал разбор. Первое: строка стояла девятой, а разрешение host all all 192.168.10.0/24 scram-sha-256 — пятой. То есть до девятой очередь не доходила физически. Второе, и это интереснее: reload вообще никто не делал. Файл пролежал изменённым трое суток, а постмастер всё это время работал по конфигу, прочитанному при последнем рестарте после обновления платформы месяц назад. Оба факта видно в одном запросе — pg_hba_file_rules показывает файл с диска, и там строка уже была, а в логе аутентификации за три дня не было ни одного отказа.

$ psql -c "SELECT rule_number, line_number, address, netmask, auth_method FROM pg_hba_file_rules WHERE address LIKE '192.168.10.%';"
 rule_number | line_number |    address    |     netmask     | auth_method
-------------+-------------+---------------+-----------------+---------------
           5 |          96 | 192.168.10.0  | 255.255.255.0   | scram-sha-256
           9 |         118 | 192.168.10.77 | 255.255.255.255 | reject

Третье — и вот это уже про то, о чём почти никогда не думают. Даже после исправления порядка и корректного reload сессия сотрудника осталась жива. В pg_stat_activity висело соединение с backend_start девятидневной давности: DBeaver держал коннект открытым, ноутбук подрядчика стоял в гостевой комнате персонала и не выключался, а pg_hba проверяется только в момент установления соединения. Правило нового подключения не пускало — но старое работало как ни в чём не бывало.

Итог по работам занял двадцать минут. Подняли reject в верхнюю часть файла, сразу после блока local. Отдельно проверили, что строка для сервера 1С (он ходит на 127.0.0.1 и ::1) осталась выше запретов и учётная запись 1С не задета. Сделали pg_ctl reload и убедились по логу, что файл принят. Прибили живые сессии с этого адреса через pg_terminate_backend. Сменили пароль роли — потому что запрет по IP снимается сменой сети, а скомпрометированный пароль остаётся скомпрометированным. И в конец файла добавили явный host all all all reject, чтобы неучтённые адреса получали внятный отказ в логе, а не неявное «no pg_hba.conf entry». За месяц наблюдения — три попытки с того же ноутбука, все в логе, все отбиты.

Запрет по адресу — это не отзыв доступа, это фильтр на сетевом уровне внутри СУБД. Если человек уволен, порядок такой: ALTER ROLE ... NOLOGIN или смена пароля в первую очередь, pg_hba — во вторую.
Памятка: Разбор из практики: хостел «Гавань», 14 рабочих мест, запрет, который ничего не запретил — схема
Памятка: Разбор из практики: хостел «Гавань», 14 рабочих мест, запрет, который ничего не запретил. Открыть схему в полном размере

Шесть причин, по которым правило «не сработало», кроме порядка

Порядок строк — самая частая, но далеко не единственная причина. Разберу остальные, с которыми сталкиваюсь регулярно, в порядке убывания частоты.

Пулер посередине. Если между клиентами и базой стоит PgBouncer или Odyssey, сервер видит адрес пулера, а не адрес человека. Все правила про 192.168.10.77 в pg_hba бесполезны по определению: с точки зрения PostgreSQL к нему подключается 127.0.0.1 или адрес хоста пулера. Запрещать нужно там же, где пулер принимает соединения, — в pgbouncer.ini и его собственном auth-файле, либо на уровне фаервола. Диагностируется мгновенно: SELECT DISTINCT client_addr FROM pg_stat_activity показывает один-два адреса вместо десятков.

IPv4 против IPv6 и local против host. Документация не оставляет свободы толкования: «An entry given in IPv4 format will match only IPv4 connections, and an entry given in IPv6 format will match only IPv6 connections, even if the represented address is in the IPv4-in-IPv6 range». Запретили 127.0.0.1/32 — а клиент пришёл на ::1/128 и попал в следующее правило. Отдельная классика: человек ходит через SSH-туннель, и для сервера он вообще не 192.168.10.77, а локальный loopback. Запрет по его «настоящему» адресу в такой схеме не значит ничего.

Тип подключения уже, чем кажется. hostnossl не совпадёт с TLS-соединением, hostssl — с открытым, replication в колонке базы — это отдельная сущность: значение all матчит все базы, но не матчит запрос физической репликации. Если вы закрываете доступ и не закрыли отдельно строку с replication, реплика или pg_basebackup спокойно пройдут мимо вашего запрета.

include_dir и порядок файлов. Начиная с 16-й версии в pg_hba.conf работают директивы include, include_if_exists и include_dir. Содержимое подключается ровно на месте директивы, а файлы внутри каталога обрабатываются «in file name order (according to C locale rules, i.e., numbers before letters, and uppercase letters before lowercase ones)». Отсюда два подвоха разом: если строка include_dir стоит в конце основного файла, то всё, что вы аккуратно разложили по conf.d, окажется ниже общих разрешений; а внутри каталога 10-app.conf будет прочитан раньше 9-deny.conf, потому что сравниваются строки, а не числа, и запрет из «девятки» окажется ниже разрешений. Префиксы делайте двузначными и с нуля.

Не тот кластер и не тот файл. Два инстанса на 5432 и 5433, тестовый и боевой каталоги данных, конфиг из системы конфигурации, который на следующем прогоне возвращает файл к шаблону. Последнее особенно обидно: правило живёт до ближайшего запуска Ansible или оператора Kubernetes. В сообществе Percona ровно на этом ломались люди, у которых оператор дописывал пользовательские правила в конец файла и не давал поставить их выше собственных строк по умолчанию — при первом совпадении такие reject не достигаются никогда.

Прежде чем искать экзотику, выполните `SELECT client_addr, usename, datname, backend_start FROM pg_stat_activity ORDER BY backend_start;`. В половине случаев там видно, что запрещаемый адрес вообще не тот, который приходит на сервер.

Как я строю pg_hba.conf, чтобы порядок не приходилось помнить

Держать порядок правил в голове — плохая стратегия: файл живёт годами, правят его разные люди, и рано или поздно кто-то допишет строку в конец. Поэтому я задаю структуру, в которой место новой строки определяется не аккуратностью автора, а именем файла. Схема простая: пять блоков сверху вниз, каждый в своём файле, подключение через include_dir в самом начале основного pg_hba.conf.

# /etc/postgresql/18/main/pg_hba.conf
# ЕДИНСТВЕННОЕ содержимое основного файла:
include_dir 'hba.d'

# hba.d/00-local.conf      — доступ администратора с самого сервера
# hba.d/10-deny.conf       — адресные запреты, всегда выигрывают
# hba.d/30-replication.conf— реплики и pg_basebackup
# hba.d/50-app.conf        — сервер 1С, пулер, сервисные роли
# hba.d/70-people.conf     — живые пользователи и их подсети
# hba.d/99-default.conf    — финальный host all all all reject

Содержимое блоков выглядит так. В 00-local.conf оставляю себе local all postgres peer — это страховка от самоблокировки, её нельзя убирать даже «на время». В 10-deny.conf лежат все reject: уволенные, скомпрометированные машины, гостевые сегменты. В 50-app.conf адреса сервера 1С и пулера с узкими масками /32 и конкретными именами баз и ролей, без all. В 70-people.conf — подсети сотрудников. В 99-default.conf ровно одна строка отказа.

# hba.d/10-deny.conf
host    all             all             192.168.10.77/32        reject
host    all             all             192.168.90.0/24         reject

# hba.d/50-app.conf
host    all             usr1cv8         127.0.0.1/32            scram-sha-256
host    all             usr1cv8         ::1/128                 scram-sha-256
hostssl all             +ro_analytics   192.168.10.0/24         scram-sha-256
hostssl "/^unf_(dev|test)$" all       192.168.20.0/24         scram-sha-256

# hba.d/99-default.conf
host    all             all             all                     reject

Две возможности, которыми стоит пользоваться и о которых почти не знают. Первая: группы через плюс. Запись +ro_analytics матчит любую роль, которая прямо или косвенно входит в эту группу, — вы управляете доступом через GRANT, а pg_hba больше не трогаете. Вторая: регулярные выражения в колонках базы и пользователя, доступные с 16-й версии — «Regular expression patterns are prefixed with a slash». Одна строка вида "/^unf_(dev|test)$" заменяет десяток. Кавычки вокруг регулярного выражения в документации используются в примерах и нужны, когда в шаблоне есть запятая, пробел или решётка. А вот группу через плюс в кавычки не берите: закавыченное значение теряет специальный смысл, и "+ro_analytics" будет искать роль с плюсом в имени.

Скажу честно про спорный момент. Финальную строку host all all all reject часть коллег считает лишней: если правило не совпало, доступ и так закрыт. Формально верно. Я всё равно её ставлю, потому что явный отказ пишется в лог иначе, чем неявный, и при разборе инцидента вы за секунду отличаете «правило отработало» от «правило не нашлось». Это стоит одной строки.

Прежде чем делать reload, проверьте новую раскладку запросом к pg_hba_file_rules: представление читает файлы с диска и покажет и итоговый порядок правил, и ошибки разбора — до того, как правила вступят в силу.
Порядок действий: Как я строю pg_hba.conf, чтобы порядок не приходилось помнить — схема
Порядок действий: Как я строю pg_hba.conf, чтобы порядок не приходилось помнить. Открыть схему в полном размере

Живые соединения: почему правило есть, а человек работает

pg_hba проверяется один раз — в момент установления соединения. Всё, что уже подключено, живёт по правилам, действовавшим на момент коннекта, и переживёт любое количество reload. Клиенты вроде DBeaver, pgAdmin и обвязки на JDBC держат соединение открытым сутками, а пул сервера 1С — вообще постоянно. Поэтому «правило не сработало» очень часто означает «правило работает, но у человека сессия с прошлой недели».

Порядок действий важен и обратный ему не работает. Сначала правим файл и делаем reload, только потом рвём сессии. Если сделать наоборот, клиент переподключится по старым правилам за долю секунды и вы получите ту же сессию с новым PID.

-- кто именно висит с проблемного адреса
SELECT pid, usename, datname, client_addr, backend_start, state
  FROM pg_stat_activity
 WHERE client_addr = '192.168.10.77'
 ORDER BY backend_start;

-- рвём (после reload, не до него)
SELECT pg_terminate_backend(pid)
  FROM pg_stat_activity
 WHERE client_addr = '192.168.10.77'
   AND pid <> pg_backend_pid();

Если задача не «закрыть один адрес», а «отключить человека совсем», работайте с ролью, а не с адресом. ALTER ROLE ivanov NOLOGIN; запрещает новые входы независимо от того, откуда человек придёт, ALTER ROLE ivanov CONNECTION LIMIT 0; даёт похожий эффект, а смена пароля обесценивает всё, что сохранено в клиентах. Ни одна из этих команд, подчеркну, не рвёт уже открытые сессии — их всё равно придётся прибить руками.

Не перезапускайте кластер ради применения pg_hba.conf. Рестарт на боевой базе — это простой на минуты и холодный кэш на часы, а reload плюс точечный terminate дают тот же результат за секунды.

scram-sha-256 против md5, тексты ошибок и особенности 1С

Вторая половина строки pg_hba — метод аутентификации, и здесь тоже много путаницы. С PostgreSQL 14 параметр password_encryption по умолчанию равен scram-sha-256 (раньше был md5), то есть все пароли, заданные через CREATE ROLE или ALTER ROLE на свежем кластере, хранятся как SCRAM-хеш. Метод md5 в pg_hba при этом не ломает вход: документация прямо говорит, что если в строке указан md5, а пароль роли хранится в SCRAM, сервер автоматически выберет SCRAM. Обратное не работает: строка scram-sha-256 не пустит роль, у которой пароль до сих пор лежит MD5-хешем после pg_upgrade со старой версии.

Поддержка MD5-паролей объявлена устаревшей и будет удалена в одной из будущих версий; в 18-й ветке появился параметр md5_password_warnings (по умолчанию on), который выдаёт WARNING при установке MD5-пароля. Переход по документации выглядит так: убедиться, что клиентские библиотеки поддерживают SCRAM, выставить password_encryption = 'scram-sha-256', заново задать пароли всем ролям и только потом поменять метод в pg_hba.conf.

-- у кого пароль всё ещё в MD5 (нужен суперпользователь)
SELECT rolname, left(rolpassword, 14) AS hash_prefix
  FROM pg_authid
 WHERE rolpassword LIKE 'md5%';

SHOW password_encryption;
-- после смены пароля хеш начнётся с SCRAM-SHA-256$
ALTER ROLE usr1cv8 PASSWORD '...';

Тексты ошибок сразу подсказывают, где искать. FATAL: no pg_hba.conf entry for host "…", user "…", database "…" означает, что не совпала ни одна строка — подключение упало мимо всех правил. pg_hba.conf rejects connection for host … — совпала строка с reject, запрет сработал. password authentication failed for user — строка найдена, метод выбран, не подошёл пароль (или у роли MD5-хеш при методе scram-sha-256). Именно по этой разнице я отличаю «правило отработало» от «правило не нашлось». Помните, что клиенту сервер сообщает меньше, чем пишет в собственный лог, так что разбор всегда начинается с журнала сервера.

Теперь про 1С. Сервер 1С ходит в PostgreSQL под одной ролью, и именно он, а не пользователи, фигурирует в pg_hba. Если сервер 1С и СУБД на одной машине, как в хостеле из разбора, ему нужны строки на 127.0.0.1/32 и ::1/128 — платформа может подключаться по любому из адресов. Колонку базы для роли 1С я держу как all или регулярное выражение по префиксу: базы создаются из консоли кластера 1С, и строка с конкретным именем сломает создание новой информационной базы. Пользователи 1С в pg_hba не видны вообще, поэтому уволенному сотруднику закрывают доступ в самой 1С, а pg_hba защищает только от прямых подключений в обход платформы — через DBeaver, psql или Excel по ODBC.

Не меняйте метод на scram-sha-256 для роли сервера 1С вслепую в рабочее время: если у роли остался MD5-хеш, все рабочие процессы 1С получат «password authentication failed», и ресепшен встанет. Сначала пароль заново, проверка хеша в pg_authid, тестовое подключение — потом правка pg_hba и reload.
Сравнение: scram-sha-256 против md5, тексты ошибок и особенности 1С — схема
Сравнение: scram-sha-256 против md5, тексты ошибок и особенности 1С. Открыть схему в полном размере

Чек-лист и приоритеты: что делать сразу, а на что можно забить

Если у вас сейчас открытый вопрос с доступом, я бы делал в таком порядке. Первое — убрать из файла строки с адресом all и методом trust, если они есть; это единственная по-настоящему срочная позиция. Второе — проверить listen_addresses и фаервол: pg_hba не заменяет ни того, ни другого, и правильная схема — сначала не пустить пакет до порта 5432, а уже потом разбираться с правилами внутри СУБД. Третье — привести файл к структуре «запреты сверху, разрешения снизу, финальный reject». Четвёртое — обновиться до текущего минорного релиза: на сентябрь 2026 года в 18-й ветке это 18.6, и сообщество прямо рекомендует всегда работать на актуальном миноре.

На что можно спокойно забить, чтобы не тратить время. Имена хостов в колонке адреса вместо IP — красиво в теории, на практике каждое подключение стоит двух резолверных запросов, прямого и обратного, и любая заминка DNS превращается в задержку логина. Держите IP и подсети. Экзотика вроде sameuser и samerole нужна на shared-хостингах и почти никогда — во внутреннем контуре небольшой компании вроде хостела на полтора десятка мест. Ручное перечисление пользователей в pg_hba тоже не нужно, если умеете пользоваться группами через плюс.

И про преувеличенные риски. Правка pg_hba.conf на боевой базе — операция обратимая и недорогая: битый файл не роняет сервер, reload не рвёт сессии, а откат — это возврат прежнего файла и повторный reload. Единственная реальная опасность — закрыть доступ самому себе, и она снимается одной строкой local для postgres и открытой заранее второй сессией psql. Я делаю такие правки на работающих кластерах в рабочее время много лет и ни разу не получил простоя из-за самой правки.

Финальная сводка, которую можно повесить рядом с файлом: правило выбирается первое совпавшее; провал аутентификации не даёт второго шанса; изменения на Linux применяются только после SIGHUP; на Windows — сразу для новых подключений; ошибки разбора видны через error в pg_hba_file_rules; открытые сессии живут по старым правилам.

Соберите привычку: любая правка pg_hba.conf заканчивается тремя командами — pg_reload_conf(), проверка pg_hba_file_rules на error, проверка лога на строку о принятии файла. Без этих трёх шагов вы не знаете, действует ваше правило или лежит мёртвым текстом.

Частые вопросы

Почему строка reject, дописанная в конец pg_hba.conf, не блокирует подключение?

Потому что PostgreSQL берёт первую строку, совпавшую по типу подключения, адресу клиента, базе и пользователю, и дальше не смотрит. Если выше уже стоит разрешающее правило на подсеть или на all, до вашего reject очередь не доходит. Точность правила и длина маски не имеют значения — значение имеет только позиция строки в файле. Перенесите reject выше разрешения и сделайте reload.

Нужно ли перезапускать PostgreSQL после правки pg_hba.conf?

Нет. На Unix достаточно перечитать конфигурацию: pg_ctl reload, SELECT pg_reload_conf() или kill -HUP по PID постмастера. На Microsoft Windows сигнал не нужен вообще — изменения применяются сразу к последующим новым подключениям. Рестарт кластера ради pg_hba — лишний простой и холодный кэш.

Разорвёт ли reload уже открытые соединения?

Нет, и это главная причина, почему кажется, что правило не работает. pg_hba проверяется только в момент установления соединения; всё, что подключено, живёт по прежним правилам сколько угодно долго. Сначала правьте файл и делайте reload, затем находите сессии в pg_stat_activity по client_addr и рвите их через pg_terminate_backend.

Как проверить, какой файл читает сервер и нет ли в нём ошибок?

Выполните SHOW hba_file — сервер сам назовёт путь, это надёжнее поиска по файловой системе, особенно при нескольких кластерах на машине. Затем посмотрите SELECT rule_number, line_number, address, auth_method, error FROM pg_hba_file_rules. Строки с непустым error не разобрались и в аутентификации не участвуют, а rule_number показывает реальный порядок просмотра.

Я запретил конкретный IP, но человек всё равно подключается. Что ещё проверить?

Проверьте, какой адрес видит сам сервер: SELECT DISTINCT client_addr FROM pg_stat_activity. Если между клиентами и базой стоит PgBouncer или Odyssey, сервер видит адрес пулера и ваши правила по адресу человека бессмысленны. То же самое даёт SSH-туннель — клиент приходит с loopback. И помните про IPv4 против IPv6: запись 127.0.0.1/32 не совпадёт с подключением на ::1.

Действует ли reject на суперпользователя postgres?

Да, полностью. reject отклоняет подключение безусловно, никаких исключений для суперпользователя нет. Именно поэтому первой строкой в файле я всегда держу local-доступ для postgres по методу peer: это страховка от ситуации, когда широкий reject наверху закрывает доступ вам самим, а других открытых сессий не осталось.

Как работает include_dir и почему мои файлы из conf.d не влияют на порядок?

include_dir подставляет содержимое каталога ровно на месте самой директивы. Если она стоит в конце основного pg_hba.conf, все ваши правила окажутся ниже общих разрешений. Внутри каталога подключаются только файлы, не начинающиеся с точки и оканчивающиеся на .conf, а их порядок определяется именем в локали C: цифры перед буквами, заглавные перед строчными. Используйте двузначные префиксы 00, 10, 50, 99.

Чем отличаются ошибки «no pg_hba.conf entry for host» и «pg_hba.conf rejects connection»?

Первая значит, что подключение не совпало ни с одной строкой файла, вторая — что совпала строка с методом reject. Если вы ждали запрета, а видите «no entry», значит, ваш reject не совпал по типу, адресу, базе или пользователю — например, клиент пришёл по IPv6 или через hostssl-правило. Если видите «password authentication failed», строка найдена и не подошёл пароль.

Нужно ли менять md5 на scram-sha-256 в pg_hba.conf для базы 1С?

Желательно, но в правильном порядке. С PostgreSQL 14 новые пароли и так хранятся в SCRAM, а метод md5 в таком случае сам использует SCRAM. Проблема возникает, когда после обновления у роли остался MD5-хеш, а метод уже scram-sha-256: вход ломается. Задайте пароль роли 1С заново, проверьте хеш в pg_authid, убедитесь в подключении на тестовой базе и только потом меняйте метод и делайте reload.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи