Catatan dari produksi
SSLSecurityCloudflare

SSL & keamanan cepat-aman di edge

Begitu domain ada di Cloudflare, tugas berikutnya adalah membuatnya cepat dan aman sejak awal. Kabar baiknya: seluruh baseline keamanan di bawah ini gratis, dan sifatnya berlapis — tiap request dari internet diperiksa di edge Cloudflare, satu lapis demi lapis, sebelum sampai ke situs Anda. Ini Bagian 4 dari seri deploy, dan fokusnya ada di lapisan keamanannya.

Bayangkan seperti tumpukan gerbang. Sebuah request turun melewati tiap gerbang — dipaksa ke HTTPS, dienkripsi, disaring dari serangan dan bot, lalu akhirnya diberi security header Anda — dan hanya request yang bersih yang sampai ke halaman.

Request dari internetAlways Use HTTPSTLS — Full (strict)WAF + Bot Fight ModeTurnstilehanya di contact formSecurity headernosniff · X-Frame-Options · HSTS · CSP
Tiap request diperiksa di edge Cloudflare — lapis demi lapis — sebelum sampai ke situs.

Di bawah gerbang terakhir ada situs & form Anda. Mari kita telusuri tumpukannya dari atas.

HTTPS & TLS — enkripsi semuanya

TLS (Transport Layer Security, nama modern dari SSL) adalah enkripsi di balik ikon gembok itu — ia mengacak lalu lintas agar tak ada pihak di antara pengunjung dan situs yang bisa membaca atau mengutak-atiknya. Tiga sakelar gratis yang menangani tugas beratnya:

  • Always Use HTTPS — kalau ada yang membuka http://pangaea.id, Cloudflare mengalihkannya ke versi https://. Pintu yang tak aman ditutup; pengunjung selalu lewat jalur terenkripsi.
  • Mode TLS → Full (strict) — ini mengatur cara Cloudflare berbicara ke server Anda (origin). "Full (strict)" mengenkripsi kedua ruas — browser↔edge dan edge↔origin — sekaligus memastikan sertifikat origin itu asli dan tepercaya. Mode yang lebih lemah ("Flexible", "Full") membiarkan ruas kedua tak terenkripsi atau tak terverifikasi; jangan dipakai.
  • Minimum TLS 1.2, lalu aktifkan TLS 1.3 — tolak versi protokol yang lama dan rapuh, dan utamakan yang terbaru sekaligus tercepat.

HSTS — "selalu akses saya lewat HTTPS saja"

HSTS (HTTP Strict Transport Security) adalah header yang memberi browser satu instruksi: selalu akses saya lewat HTTPS saja, bahkan kalau ada yang mengetik http:// atau mengklik tautan lama. Browser mengingatnya dan otomatis meng-upgrade tiap request berikutnya — tak ada lagi lompatan pertama yang tak aman untuk disadap.

