Sebuah aplikasi dapat berjalan normal di port internal, tetapi tetap menghasilkan redirect yang salah ketika dibuka melalui domain publik. Salah satu hal yang perlu diperiksa adalah apakah aplikasi menerima konteks yang benar setelah permintaan melewati reverse proxy.
Saya melihat reverse proxy sebagai penghubung yang mempunyai tanggung jawab sendiri: menerima permintaan publik, memilih tujuan, dan meneruskan informasi yang diperlukan aplikasi. Untuk memahaminya, kita perlu mengikuti perjalanan permintaan sekaligus menetapkan bagian mana yang boleh dipercaya.
Peta singkat
Bagian | Hal yang perlu dipahami |
Posisi proxy | Client mengakses alamat publik; proxy meneruskan permintaan ke aplikasi. |
Dua koneksi | Perlindungan browser–proxy dan proxy–aplikasi perlu dinilai terpisah. |
Routing | Host dan path publik dipetakan ke tujuan internal yang ditentukan. |
Header | Konteks permintaan diteruskan dengan aturan kepercayaan yang jelas. |
Respons | Redirect, cookie, dan cache harus sesuai dengan alamat serta pengguna yang benar. |
Kegagalan | Pengujian perlu mencakup sambungan proxy ke aplikasi. |
1. Reverse proxy mewakili layanan di belakangnya
Dalam terminologi RFC 9110, gateway juga disebut reverse proxy. Dari sisi client, perantara ini bertindak sebagai server yang menerima permintaan; untuk memenuhinya, ia dapat meneruskan permintaan ke server lain.
Misalnya, aplikasi dengan alamat publik
https://app.example.com. Aplikasinya berjalan pada 127.0.0.1:3000 di mesin yang sama dengan proxy. Browser menghubungi domain publik, lalu proxy membuat permintaan ke aplikasi.Ini berbeda dengan forward proxy yang dipilih client untuk mengakses server lain. Dokumentasi mod_proxy Apache 2.4.54 menjelaskan kedua peran tersebut.
Untuk contoh tadi, tujuan internal ditetapkan oleh pengelola. Pemanggil tidak boleh bebas menentukan URL tujuan, karena itu mengubah perilaku sistem dari penerus untuk layanan tertentu menjadi proxy yang dapat disalahgunakan.
2. Terminasi TLS membagi jalur menjadi dua bagian
Ketika TLS berakhir di reverse proxy, koneksi HTTPS dari browser dilindungi sampai proxy. Selanjutnya, proxy dapat memakai HTTP atau membuat koneksi HTTPS tersendiri ke aplikasi.
Karena itu, gambarkan dua sambungan saat meninjau desain:
Browser -- HTTPS --> Reverse proxy -- HTTP/HTTPS --> AplikasiPada contoh satu mesin, sambungan aplikasi dapat dibatasi ke loopback. Jika aplikasi berada di mesin lain, penilaian harus mencakup jaringan yang dilalui dan perlindungan koneksi keduanya.
Memilih HTTPS untuk upstream juga memerlukan verifikasi identitas server. Dokumentasi mod_ssl versi 2.4.54 memisahkan pengaturan verifikasi sertifikat, CA tepercaya, dan pemeriksaan nama peer. Bahkan
SSLProxyVerify mempunyai default none; jangan menganggap penggunaan URL HTTPS saja membuktikan seluruh verifikasi yang dibutuhkan sudah aktif.Hasil konfigurasinya perlu diperiksa langsung: apakah sertifikat upstream yang tidak dipercaya atau tidak sesuai nama benar-benar ditolak?
3. Routing perlu menjaga makna URL
Proxy dapat memetakan path publik ke lokasi internal. Misalnya,
/api/files diteruskan ke service file, sedangkan / diteruskan ke aplikasi web.Perubahan prefix harus disengaja. Meneruskan
/api/files sebagai /files berbeda dengan meneruskannya tanpa perubahan. Dalam Apache, pemetaan ini antara lain diatur melalui ProxyPass.Respons pun perlu diperiksa. Jika aplikasi mengirim redirect ke alamat internal, pengguna dapat diarahkan ke tujuan yang tidak bisa diakses.
ProxyPassReverse menyesuaikan header respons tertentu; directive tersebut bukan alat untuk menulis ulang semua URL dalam HTML. Domain dan path cookie mempunyai pengaturan tersendiri.Semua perilaku itu dijelaskan dalam dokumentasi mod_proxy versi yang sama. Untuk contoh tadi, uji halaman login, redirect setelah login, dan tautan file melalui domain publik.
4. Header penerusan membawa konteks, bukan bukti
Pada sambungan yang dibuat proxy, alamat peer yang dilihat aplikasi bisa merupakan alamat proxy. Informasi tentang permintaan asal dapat diteruskan melalui header.
RFC 7239 mendefinisikan
Forwarded, dengan parameter seperti for, host, dan proto. Contoh ilustratifnya:Forwarded: for=192.0.2.60;proto=https;host=app.example.comDukungan aplikasi dan proxy perlu dicocokkan. Header standar ini tidak otomatis dibuat atau dibaca oleh setiap implementasi. Apache mod_proxy juga mendokumentasikan keluarga header
X-Forwarded-*.Konteks skema publik penting ketika aplikasi menyusun URL absolut. Jika aplikasi mengira permintaan berasal dari HTTP, sementara browser memakai HTTPS ke proxy, hasilnya dapat berupa URL yang keliru.
Namun, RFC 7239 menegaskan bahwa isi header dapat dimodifikasi, termasuk oleh client. Jangan menjadikannya dasar keputusan akses sebelum proxy tepercaya ditetapkan dan cara menangani nilai kiriman pemanggil sudah jelas.
5. Tetapkan batas kepercayaan sampai ke aplikasi
Untuk susunan dengan satu proxy publik dan tanpa proxy lain di depannya, aturannya bisa seperti berikut:
- Endpoint aplikasi menerima trafik hanya melalui jalur proxy yang ditetapkan.
- Proxy menghapus atau mengganti metadata penerusan dari client dengan nilai yang dapat ditentukannya sendiri.
- Aplikasi hanya menerima metadata tersebut dari proxy yang dipercaya.
- Host publik yang diterima dibatasi sesuai domain layanan.
- Aturan pembacaan alamat client diuji dengan header palsu.
Jika ada CDN atau load balancer tambahan, aturan itu harus disesuaikan dengan rantai proxy yang sebenarnya. Memilih alamat pertama dari sebuah daftar tanpa menilai siapa yang menambahkannya dapat menghasilkan identitas client yang keliru.
Sebagai contoh implementasi, mod_remoteip Apache 2.4.54 menyediakan daftar proxy tepercaya dan memproses rantai alamat. Dokumentasinya memperingatkan bahwa mengaktifkan
RemoteIPHeader tanpa pembatas proxy terkait akan mempercayai semua host yang memberikan nilai header itu.6. Caching perlu mengenali respons pribadi
Meneruskan permintaan dan menyimpan respons adalah kemampuan berbeda. Dokumentasi mod_proxy_http menyatakan bahwa modul tersebut tidak menyediakan caching sendiri.
Jika shared cache ditambahkan, kebijakannya harus mengikuti jenis data. RFC 9111 menjelaskan bahwa
private melarang penyimpanan oleh shared cache, sedangkan no-store melarang penyimpanan oleh cache yang mematuhi directive tersebut. no-cache mempunyai makna lain: respons perlu divalidasi sebelum digunakan kembali.Untuk contoh tadi, uji bahwa data pribadi pengguna pertama tidak muncul ketika pengguna kedua mengakses URL yang sama. Memeriksa kecepatan respons saja belum cukup.
7. Uji kegagalan dari sisi pengguna
RFC 9110 membedakan
502 Bad Gateway, ketika proxy menerima respons upstream yang tidak valid, dan 504 Gateway Timeout, ketika respons upstream tidak diterima tepat waktu. Keduanya membantu membaca gejala, tetapi tidak langsung mengungkap seluruh penyebabnya.Uji contoh tadi dengan menghentikan aplikasi, membuat responsnya terlambat, dan mengirim header penerusan palsu, lalu periksa status publik serta log di kedua sisi sambungan.
Pengujian juga mencakup jalur normal: login, redirect, pembukaan file, dan permintaan yang ditolak. Tujuannya memastikan proxy dan aplikasi mempunyai pemahaman yang sama tentang permintaan yang sedang dilayani.
Penutup
Mulailah dengan satu domain, satu proxy, dan satu aplikasi. Petakan kedua koneksi, tentukan perubahan URL, lalu tuliskan aturan kepercayaan header sebelum menambahkan kemampuan lain.
Konfigurasi penerusan yang berhasil baru permulaan. Ujiannya adalah layanan yang tetap benar ketika diakses lewat alamat publik, menerima header palsu, dan menghadapi upstream yang bermasalah.
