PostgreSQL kļūdai "no pg_hba.conf entry for host" ir arī mierinoša puse: tīkls ir kārtībā. Klients sasniedza serveri, serveris nolasīja pieprasījumu, izgāja cauri saviem host-based autentifikācijas noteikumiem un neatrada nevienu atbilstošu. Nekas nav salūzis. Vienkārši nav noteikuma tieši šai adreses, lietotāja, datubāzes un savienojuma veida kombinācijai. Jāatrod, kura no četrām vērtībām nesakrīt, un lielāko daļu atbildes jau satur pats kļūdas ziņojums.
Aktuālajās PostgreSQL versijās ziņojums izskatās šādi:
FATAL: no pg_hba.conf entry for host "10.20.0.15", user "app", database "appdb", no encryption
PostgreSQL dokumentācija par autentifikācijas problēmām raksturo to kā visticamāko kļūdu gadījumā, ja serveri sasniedzat, bet tas nevēlas ar jums runāt. Salīdziniet to ar "Connection refused" vai taimautu. Tie nozīmē, ka līdz šim brīdim nemaz netikāt: serveris neklausās uz šīs adreses vai ceļā ir ugunsmūris.
Nolasiet ziņojumu pa laukiem
Teksts tiek veidots failā auth.c, un katra tā daļa ir noderīga:
- host: klienta IP adrese tā, kā to redz serveris. Tas ir biežākais pārsteigums. Aiz NAT, slodzes balansētāja, savienojumu pūlera vai konteineru tīkla tā bieži nav tā adrese, ko gaidāt.
- user: datubāzes loma, ko pieprasīja klients, nevis operētājsistēmas lietotājs.
- database: pieprasītā datubāze. Ja klients to nenorādīja, libpq pēc noklusējuma izmanto lietotāja vārdu. Tā arī rodas pieprasījums datubāzei "app", lai gan bija domāta "appdb".
- šifrēšanas stāvoklis:
no encryption,SSL encryptionvaiGSS encryption. PostgreSQL 13 un vecākās versijās šeit bijaSSL off/SSL on.
Fiziskās replikācijas savienojumam teksts mainās uz "no pg_hba.conf entry for replication connection from host ...", un datubāzes lauka tajā nav. Tas jau pats par sevi ir mājiens: replikācijai vajag atsevišķu noteikumu, kā redzēsim tālāk.
Skatiet arī servera žurnālu, ne tikai klienta izvadi. Dokumentācija norāda, ka žurnālā bieži ir vairāk informācijas nekā klientam nosūtītajā ziņojumā. Ja pg_hba.conf izmantojat hostu vārdus, žurnālā būs arī redzams, vai klienta IP tika atrisināts uz vārdu un vai sakrita tiešā (forward) pārbaude.
Kā PostgreSQL izvēlas noteikumu
pg_hba.conf dokumentācijā noteikumi ir īsi. Ieraksti tiek pārbaudīti no augšas uz leju, un tiek izmantots pirmais ieraksts, kuram sakrīt savienojuma veids, klienta adrese, datubāze un lietotājs. Pāriešanas uz nākamo nav: ja šī ieraksta autentifikācija neizdodas, nākamie ieraksti netiek pārbaudīti. Ja nesakrīt neviens, piekļuve tiek liegta ar iepriekš minēto kļūdu.
Tātad "no entry" nozīmē, ka neviena rinda nesakrita pēc visiem četriem laukiem vienlaikus. Biežākie iemesli, aptuveni tādā secībā, kādā ar tiem saskaramies:
- Adrese nav tā, ko domājat. Noteikums atļauj
10.20.0.0/24, bet lietotne pēc migrācijas darbojas citā apakštīklā. Vai arī tā pieslēdzas caur PgBouncer vai starpniekserveri, un serveris redz starpnieka adresi. Uzticieties IP adresei kļūdas ziņojumā, nevis tīkla shēmai. - IPv4 pret IPv6. Dokumentācija to saka skaidri: IPv4 formātā rakstīts ieraksts atbilst tikai IPv4 savienojumiem, bet IPv6 ieraksts tikai IPv6. Ja
localhosttiek atrisināts uz::1, noteikums127.0.0.1/32šim klientam neko nedod. - Nepareizs savienojuma veids.
localrindas attiecas tikai uz Unix domēna soketiem,hostuz TCP/IP ar šifrēšanu vai bez tās,hostssltikai uz TCP/IP ar SSL, bethostnossltikai uz TCP/IP bez tā. Noteikumu kopa, kas sastāv tikai nohostsslrindām, noraidīs klientu bez TLS, un ziņojums beigsies ar "no encryption". Ja serverīsslnav ieslēgts, dokumentācija norāda, kahostsslieraksti tiek ignorēti, tikai žurnālā parādās brīdinājums. - Replikācija neietilpst "all". Atslēgvārds
alldatubāzes kolonnā neattiecas uz fizisko replikāciju. Vajag rindu arreplicationdatubāzes kolonnā. Dokumentācijā ir vēl viena nianse:replicationatbilst fiziskās replikācijas savienojumiem, bet ne loģiskās. Loģiskās replikācijas savienojumi norāda datubāzi un tiek salīdzināti kā parasti savienojumi. - Dalība grupās. Vienkāršs lomas vārds atbilst tikai šai lomai. Lai atbilstu grupas lomas dalībniekiem, pievienojiet priekšā
+. Superlietotāji netiek uzskatīti par lomas dalībniekiem tikai tāpēc, ka ir superlietotāji. - Rediģētais fails nav tas, kas tiek lietots. Ceļu nosaka
hba_file. Dažās no pakotnēm instalētās sistēmās tas atrodas ārpus datu direktorijas. Pirms ko labojat, pārbaudiet arSHOW hba_file;. - Labojāt, bet nepārlādējāt. Fails tiek nolasīts startējot un saņemot SIGHUP. Saglabāšana neko nemaina, kamēr konfigurācija netiek pārlādēta. Izņēmums ir Windows: tur izmaiņas uzreiz attiecas uz jauniem savienojumiem.
Apskatiet noteikumus tā, kā tos redz serveris
Sāciet ar rindu servera žurnālā un salīdziniet to ar nolasītajiem noteikumiem. Skats pg_hba_file_rules rāda vienu rindu katrai rindai, kas nav komentārs, tādā secībā, kādā tās tiek vērtētas:
SELECT rule_number, file_name, line_number, type,
database, user_name, address, netmask, auth_method, error
FROM pg_hba_file_rules
ORDER BY rule_number NULLS LAST, line_number;
Kolonnas rule_number un file_name ir pieejamas no PostgreSQL 16, kurā pg_hba.conf parādījās arī include direktīvas. Versijās 15 un vecākās izņemiet šīs divas kolonnas no vaicājuma. Pēc noklusējuma skatu var lasīt tikai superlietotāji.
Viena detaļa padara skatu ļoti ērtu, bet to ir arī viegli pārprast: tas rāda faila pašreizējo saturu, nevis to, ko serveris ielādēja pēdējo reizi. Tas ir lieliski, lai pārbaudītu izmaiņas pirms pārlādēšanas. Rinda, kurā error nav NULL, nozīmē, ka to nevar parsēt:
SELECT file_name, line_number, error
FROM pg_hba_file_rules
WHERE error IS NOT NULL;
Pēc tam ejiet cauri sarakstam no augšas ar četrām vērtībām no kļūdas ziņojuma un apstājieties pie pirmās rindas, kas atbilst tām visām. Ja nonākat līdz beigām, tā arī ir atbilde. Ja agrāk sakrīt rinda ar reject, klients saņem citu ziņojumu, "pg_hba.conf rejects connection for host ...", kas nozīmē, ka to bloķēja tiešs noteikums.
Labojiet ar šauru noteikumu
Pievienojiet pēc iespējas konkrētāku rindu, kas aptver reālo klientu, un novietojiet to virs plašākiem noteikumiem, kas varētu sakrist agrāk:
# TYPE DATABASE USER ADDRESS METHOD
# lietotņu serveri, obligāts TLS
hostssl appdb app 10.20.0.0/24 scram-sha-256
# replikas straumēšana (fiziskā replikācija)
hostssl replication replicator 10.20.1.12/32 scram-sha-256
Pēc tam pārlādējiet konfigurāciju. Restartēt nevajag. Noteikumi tiek pārbaudīti, kad savienojums tiek atvērts, tāpēc esošās sesijas turpina darboties:
SELECT pg_reload_conf();
-- pēc tam pārliecinieties, ka fails ir nolasīts bez kļūdām
SELECT count(*) FROM pg_hba_file_rules WHERE error IS NOT NULL;
pg_ctl reload vai kill -HUP postmaster procesam dara to pašu. Ja failā ir sintakses kļūda, pārlādēšana nevienu neizslēgs. Kods failā hba.c parsē jauno failu pagaidu sarakstā un saglabā vecos noteikumus, ja kaut kas neizdodas. Žurnālā parādās "... pg_hba.conf was not reloaded". Tas ir droši, bet nozīmē arī to, ka jūsu labojums klusi nav stājies spēkā, tāpēc pēc katras pārlādēšanas pārbaudiet žurnālu vai skatu.
host all all 0.0.0.0/0 trust. Dokumentācija tieši saka, ko nozīmē trust: ikviens, kas var pieslēgties, var ielogoties kā jebkurš lietotājs, arī superlietotājs, bez paroles. Izmantojiet precīzu adrešu diapazonu un scram-sha-256, arī kā pagaidu risinājumu. Kā šo failu pēc tam uzturēt stingru, aprakstījām mūsu PostgreSQL drošības nostiprināšanas kontrolsarakstā.Vēl viena pārbaude pirms aiziešanas: attālie klienti var pieslēgties tikai tad, ja listen_addresses ietver interfeisu, līdz kuram tie var tikt. Savienojumu iestatījumu dokumentācijā noklusējuma vērtība ir localhost, un tās maiņai vajag restartu, nevis pārlādēšanu. Ja serveris tur neklausās, klients šīs kļūdas vietā saņem "Connection refused".
Kad kļūda mainās uz "password authentication failed"
Bieži nākamais mēģinājums pēc labojuma beidzas ar FATAL: password authentication failed for user "app". Tas ir progress: noteikums sakrita, un tagad neizdodas šī noteikuma metode. Klients apzināti redz tikai šo vispārīgo tekstu. Īstais iemesls ir servera žurnālā, kas norāda arī, kura pg_hba.conf rinda sakrita (PostgreSQL 16 un jaunākās versijas pievieno arī faila nosaukumu). crypt.c un SCRAM kods žurnālā raksta, piemēram:
Role "app" does not exist.Lomas vārds ir nepareizs. Klients tik un tā saņem "password authentication failed", lai no kļūdas neviens neuzzinātu, kādas lomas eksistē.User "app" has no password assigned.Dokumentācija apstiprina, ka lomai bez paroles paroles autentifikācija vienmēr neizdodas.User "app" has an expired password.Pārbaudietrolvaliduntil.User "app" does not have a valid SCRAM secret.Noteikumā irscram-sha-256, bet parole glabājas kā MD5 hash.
Pēdējais gadījums bieži parādās pēc drošības nostiprināšanas. Saskaņā ar paroles autentifikācijas dokumentāciju SCRAM formātā glabāta parole darbojas ar scram-sha-256, md5 (PostgreSQL klusi pārslēdzas uz SCRAM) un password. MD5 formātā glabāta parole darbojas tikai ar md5 un password. Tātad, ja rindu nomaināt no md5 uz scram-sha-256, pirms vecās paroles ir iestatītas no jauna, šie lietotāji paliek ārpusē. Dokumentētā secība ir šāda: pārliecinieties, ka visas klientu bibliotēkas atbalsta SCRAM, iestatiet password_encryption = 'scram-sha-256' (aktuālajās versijās tas jau ir noklusējums), lieciet lietotājiem iestatīt jaunas paroles un tikai tad mainiet metodi pg_hba.conf.
-- kāds hash tips ir lomai? (tikai superlietotājam)
SELECT rolname, left(rolpassword, 14) AS hash_prefix, rolvaliduntil
FROM pg_authid
WHERE rolname = 'app';
-- iestatiet paroli no jauna, lai tā tiktu glabāta kā SCRAM
SET password_encryption = 'scram-sha-256';
\password app
Hash, kas sākas ar SCRAM-SHA-256$, ir SCRAM, bet tas, kas sākas ar md5, ir vecais formāts.
Divas īpatnības, kas rada mulsinošas kļūdas
Tā pati kļūda divreiz. libpq noklusējuma sslmode ir prefer. libpq dokumentācija to apraksta kā "vispirms mēģināt SSL savienojumu; ja tas neizdodas, mēģināt bez SSL". Tāpēc klients var parādīt divas FATAL rindas, vienu ar "SSL encryption" beigās un otru ar "no encryption". Tas nozīmē, ka neviens no mēģinājumiem neatbilda noteikumam. Produkcijas klientiem iestatiet sslmode=require vai stingrāku režīmu, lai vienmēr zinātu, kāda veida savienojumu atkļūdojat.
Peer autentifikācijas kļūdas. local rinda ar peer salīdzina operētājsistēmas lietotāja vārdu ar pieprasīto lomu. Palaižot psql -U postgres kā root caur soketu, tiek sakrists ar šo rindu un saņemta kļūda "Peer authentication failed for user "postgres"". Tā ir cita kļūda nekā "no entry", un risinājums ir palaist komandu kā pareizajam OS lietotājam (vai izmantot lietotāju vārdu karti), nevis pārrakstīt noteikumu.
Lai nākamreiz būtu ātrāk
- Glabājiet failu versiju kontrolē un izvietojiet to ar konfigurācijas pārvaldības rīkiem, pie katras rindas ar komentāru, kam tā domāta.
- Pārbaudiet
pg_hba_file_ruleskļūdas CI vai pirms katras pārlādēšanas. Tā drukas kļūdas tiek noķertas, pirms tās nonāk serverī. - Iestatiet brīdinājumus par autentifikācijas kļūdu uzliesmojumiem. Žurnalēšanas dokumentācija norāda, ka neveiksmīga autentifikācija vienmēr tiek žurnalēta neatkarīgi no
log_connectionsvērtības, tāpēc dati jau ir jūsu žurnālos. - Iekļaujiet pg_hba.conf izmaiņas tīkla pārbūves plānā. Jauni apakštīkli, jauns pūleris vai failover uz citu reģionu gandrīz vienmēr prasa jaunas rindas. Pievienojiet tās pirms pārbūves, nevis incidenta laikā.
Galvenās atziņas
- "no pg_hba.conf entry for host" nozīmē, ka klients sasniedza PostgreSQL, bet neviens noteikums neatbilda tā adresei, lietotājam, datubāzei un savienojuma veidam.
- Noteikumi tiek pārbaudīti no augšas uz leju, uzvar pirmais atbilstošais, un pāriešanas uz nākamo nav.
- Uzticieties IP adresei ziņojumā. Starpniekserveri, NAT, IPv6 un konteineri to maina.
allneietver fizisko replikāciju, unhostsslneatbilst klientiem bez TLS.- Pārbaudiet ar
pg_hba_file_rules, pārlādējiet arpg_reload_conf()un meklējiet žurnālā "was not reloaded". - Nekad nelabojiet to ar
trust. Kad kļūda mainās uz "password authentication failed", īsto iemeslu meklējiet servera žurnālā.