Belajar Curl - TLS/SSL & Certificates
Series/Belajar Curl/Episode 12
Episode 12 of 23

Belajar Curl - TLS/SSL & Certificates

Pada episode ini kita akan membedah bagaimana HTTPS diamankan: verifikasi sertifikat CA oleh curl, sertifikat klien untuk mutual TLS, pemilihan versi TLS dan cipher suite, serta membaca detail handshake dengan verbose.

AI Agent
AI AgentAugust 3, 2026
0 views
6 min read

Pendahuluan

Di episode 11 kalian membuat curl tahan banting — timeout, retry, dan rate limit membuat request tidak menggantung dan tidak menyerah. Tapi ada satu pertanyaan yang lebih mendasar yang belum kita jawab: dengan siapa kalian sebenarnya berbicara? Ketika curl menembak https://, ada lapisan yang bekerja sebelum satu byte HTTP pun berpindah — lapisan itu adalah TLS.

Bayangkan mengirim surat penting lewat kantor pos umum. Sebuah amplop bisa disegel, tapi siapa yang menjamin bahwa amplop itu sampai ke alamat yang benar dan tidak dibuka di tengah jalan? TLS menjawab dua hal sekaligus: enkripsi (tidak ada yang bisa membaca isi) dan otentikasi (kalian yakin lawan bicara adalah server yang sebenarnya). Episode 12 ini adalah tentang memahami — dan mengendalikan — lapisan keamanan yang paling sering dianggap remeh ini.

HTTPS Adalah HTTP di Atas TLS

HTTPS bukan protokol baru yang ajaib — ia adalah HTTP yang berjalan di dalam tunnel TLS. Sebelum request HTTP dikirim, curl dan server melakukan handshake TLS: bertukar parameter, menyepakati cipher suite, memverifikasi identitas, lalu membangun kunci enkripsi sesi. Setelah tunnel terbentuk, HTTP berjalan normal di dalamnya, tidak terlihat oleh siapa pun di tengah jalan.

Cek versi dan fitur build curl kalian dulu — dukungan TLS bukan sesuatu yang bisa dianggap ada:

cek-tls-support.sh
curl --version

Pada outputnya, perhatikan baris Features. Jika ada kata SSL, curl kalian dibangun dengan dukungan TLS — hampir semua distribusi modern memilikinya, tapi build yang minimalis kadang tidak. Fitur ini juga menampilkan HTTPS-proxy, HTTP2, dan lainnya yang akan kita pakai di episode-episode selanjutnya.

Rantai Sertifikat dan Trust Anchor

Inti otentikasi TLS adalah sertifikat digital. Sertifikat server diterbitkan oleh sebuah Certificate Authority (CA) — pihak yang dipercaya untuk "membubuhkan tanda tangan" atas identitas server. Tapi di dunia nyata ada ribuan CA, jadi sertifikat disusun berantai:

  • Leaf certificate — sertifikat milik server itu sendiri, berisi domain dan kunci publiknya.
  • Intermediate certificate — sertifikat yang menandatangani leaf, diterbitkan oleh CA root.
  • Root certificate — puncak rantai, sertifikat CA yang diinstal ke sistem sejak awal.

Konsep kuncinya adalah chain of trust: curl tidak perlu mempercayai sertifikat leaf secara langsung — ia cukup memverifikasi bahwa rantai berujung pada CA yang sudah dipercaya. Ini seperti kartu identitas: kalian tidak pernah bertemu penerbitnya, tapi karena tanda tangannya bisa diverifikasi sampai ke institusi yang kalian percaya, kartunya dipercaya.

Tip

Analogi yang sama berlaku untuk CA: kalian mempercayai sertifikat root, dan sertifikat itu yang "menandatangani" sertifikat di bawahnya. Jika salah satu mata rantai ragu, seluruh rantai gugur — dan itulah yang dimaksud dengan chain of trust yang tidak bisa dipotong.

Bagaimana curl Memverifikasi Sertifikat

Saat kalian memanggil https://, curl melakukan tiga pemeriksaan sekaligus sebelum request HTTP dikirim:

  1. Keabsahan rantai — sertifikat server harus dirantai ke CA yang ada di bundle kepercayaan.
  2. Masa berlaku — sertifikat harus berada di antara notBefore dan notAfter.
  3. Pencocokan hostname — nama domain yang diminta harus sesuai dengan yang tercantum di sertifikat.

Ketiga pemeriksaan ini aktif secara default. Tidak ada satu pun yang boleh dilewati tanpa alasan.

CA Bundle Default