Cukup satu header di blok /*:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

max-age=31536000 itu satu tahun (dalam detik); includeSubDomains memperluas aturannya ke tiap subdomain; preload mendaftarkan domain Anda ke daftar bawaan browser.

Record CAA — melindungi perpanjangan otomatis sertifikat Anda

Inilah lapisan yang paling jarang didengar orang, dan justru lapisan inilah yang diam-diam merusak ikon gembok.

Record CAA (Certification Authority Authorization) adalah record DNS kecil yang mendaftar Certificate Authority mana saja yang boleh menerbitkan sertifikat HTTPS untuk domain Anda. Certificate Authority (CA) adalah salah satu perusahaan tepercaya yang mengeluarkan sertifikat HTTPS — Let's Encrypt, Google Trust Services, DigiCert, dan sebagainya. Record CAA berfungsi seperti whitelist: kalau sebuah CA tak ada di sana, browser tak akan mengakui sertifikat yang ia terbitkan, dan CA yang taat aturan bahkan tak akan mencoba.

Kenapa ini penting

Cloudflare memperbarui otomatis sertifikat Universal SSL situs Anda kira-kira tiap 90 hari — diam-diam, di latar belakang. Inilah jebakannya: kalau sebuah record CAA ada tapi melewatkan satu CA yang dipakai Cloudflare, perpanjangan otomatis berikutnya akan gagal. Anda tak akan sadar di hari pertama. Lalu sertifikat lama kedaluwarsa, dan tiba-tiba tiap pengunjung melihat ikon gembok rusak disertai peringatan "Tidak aman" yang bikin panik. Record CAA yang Anda tambahkan demi keamanan malah jadi penyebab situs tumbang.

Langkah amannya

Berikut set CAA live untuk pangaea.id (baris letsencrypt.org milik kami; sisanya diisi otomatis oleh Cloudflare):

@   CAA   0 issue     "letsencrypt.org"
@   CAA   0 issuewild "letsencrypt.org"
@   CAA   0 issue     "pki.goog; cansignhttpexchanges=yes"
@   CAA   0 issuewild "pki.goog; cansignhttpexchanges=yes"
@   CAA   0 issue     "ssl.com"
@   CAA   0 issuewild "ssl.com"
@   CAA   0 issue     "sectigo.com"
@   CAA   0 issuewild "sectigo.com"
@   CAA   0 issue     "comodoca.com"
@   CAA   0 issuewild "comodoca.com"
@   CAA   0 issue     "digicert.com; cansignhttpexchanges=yes"
@   CAA   0 issuewild "digicert.com; cansignhttpexchanges=yes"
@   CAA   0 iodef     "mailto:sales@pangaea.id"

Cara membaca tiap kolomnya:

  • @apex domain (pangaea.id itu sendiri).
  • 0 — sebuah flag; 0 berarti "non-critical" (CA yang tak mengenali record ini tetap boleh lanjut).
  • issue — siapa yang boleh menerbitkan sertifikat biasa.
  • issuewild — siapa yang boleh menerbitkan sertifikat wildcard (*.pangaea.id). Yang ini wajib: sertifikat edge Cloudflare berbentuk wildcard, jadi set CAA tanpa issuewild akan memblok perpanjangan.
  • iodef — ke mana sebuah CA mengirim email laporan kalau ada yang meminta sertifikat yang dilarang kebijakan (mailto:sales@pangaea.id).

Verifikasi

Tanyakan langsung ke DNS, record CAA apa saja yang aktif:

dig CAA pangaea.id +short

Lalu pastikan siapa yang sebenarnya menerbitkan sertifikat live tersebut:

openssl s_client -connect www.pangaea.id:443 -servername www.pangaea.id </dev/null 2>/dev/null | openssl x509 -noout -issuer

Status di pangaea.id: terkonfigurasi dan terverifikasi. Sertifikat live diterbitkan oleh Google Trust Services, dan perpanjangannya terlindungi karena CA Cloudflare otomatis terotorisasi di set CAA di atas.

Security header — instruksi di tiap response

Header adalah instruksi singkat yang Cloudflare tempelkan ke tiap response, untuk menyuruh browser berperilaku aman. Empat header murah ini menutup celah yang umum:

  • X-Content-Type-Options: nosniff — cegah browser menebak-nebak tipe sebuah file (yang bisa mengubah gambar yang diunggah jadi script yang dieksekusi). Browser harus mempercayai tipe yang dideklarasikan saja.
  • X-Frame-Options: DENY — larang siapa pun menyematkan situs di dalam <iframe>, sehingga mematahkan "clickjacking" (frame tersembunyi yang mengelabui pengguna agar mengklik).
  • Referrer-Policy: strict-origin-when-cross-origin — saat pengunjung mengklik keluar ke situs lain, jangan bocorkan URL lengkap asalnya; cukup bagikan origin-nya saja.
  • Permissions-Policy: geolocation=(), microphone=(), camera=() — matikan fitur browser yang tak pernah dipakai situs, supaya tak ada script yang bisa meminta akses lokasi, mikrofon, atau kamera.

CSP — allowlist script

Yang terbesar adalah CSP (Content-Security-Policy): sebuah allowlist soal dari mana saja script, style, font, dan gambar boleh dimuat. Apa pun yang tak ada di daftar akan ditolak — jadi resource yang disuntikkan atau berbahaya sama sekali tak akan pernah jalan. Inilah pertahanan tunggal terkuat terhadap cross-site scripting. Berikut policy live-nya:

default-src 'self'; script-src 'self' {{INLINE_SCRIPT_HASHES}} https://static.cloudflareinsights.com https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; font-src 'self'; img-src 'self' data: https://www.googletagmanager.com https://*.google-analytics.com; connect-src 'self' https://cloudflareinsights.com https://api.web3forms.com https://www.googletagmanager.com https://*.google-analytics.com https://*.analytics.google.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'; upgrade-insecure-requests

Singkatnya, beberapa directive kuncinya:

  • default-src 'self' — secara default, hanya muat resource dari origin kami sendiri. Tiap directive lain menyempit dari titik ini.
  • font-src 'self' — font dimuat hanya dari server kami sendiri. Situs meng-host font-nya sendiri, jadi tak ada font CDN yang perlu diizinkan — allowlist-nya tetap ketat.
  • connect-src … https://api.web3forms.com … — contact form mengirim data ke Web3Forms, jadi cuma endpoint itu yang diizinkan untuk request jaringan; selebihnya diblok.
  • frame-ancestors 'none' — tak ada yang boleh mem-frame situs (pasangan modern dari X-Frame-Options).
  • object-src 'none' — sama sekali tak ada objek Flash/plugin.
  • upgrade-insecure-requests — diam-diam menulis ulang sub-resource http:// yang nyasar menjadi https://.

Bagian yang menarik adalah script-src. Tak ada 'unsafe-inline' untuk script — padahal itulah yang biasanya membiarkan sembarang inline <script> jalan. Sebagai gantinya, satu-satunya inline script di situs ini (bootstrap vite-react-ssg dan snippet gtag GA4) dipancang dengan hash SHA-256 per-build. Sebuah langkah build, apps/labs/scripts/csp-hash.mjs, men-hash persis script-script itu dan menulis hash-nya ke _headers, menggantikan placeholder {{INLINE_SCRIPT_HASHES}}. Jadi hanya script persis itu yang boleh jalan — ubah satu karakter saja, hash-nya tak lagi cocok, dan script langsung ditolak. Allowlist-nya tak akan pernah bergeser diam-diam.

Anti-bot & firewall, secara sederhana

Tiga sakelar terakhir ini menjauhkan penyalahgunaan otomatis dari situs, dan semuanya gratis:

  • Bot Fight Mode — sakelar satu klik yang menantang bot yang jelas-jelas bot (scraper, brute-forcer) sebelum mereka mencapai halaman Anda. Mode ini sudah mengecualikan search dan AI crawler yang terverifikasi, jadi Google, Bing, dan bot answer-engine tetap meng-index situs seperti biasa.
  • WAF (Web Application Firewall) — managed ruleset gratis dari Cloudflare yang memblok pola serangan yang sudah dikenal (SQL injection, percobaan exploit umum) di edge, sebelum menyentuh aplikasi Anda. Ini baseline yang tinggal Anda nyalakan.
  • Turnstile — pemeriksaan "apakah Anda manusia?" gratis dan ramah-privasi dari Cloudflare — pengganti CAPTCHA modern tanpa teka-teki. Pasang di contact form saja, jangan di seluruh situs, supaya pengunjung asli yang sedang menjelajah halaman tak pernah melihat tantangan — hanya yang mengirim form yang diverifikasi.

Do

  • Set TLS → Full (strict) dan Always Use HTTPS supaya tiap ruas terenkripsi dan pintu yang tak aman tertutup
  • Tambahkan satu CA ke CAA lalu biarkan Cloudflare mengisi sendiri miliknya — perpanjangan tetap aman
  • Batasi Turnstile hanya ke contact form, supaya aktivitas menjelajah biasa tetap bebas hambatan

Don't

  • Memakai TLS "Flexible" atau "Full" (ruas kedua berakhir tak terenkripsi atau tak terverifikasi)
  • Mendaftar tiap CA di CAA satu per satu lalu tak sengaja melewatkan satu yang dipakai Cloudflare — perpanjangan berikutnya jadi rusak
  • Membiarkan Rocket Loader on dengan CSP ketat, atau lupa mengecek console DevTools setelah deploy

Contekan

Pertanyaan umum

Siapa yang memperpanjang gembok HTTPS, dan seberapa sering?

Cloudflare melakukannya otomatis — Anda tak pernah menyentuh file sertifikat. Sertifikat berlaku sekitar jendela 90 hari, dan Cloudflare memperpanjangnya jauh sebelum kedaluwarsa. Sertifikat live kami saat ini diterbitkan oleh Google Trust Services.

Pandu saya, apa sebenarnya yang terjadi saat perpanjangan.

Langkah demi langkah: (1) sebuah sertifikat sudah melayani (Google Trust Services, kira-kira jendela 90 hari). (2) Cloudflare memulai perpanjangan jauh sebelum kedaluwarsa. (3) ia membuktikan dirinya mengendalikan domain lewat challenge DNS atau HTTP. (4) cek CAA — Certificate Authority membaca record CAA Anda: tanpa CAA berarti CA mana pun boleh menerbitkan; CAA yang mencantumkan CA ini berarti berhasil; CAA yang melewatkan CA ini berarti ditolak dan perpanjangan gagal. (5) sertifikat baru dipasang ke edge Cloudflare otomatis dan hitungannya mulai dari awal. (6) loop berulang selamanya.

Apa itu CAA, dan apa jebakannya?

CAA singkatan dari Certification Authority Authorization — record DNS yang mencantumkan Certificate Authority mana yang boleh menerbitkan sertifikat HTTPS Anda. Jebakannya: daftar CAA yang tak lengkap diam-diam merusak perpanjangan berikutnya berminggu-minggu kemudian, bukan hari ini. Semua tampak baik sampai siklus perpanjangan berikutnya tiba dan ditolak karena CA yang dipakai tak ada di daftar Anda — yang membuatnya menyebalkan untuk didiagnosis. Zona kami mengizinkan Let's Encrypt, Google, SSL.com, Sectigo, Comodo, dan DigiCert (lihat tabel di atas).

Berikutnya

Ini Bagian 4 (keamanan) dari seri deploy. Sisa jalurnya: Bagian 1 · Arahkan domain ke Cloudflare, Bagian 2 · CI/CD dengan GitHub Actions → Pages, Bagian 3 · Redirect Root → www, dan saudara caching-nya — HTTP caching di CDN Cloudflare. Cerita bahasa-sederhana kenapa kami melapisinya seperti ini ada di catatan build kami: Bikin cepat dan aman.

Sources

  1. Cloudflare — Mode enkripsi SSL/TLS: Full (strict)
  2. Cloudflare — Record CAA dan penerbitan sertifikat
  3. MDN — Content Security Policy (CSP)