เปิดให้เชื่อมต่อ PostgreSQL จากภายนอกด้วย pg_hba.conf
ค่าเริ่มต้นของ PostgreSQL รับการเชื่อมต่อจากภายในเครื่องเท่านั้น เมื่อแอปพลิเคชันอยู่คนละเซิร์ฟเวอร์กับฐานข้อมูล หรือต้องให้ระบบรายงานจากสำนักงานดึงข้อมูล ต้องปรับค่าสองส่วน คือ listen_addresses ใน postgresql.conf เพื่อให้ PostgreSQL ฟังบน Network Interface ภายนอก และ pg_hba.conf เพื่อกำหนดว่าใครเชื่อมต่อจาก IP ใด เข้าฐานข้อมูลใด และยืนยันตัวตนด้วยวิธีใด
บทความนี้แสดงวิธีเปิดการเชื่อมต่อแบบจำกัดเฉพาะ IP ที่ไว้ใจได้ ใช้รหัสผ่านแบบ scram-sha-256 และบังคับเข้ารหัส SSL พร้อมตั้ง Firewall ให้สอดคล้องกัน
สิ่งที่ต้องเตรียม
- PostgreSQL 14 ขึ้นไปที่ติดตั้งแล้ว ตาม ติดตั้ง PostgreSQL และสร้างผู้ใช้บน Ubuntu หรือบน AlmaLinux/Rocky Linux
- สิทธิ์
sudoบนเซิร์ฟเวอร์ฐานข้อมูล - IP สาธารณะแบบคงที่ของเครื่องที่จะเชื่อมต่อเข้ามา ตัวอย่างในบทความใช้
198.51.100.25และเซิร์ฟเวอร์ฐานข้อมูลคือ203.0.113.10 - Role และฐานข้อมูลที่จะใช้ ตัวอย่างคือ
appuserและappdb
หมายเหตุ: ถ้าผู้ที่ต้องเข้าถึงคือผู้ดูแลระบบที่ต้องการเปิดดูข้อมูลเป็นครั้งคราว ไม่ใช่แอปพลิเคชัน ไม่จำเป็นต้องเปิดพอร์ต 5432 สู่ภายนอกเลย ใช้ SSH Tunnel ด้วย DBeaver แทนจะปลอดภัยกว่า
ขั้นตอนที่ 1: หาตำแหน่งไฟล์ตั้งค่า
ตำแหน่งไฟล์ต่างกันตามระบบปฏิบัติการ วิธีที่แน่นอนที่สุดคือถามจาก PostgreSQL เอง
sudo -u postgres psql -c "SHOW config_file;" -c "SHOW hba_file;"
| ระบบ | ตำแหน่งโดยทั่วไป |
|---|---|
| Ubuntu (แพ็กเกจของ Ubuntu หรือ PGDG) | /etc/postgresql/16/main/postgresql.conf และ pg_hba.conf ในโฟลเดอร์เดียวกัน |
| AlmaLinux/Rocky (แพ็กเกจของ OS) | /var/lib/pgsql/data/ |
| AlmaLinux/Rocky (แพ็กเกจ PGDG) | /var/lib/pgsql/16/data/ |
สำรองไฟล์ทั้งสองก่อนแก้ไข (แทนพาธด้วยค่าที่ได้จากคำสั่งข้างบน)
sudo cp /etc/postgresql/16/main/postgresql.conf /etc/postgresql/16/main/postgresql.conf.bak
sudo cp /etc/postgresql/16/main/pg_hba.conf /etc/postgresql/16/main/pg_hba.conf.bak
ขั้นตอนที่ 2: ตั้ง listen_addresses
เปิด postgresql.conf แล้วหาบรรทัด listen_addresses (ค่าเริ่มต้นถูก Comment ไว้และมีค่าเป็น localhost) แก้เป็น
listen_addresses = 'localhost,203.0.113.10'
การระบุ IP ของเซิร์ฟเวอร์เองจะฟังเฉพาะ Interface นั้น ถ้าเซิร์ฟเวอร์มีหลาย IP หรือ IP อาจเปลี่ยน ใช้ '*' เพื่อฟังทุก Interface ได้ แล้วให้ pg_hba.conf และ Firewall เป็นตัวจำกัดสิทธิ์ ค่านี้ต้อง รีสตาร์ต จึงมีผล การ Reload อย่างเดียวไม่พอ
sudo systemctl restart postgresql
บน AlmaLinux/Rocky ชื่อ Service อาจเป็น postgresql หรือ postgresql-16 ตามแหล่งที่ติดตั้ง ตรวจว่าฟังพอร์ตถูกต้องแล้ว
sudo ss -ltnp | grep 5432
ควรเห็นบรรทัดที่มี 203.0.113.10:5432 หรือ 0.0.0.0:5432 (ดูเพิ่มเติมที่ ตรวจสอบพอร์ตที่เปิดอยู่บน Linux ด้วย ss และ lsof)
ขั้นตอนที่ 3: เพิ่มกฎใน pg_hba.conf
แต่ละบรรทัดใน pg_hba.conf มี 5 คอลัมน์หลัก
| คอลัมน์ | ตัวอย่าง | ความหมาย |
|---|---|---|
| TYPE | hostssl | local คือ Socket, host คือ TCP ทั้งแบบเข้ารหัสและไม่เข้ารหัส, hostssl คือ TCP ที่เข้ารหัส SSL เท่านั้น |
| DATABASE | appdb | ชื่อฐานข้อมูล ใช้ all ได้แต่ไม่แนะนำ |
| USER | appuser | ชื่อ Role |
| ADDRESS | 198.51.100.25/32 | IP หรือช่วง IP ในรูปแบบ CIDR, /32 คือ IP เดียว |
| METHOD | scram-sha-256 | วิธียืนยันตัวตน ไม่ควรใช้ trust หรือ password กับการเชื่อมต่อจากภายนอก |
เพิ่มบรรทัดนี้ไว้ท้ายไฟล์
# แอปพลิเคชันจากเซิร์ฟเวอร์ 198.51.100.25
hostssl appdb appuser 198.51.100.25/32 scram-sha-256
PostgreSQL อ่านกฎจากบนลงล่างและใช้ บรรทัดแรกที่ตรงเงื่อนไข ทันที ถ้ามีกฎที่กว้างกว่าอยู่ด้านบน เช่น บรรทัดที่ปฏิเสธ (reject) ช่วง IP เดียวกัน กฎของคุณจะไม่ถูกใช้
ต่อมา Reload ค่า ซึ่งไม่ตัดการเชื่อมต่อที่มีอยู่
sudo systemctl reload postgresql
# หรือจากใน psql
sudo -u postgres psql -c "SELECT pg_reload_conf();"
ตรวจว่า PostgreSQL อ่านไฟล์ได้โดยไม่มีบรรทัดผิดรูปแบบ คอลัมน์ error ต้องว่างทุกแถว
sudo -u postgres psql -c "SELECT line_number, type, database, user_name, address, auth_method, error FROM pg_hba_file_rules;"
ขั้นตอนที่ 4: ตรวจสอบ SSL และรูปแบบรหัสผ่าน
กฎแบบ hostssl ต้องเปิด SSL ที่เซิร์ฟเวอร์ แพ็กเกจบน Ubuntu เปิดไว้ให้แล้วโดยใช้ Certificate แบบ Self-signed ส่วน AlmaLinux/Rocky ต้องเปิดเอง ตรวจสอบด้วย
sudo -u postgres psql -c "SHOW ssl;"
ถ้าได้ off ให้วางไฟล์ Certificate และ Private Key ในโฟลเดอร์ Data (ชื่อค่าเริ่มต้นคือ server.crt และ server.key ไฟล์ Key ต้องเป็นของผู้ใช้ postgres และสิทธิ์ 0600) แล้วตั้ง ssl = on ใน postgresql.conf และรีสตาร์ต
ต่อมาตรวจว่ารหัสผ่านของ Role ถูกเก็บแบบ SCRAM (ค่าเริ่มต้นตั้งแต่ PostgreSQL 14) ถ้าผลลัพธ์ขึ้นต้นด้วย md5 ให้ตั้งรหัสผ่านใหม่หนึ่งครั้งด้วย \password appuser ใน psql
sudo -u postgres psql -c "SELECT rolname, left(rolpassword, 14) FROM pg_authid WHERE rolname = 'appuser';"
ขั้นตอนที่ 5: เปิด Firewall เฉพาะ IP ที่อนุญาต
บน Ubuntu ที่ใช้ UFW (ดู ตั้งค่า Firewall ด้วย UFW บน Ubuntu)
sudo ufw allow from 198.51.100.25 to any port 5432 proto tcp
sudo ufw status numbered
บน AlmaLinux/Rocky ที่ใช้ firewalld (ดู ตั้งค่า Firewall ด้วย firewalld บน AlmaLinux และ Rocky Linux)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.25/32" port port="5432" protocol="tcp" accept'
sudo firewall-cmd --reload
หากเซิร์ฟเวอร์มี Security Group หรือ Firewall ภายนอกจากฝั่งผู้ให้บริการ ให้เปิดพอร์ตนั้นเพิ่มด้วย โดยจำกัดต้นทางเป็น IP เดียวกัน ไม่ควรเปิดพอร์ต 5432 ให้ทุก IP (0.0.0.0/0) เพราะจะถูกสแกนและเดารหัสผ่านตลอดเวลา
ตรวจสอบผลลัพธ์
จากเครื่อง 198.51.100.25 ที่ติดตั้ง psql ไว้ ให้เชื่อมต่อโดยบังคับ SSL
psql "host=203.0.113.10 port=5432 dbname=appdb user=appuser sslmode=require"
เมื่อเข้าได้ ใช้ \conninfo จะเห็นข้อความระบุว่าเป็นการเชื่อมต่อ SSL พร้อมชื่อ Protocol เช่น TLSv1.3 ถ้าใช้ Certificate จาก CA จริงและต้องการตรวจชื่อเซิร์ฟเวอร์ด้วย ให้ใช้ sslmode=verify-full
ฝั่งเซิร์ฟเวอร์ ดูการเชื่อมต่อที่เข้ามาได้ด้วย
sudo -u postgres psql -c "SELECT a.usename, a.client_addr, s.ssl FROM pg_stat_activity a JOIN pg_stat_ssl s USING (pid) WHERE a.client_addr IS NOT NULL;"
ปัญหาที่พบบ่อย
FATAL: no pg_hba.conf entry for host "198.51.100.25", user "appuser", database "appdb", no encryption
PostgreSQL ได้รับการเชื่อมต่อแล้ว แต่ไม่มีกฎที่ตรง ข้อความ no encryption บอกว่า Client ไม่ได้ใช้ SSL ขณะที่กฎเป็น hostssl ให้เพิ่ม sslmode=require ฝั่ง Client หรือตรวจว่า IP ต้นทางที่แสดงใน Error ตรงกับที่ใส่ในกฎ (กรณีอยู่หลัง NAT IP อาจไม่ใช่ที่คาดไว้) และอย่าลืม Reload หลังแก้ไฟล์
Connection refused หรือ Connection timed out
Connection refused มักแปลว่า PostgreSQL ไม่ได้ฟังบน IP นั้น ให้ตรวจ listen_addresses และรีสตาร์ต ส่วน timed out มักเป็น Firewall บนเครื่องหรือ Firewall ภายนอกของผู้ให้บริการที่ยังไม่เปิด
FATAL: password authentication failed for user "appuser"
ตรวจว่ารหัสผ่านถูกต้อง และรหัสที่เก็บไว้เป็นแบบ SCRAM ตามขั้นตอนที่ 4 ถ้า Client เป็นไลบรารีรุ่นเก่ามากที่ไม่รองรับ SCRAM ให้อัปเดตไลบรารีแทนการลดระดับเป็น md5 รายละเอียดวิธียืนยันตัวตนทั้งหมดดูได้จากคู่มือทางการ The pg_hba.conf File
หากทำตามแล้วยังเชื่อมต่อไม่ได้ หรือต้องการตรวจสอบ Firewall ภายนอกของเซิร์ฟเวอร์ ติดต่อทีมงาน THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/
- Categories:
- Cloud
- Tags:
- Cloud
- Cloud Server
Related Posts
หมวดหมู่ที่น่าสนใจ
- Account Settings
- AD Server
- AI
- Alibaba Cloud
- Anti-Spam Gateway
- AWS Amazon Web Services
- Campaign
- CentOS/AlmaLinux
- Cloud
- Cloud Backup
- Cloud Communication
- Cloud Migration
- Cloud Security
- Cloud Server Management
- Cloud Solution
- Cloud Solution for Government
- Cloud Solutions by Industry
- Cloud Storage
- Cloud VPS App Plus +
- Cloud VPS DirectAdmin
- Cloud VPS Plesk
- CSR
- Cyber Security
- Cybersecurity
- Data Sovereignty
- Database Server
- DDoS
- Digital Tranformation
- Digital Transformation
- Direct Mail
- Directadmin
- Domainname
- Ecommerce
- ERP
- Generative AI
- Getting Started
- Google Cloud
- Google G Suite
- Huawei Cloud
- IT News
- Linux Server
- Managed Cloud Services
- Managed Service Provider
- Manual
- Microsoft
- Microsoft 365
- Microsoft Azure
- News
- On-premise
- Private Mail Server
- Promotion
- Recommend Solution (Enterprise)
- Server
- Sovereign Cloud
- THAI DATA CLOUD Platform
- Ubuntu
- Ubuntu
- Uncategorized
- VMware
- VPS Server
- Web Design
- Web Hosting
- Web Hosting (DirectAdmin)
- Web Hosting (Plesk)
- Web Technologies
- Windows Server
- Wordpress
- Zimbra
- เรื่องราวความประทับใจ
- โซลูชันสำหรับธุรกิจการผลิตและยานยนต์
- โซลูชันสำหรับธุรกิจการศึกษา
- โซลูชันสำหรับธุรกิจการเงิน
- โซลูชันสำหรับธุรกิจขนส่งและกระจายสินค้า
- โซลูชันสำหรับธุรกิจค้าปลีก
- โซลูชันสำหรับธุรกิจท่องเที่ยว
- โซลูชันสำหรับธุรกิจบริการสุขภาพและโรงพยาบาล
- โซลูชันสำหรับธุรกิจประกันภัย
- โซลูชันสำหรับธุรกิจพลังงานและสาธารณูปโภค
- โซลูชันสำหรับธุรกิจสื่อสารมวลชนและเอ็นเตอร์เทนเมนท์
- โซลูชันสำหรับธุรกิจอสังหาริมทรัพย์
- โซลูชันสำหรับธุรกิจเทคโนโลยี