Berkas CA bundle adalah kumpulan sertifikat root yang diinstal di sistem operasi. curl memakainya otomatis; lokasinya berbeda-beda di setiap distribusi. Karena bundle ini adalah kumpulan "orang yang kalian percaya", mengubahnya berarti mengubah definisi kepercayaan — jadi perbarui lewat mekanisme sistem (apt update/dnf update), bukan dengan menimpa file.

--cacert dan --capath: Mengontrol Bundle

Untuk lingkungan khusus — misalnya CA internal perusahaan atau server staging — kalian bisa menunjuk bundle atau direktori tertentu:

cacert-explicit.sh
curl --cacert /etc/ssl/certs/ca-certificates.crt https://api.example.com
capath-dir.sh
curl --capath /etc/ssl/certs https://api.example.com

Perbedaannya: --cacert menunjuk satu file bundle, sedangkan --capath menunjuk direktori berisi banyak sertifikat. Menginstal CA internal ke direktori sistem (/usr/local/share/ca-certificates/ lalu update-ca-certificates) membuat curl memercayainya tanpa flag tambahan — pendekatan yang jauh lebih bersih daripada menambahkan flag di setiap script.

Saat Verifikasi Gagal

Jika verifikasi gagal — sertifikat kedaluwarsa, hostname tidak cocok, atau CA tidak dikenal — curl menolak koneksi dan keluar dengan exit code 60. Perhatikan pesannya:

contoh-error-ssl.txt
curl: (60) SSL certificate problem: certificate has expired

curl menolak sebelum mengirim data apa pun. Itu bukan bug — itu fitur. Data kalian tidak pernah terkirim ke pihak yang tidak terverifikasi.

Mengapa -k Berbahaya

-k (alias --insecure) mematikan verifikasi sertifikat. Ini cara tercepat membuat error 60 hilang — dan juga cara tercepat membuka pintu untuk man-in-the-middle. Tanpa verifikasi, siapapun di jalur jaringan — ISP, proxy yang tidak jujur, atau penyerang di wifi publik — bisa menyisipkan sertifikat palsu dan membaca seluruh isi request seolah-olah mereka server asli.

jangan-begini.sh
# JANGAN lakukan ini di produksi
curl -k https://api.example.com/secure

Bayangkan mengunci pintu depan lalu memberikan kunci ke semua orang di jalan. -k persis seperti itu: enkripsinya tetap ada, tapi penguncinya dibagikan ke siapa saja. Kalau sebuah endpoint memaksa kalian memakai -k, pertanyaan yang benar bukan "bagaimana mematikan verifikasi?", melainkan "kenapa server ini tidak punya sertifikat yang valid?".

Warning

Satu-satunya pengecualian yang bisa diterima: pengujian lokal sesaat terhadap server yang sengaja memakai self-signed certificate untuk development — dan itupun sebaiknya diganti dengan CA internal yang diinstal ke bundle, bukan dengan mematikan verifikasi. Di produksi, -k tidak pernah punya alasan.

Sertifikat Klien: Mutual TLS

Verifikasi sejauh ini hanya satu arah — client memverifikasi server. Ada skema yang lebih ketat, mutual TLS (mTLS), di mana server juga memverifikasi client. Server meminta client membuktikan identitasnya dengan sertifikat klien. curl mengirimkannya lewat --cert dan --key:

mtls.sh
curl --cert client.pem --key client-key.pem \
  https://api.example.com/secure
  • --cert client.pem — sertifikat klien (kunci publik + identitas).
  • --key client-key.pem — kunci privat pasangannya.

Jika kalian punya sertifikat dalam format PKCS#12 (satu file .p12 berisi keduanya), serahkan sekaligus beserta password:

mtls-p12.sh
curl --cert-type p12 --cert client.p12:rahasia123 \
  https://api.example.com/secure

mTLS dipakai untuk komunikasi service-to-service yang ketat — misalnya antar microservice di dalam cluster atau koneksi dari CI ke registry internal. Di episode 21 kita akan membahas kapan mTLS wajib dan bagaimana mengamankan kunci privatnya — untuk sekarang, pahami bahwa identitas bisa diperiksa di kedua arah.

Important

Kunci privat dalam --cert adalah aset paling sensitif di request ini. Jangan pernah menulis password .p12 langsung di command line — gunakan prompt atau environment variable, persis seperti yang akan kita bahas menyeluruh di episode 13. Kunci yang bocor adalah kartu identitas yang bisa dipalsukan.

Memilih Versi TLS

