Chapter pg_hba.conf ditutup dengan satu pengamatan: di server latihan kita tidak ada satu pun baris hostssl, karena memang parameter ssl masih off — seluruh latihan sejauh ini berjalan di jalur tak terenkripsi. Tanpa TLS, sandi SCRAM memang tetap tidak bocor (protokolnya memang dirancang untuk itu), tetapi seluruh hasil query — data pelanggan, harga, alamat — mengalir sebagai teks yang bisa disadap di jaringan. Bagi aplikasi yang berjalan lintas mesin, enkripsi jalur bukan pelengkap: pg_hba.conf bisa memaksa koneksi TLS lewat baris hostssl, dan klien mengatur tingkat ketatnya lewat satu parameter — sslmode. Chapter ini membedah keduanya dari dua arah: server yang menyalakan TLS, dan klien yang memverifikasi bahwa jalurnya benar-benar terenkripsi serta servernya memang yang diklaim.

Kondisi TLS di Server Latihan #

Delapan parameter mengatur TLS di sisi server. Query berikut membaca semuanya dari pg_settings — hasilnya adalah kondisi nyata server kita, dan kolom context akan menentukan cara menerapkan perubahannya:

sql status-ssl.sql
-- Parameter TLS di server latihan: ssl masih off, sementara seluruh
-- parameter pendukungnya sudah tersedia dengan nilai bawaan.
-- Kolom context bernilai sighup: cukup reload untuk menerapkan.
SELECT name, setting, context
FROM pg_settings
WHERE name IN ('ssl', 'ssl_min_protocol_version', 'ssl_max_protocol_version',
               'ssl_cert_file', 'ssl_key_file', 'ssl_ca_file',
               'ssl_ciphers', 'ssl_prefer_server_ciphers')
ORDER BY name;

Output yang Dihasilkan:

text
           name            |         setting          | context 
---------------------------+--------------------------+---------
 ssl                       | off                      | sighup
 ssl_ca_file               |                          | sighup
 ssl_cert_file             | server.crt               | sighup
 ssl_ciphers               | HIGH:MEDIUM:+3DES:!aNULL | sighup
 ssl_key_file              | server.key               | sighup
 ssl_max_protocol_version  |                          | sighup
 ssl_min_protocol_version  | TLSv1.2                  | sighup
 ssl_prefer_server_ciphers | on                       | sighup
(8 rows)

Baris-baris hasil itu bisa dibaca sebagai daftar periksaperalatan TLS kita:

  1. ssl = off — saklar utama; TLS belum menyala di server latihan.
  2. ssl_cert_file = server.crt dan ssl_key_file = server.key — nama file sertifikat dan kunci privat. Nama relatif ini dicari di direktori data (PGDATA); path absolut juga sah bila diperlukan.
  3. ssl_min_protocol_version = TLSv1.2 — protokol di bawah TLS 1.2 ditolak; nilai ssl_max_protocol_version yang kosong berarti mengikuti versi tertinggi yang didukung pustaka.
  4. ssl_ciphers = HIGH:MEDIUM:+3DES:!aNULL — daftar cipher yang ditawarkan, dengan ssl_prefer_server_ciphers = on berarti urutan pilihan dipegang server, bukan klien.
  5. ssl_ca_file yang kosong — belum ada Certificate Authority (CA) yang dipasang; file inilah yang nantinya dipakai untuk memverifikasi sertifikat klien.
  6. context = sighup pada seluruh baris — menerapkan perubahan delapan parameter ini cukup dengan reload (misalnya SELECT pg_reload_conf(); sebagaimana dilatih di chapter pg_hba.conf), tanpa memulai ulang server.

Menyalakan TLS #

Prosedur menyalakan TLS membutuhkan sepasang kunci privat dan sertifikat. Untuk latihan, openssl bisa membuatnya dalam satu perintah; untuk produksi, sertifikat sebaiknya diterbitkan CA internal perusahaan atau CA publik yang sudah dikenali klien:

bash
# kunci privat tanpa passphrase + sertifikat self-signed, 30 hari
openssl req -new -x509 -days 30 -nodes \
    -subj "/CN=db.example.com" \
    -keyout server.key -out server.crt

# kunci privat hanya boleh dibaca pemiliknya -- server menolak
# menjalankan TLS dengan kunci yang terlalu terbuka
chmod 600 server.key