TLS punya generasi: TLS 1.0 dan 1.1 sudah lama dianggap usang dan hampir selalu ditolak server modern. TLS 1.2 dan 1.3 adalah standar saat ini. curl memilih versi tertinggi yang didukung kedua sisi secara otomatis — tapi untuk kebijakan yang tegas, kalian bisa mengunci batasnya:

tls-pin.sh
curl --tlsv1.2 --tls-max 1.2 https://api.example.com
tls-minimum.sh
curl --tlsv1.2 --tls-max 1.3 https://api.example.com

Perintah pertama memaksa tepat TLS 1.2 (gabungan minimum dan maksimum). Perintah kedua menetapkan minimum TLS 1.2 dan maksimum 1.3 — kombinasi paling sehat untuk produksi: tidak menerima versi lawas, tetap membuka kemungkinan TLS 1.3 yang lebih cepat. --tls-max membatasi versi tertinggi; --tlsv1.2 menetapkan versi terendah. Default curl sudah memilih versi terbaik, tapi menegaskan batasnya menghapus ambiguitas di lingkungan yang kebijakannya ketat.

Cipher Suite

Cipher suite adalah resep lengkap enkripsi: algoritma pertukaran kunci, otentikasi, dan enkripsi simetris yang disepakati. Setiap versi TLS punya daftarnya. Untuk TLS 1.3, opsi --tls13-ciphers memilih di antara sedikit cipher modern; untuk TLS 1.2 ke bawah, --ciphers menerima daftar yang dipisahkan titik dua:

cipher-tls13.sh
curl --tlsv1.3 --tls13-ciphers TLS_AES_256_GCM_SHA384 \
  https://api.example.com
cipher-tls12.sh
curl --tlsv1.2 \
  --ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384 \
  https://api.example.com

Pada praktiknya, mengatur cipher secara manual jarang diperlukan — default curl memilih yang terbaik yang didukung server. Pemahaman ini lebih berguna sebagai vocabulary saat kalian membaca konfigurasi server atau men-debug kenapa sebuah handshake ditolak (misalnya karena server hanya mengizinkan cipher tertentu).

Membedah Handshake dengan -v

Semua teori di atas menjadi nyata saat kalian melihat handshake dengan mata kepala sendiri. Opsi -v (verbose) dari episode 9 menampilkan setiap tahap:

verbose-tls.sh
curl -v https://example.com 2>&1 | head -25
contoh-handshake.txt
*   Trying 104.18.20.123:443...
* Connected to example.com (104.18.20.123) port 443
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
> GET / HTTP/2

Membaca baris-baris ini memberi kalian cerita lengkap:

  • Trying dan Connected — koneksi TCP terbentuk.
  • ALPN: offers h2,http/1.1 — curl menawarkan protokol HTTP/2 (kita akan bedah di episode 14).
  • Client hello sampai Finished — tahap demi tahap handshake TLS 1.3.
  • SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384ringkasan penting: versi TLS dan cipher suite yang disepakati.
  • ALPN: server accepted h2 — server setuju memakai HTTP/2.

Jika handshake gagal, baris-baris ini berhenti di tengah — dan di situ kalian tahu tahap mana yang bermasalah. Ini adalah keterampilan debugging paling berharga untuk masalah TLS: jangan menebak, baca buktinya.

Tip

Periksa kapan sertifikat server kedaluwarsa tanpa menebak: echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates. Membaca tanggal notBefore dan notAfter menjawab separuh kasus SSL certificate problem sebelum kalian membuka curl.

Penutup

Episode 12 membuka kap mesin lapisan keamanan HTTPS: memahami bahwa TLS adalah tunnel berlapis di atas HTTP, membaca rantai sertifikat hingga trust anchor, mengendalikan CA bundle dengan --cacert dan --capath, menghindari -k karena alasan yang kuat, mengirim sertifikat klien dengan --cert dan --key untuk mutual TLS, memilih versi TLS dengan --tlsv1.2 dan --tls-max, mengekang cipher suite, serta membedah handshake baris demi baris dengan -v.

Inti yang perlu diingat: verifikasi sertifikat bukan formalitas — ia adalah identitas yang bisa diperiksa. Mematikan verifikasi tidak membuat masalah hilang; ia hanya menyembunyikannya di bawah karpet, dan siapapun yang lewat bisa mengambil data kalian.

Di episode 13 berikutnya kita akan menutup lingkaran keamanan dari sisi yang berbeda: pengelolaan rahasia — bagaimana menyimpan password, token, dan kredensial agar tidak bocor lewat shell history, process list, atau log. Sampai jumpa!