Selanjutnya pasang kedua file itu di direktori data, lalu nyalakan saklarnya di postgresql.conf:

text
ssl = on
# ssl_cert_file = 'server.crt'
# ssl_key_file  = 'server.key'
# ssl_min_protocol_version = 'TLSv1.2'

Begitu ssl = on dimuat ulang, server menawarkan TLS pada koneksi TCP; klien lama yang memakai sslmode=disable atau allow tetap terhubung tanpa TLS, sehingga penyalakan ini tidak memutus aplikasi yang sedang berjalan. Memaksa enkripsi penuh baru terjadi lewat pg_hba.conf — mengganti baris host yang sensitif menjadi hostssl — atau dari sisi klien lewat sslmode=require. Satu pengecualian perlu diingat: unix socket tidak melalui jaringan, jadi TLS tidak berlaku untuk baris local — inilah alasan server latihan kita aman menjalankan trust di socket sembari ssl = off.

Parameter sslmode dari Sisi Klien #

Klien libpq — psql dan hampir semua driver aplikasi — memilih perilaku TLS lewat parameter koneksi sslmode. Enam nilainya membentuk tangga jaminan yang menaik:

sslmodeTerenkripsi?Memverifikasi sertifikat server?Perilaku khas
disabletidaktidakTLS tidak dicoba sama sekali
allowbila terpaksatidakCoba polos dulu; TLS hanya bila polos gagal
preferbila tersediatidakCoba TLS dulu; jatuh ke polos bila server tak mendukung
requireyatidakPolos ditolak; identitas server tidak diperiksa
verify-cayaya, terhadap CASertifikat harus diterbitkan CA yang dikenal
verify-fullyaya, CA + hostnameDitambah: nama host harus cocok dengan sertifikat

Bawaan libpq adalah prefer — pilihan yang nyaman untuk internet yang bercampur, tetapi berbahaya sebagai kebijakan: koneksi yang diam-diam jatuh ke jalur polos tetap dianggap sukses. Untuk server produksi yang sudah jelas mendukung TLS, naikkan minimal ke require, dan untuk aplikasi lintas jaringan publik gunakan verify-full — pengecualian hostname pada verify-ca masih membuka celah server-bukan-server yang sertifikatnya sah.

Pemakaian sslmode dalam connection string cukup satu pasangan kunci-nilai, dan sertifikat CA untuk verifikasi diarahkan lewat parameter pendamping:

text
postgresql://[email protected]:5432/penjualan?sslmode=verify-full&sslrootcert=/etc/app/ca.crt

Memeriksa Enkripsi Koneksi Berjalan #

Setelah tersambung, klaim “koneksi ini terenkripsi” bisa diverifikasi — bukan dianggap. View pg_stat_ssl menyimpan status TLS setiap koneksi backend: kolom ssl menandakan terenkripsi atau tidak, version mencatat protokol, cipher dan bits menjelaskan algoritma serta panjang kuncinya, dan tiga kolom terakhir (client_dn, client_serial, issuer_dn) terisi hanya bila klien mengirim sertifikat. File berikut memeriksa koneksi kita sendiri dengan memfilter pid milik sesi ini:

sql cek-koneksi.sql
-- Status TLS koneksi kita sendiri, dibaca dari view pg_stat_ssl:
-- ssl bernilai f karena server belum menyalakan TLS, sehingga kolom
-- versi protokol, nama cipher, dan panjang kunci tidak terisi.
SELECT ssl, version, cipher, bits
FROM pg_stat_ssl
WHERE pid = pg_backend_pid();

Output yang Dihasilkan:

text
 ssl | version | cipher | bits 
-----+---------+--------+------
 f   |         |        |     
(1 row)

Hasilnya jujur: ssl bernilai f dengan kolom protokol, cipher, dan panjang kunci kosong — koneksi ini benar-benar tidak terenkripsi, sebagaimana dugaan kita dari ssl = off. Di server yang sudah menyala TLS-nya, baris yang sama akan memperlihatkan misalnya version = TLSv1.3, nama cipher seperti TLS_AES_256_GCM_SHA384, dan bits = 256. Di sisi klien, psql menyediakan perintah meta \connectioninfo yang meringkas jalur koneksi aktif — termasuk status enkripsinya — dalam satu baris. View ini juga alat audit yang praktis: query SELECT ssl, count(*) FROM pg_stat_ssl GROUP BY ssl memetakan berapa koneksi produksi yang masih polos; jalankan setelah menyalakan hostssl untuk mengukur sisa klien yang belum ikut.

Sertifikat Server dan Verifikasi Identitas #

TLS memakai sertifikat untuk memecahkan masalah yang sandi tidak sentuh: memastikan server di ujung koneksi adalah pemilik sah dari alamat yang dituju. Sertifikat server memuat nama host di field Subject Alternative Name (SAN) dan ditandatangani oleh CA. Klien dengan sslmode=verify-ca memeriksa tanda tangan itu terhadap salinan sslrootcert; klien dengan verify-full menambahkan satu pemeriksaan — nama host yang dikoneksikan harus sama dengan nama pada sertifikat. Karena itu sertifikat dengan CN=db.example.com sah untuk koneksi ke db.example.com, tetapi gagal verify-full bila klien mengalamatkan server dengan nama lain atau alamat IP.

Protokol lama juga ikut tersaring: ssl_min_protocol_version = TLSv1.2 menolak SSLv3 dan TLS 1.0/1.1 yang telah dinyatakan usang, dan daftar ssl_ciphers menyaring algoritma enkripsi yang lemah. Kombinasi kebijakan server ini plus verify-full di klien menghasilkan jalur yang terenkripsi dan terautentikasi dua arah penuh.

Sertifikat Klien dan Metode cert #

TLS bisa bekerja dua arah: server memverifikasi klien dengan sertifikat, bukan sandi. Metode cert dari chapter Authentication memanfaatkan persis mekanisme ini — pg_hba.conf menuliskannya pada baris hostssl karena sertifikat klien hanya terkirim selama handshake TLS:

text
# TYPE      DATABASE    USER      ADDRESS         METHOD
hostssl     penjualan   app_web   10.0.0.0/24     cert map=webmap

Server memeriksa tanda tangan sertifikat klien terhadap ssl_ca_file, lalu mencocokkan nama CN pada sertifikat dengan nama role PostgreSQL — pemetaan yang bisa diubah lewat map bila penamaan sertifikat dan role tidak identik. Opsi clientcert=verify-full juga bisa dipasang pada metode lain (misalnya scram-sha-256 clientcert=verify-full): klien tetap mengirim sandi, dan sertifikat menjadi faktor kedua — pola two-factor yang disarankan untuk server yang menghadap jaringan publik. Sertifikat klien tidak bisa digandakan semudah sandi dan pencabutannya cukup dengan mengeluarkan dari daftar CA.

Jalur kini tertutup rapi: pg_hba.conf menyeleksi siapa yang boleh masuk, scram-sha-256 membuktikan identitas tanpa mengirim sandi, dan TLS mengenkripsi sekaligus memverifikasi kedua arah. Tetapi semua lapisan itu menjaga jalur — bukan isi query-nya. Aplikasi yang merangkai SQL dengan menempelkan input pengguna begitu saja akan membocorkan dan merusak data lewat jalur yang sudah terenkripsi sekalipun. Serangan itu bernama SQL injection, dan tiga chapter terakhir section ini membongkarnya: anatomi serangannya, pertahanan utamanya, lalu prinsip hak akses minimum yang membatasi ledakannya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

cek-koneksi.sql

Unduh berkas
sql
-- Status TLS koneksi kita sendiri, dibaca dari view pg_stat_ssl:
-- ssl bernilai f karena server belum menyalakan TLS, sehingga kolom
-- versi protokol, nama cipher, dan panjang kunci tidak terisi.
SELECT ssl, version, cipher, bits
FROM pg_stat_ssl
WHERE pid = pg_backend_pid();

status-ssl.sql

Unduh berkas
sql
-- Parameter TLS di server latihan: ssl masih off, sementara seluruh
-- parameter pendukungnya sudah tersedia dengan nilai bawaan.
-- Kolom context bernilai sighup: cukup reload untuk menerapkan.
SELECT name, setting, context
FROM pg_settings
WHERE name IN ('ssl', 'ssl_min_protocol_version', 'ssl_max_protocol_version',
               'ssl_cert_file', 'ssl_key_file', 'ssl_ca_file',
               'ssl_ciphers', 'ssl_prefer_server_ciphers')
ORDER BY name;