HAProxy 302 ke aplikasi privat: siapa yang membuka lompatan kedua?
Pengalihan mengembalikan koneksi kedua ke browser. Kirim permintaan ke backend saja, lalu perbaiki pengalihan absolut dan cookie milik aplikasi itu sendiri.
Seseorang mengarahkan host HAProxy publik ke aplikasi internal dan bertanya mengapa browser tidak bisa mengikuti. Proxy mencapai aplikasi lewat VPN-nya, pengalihan mengembalikan header Location, dan browser lalu mencoba alamat yang hanya ada di dalam terowongan. Dari luar halaman itu hanya menggantung. Keputusannya adalah pihak mana yang membuka koneksi kedua, dan itulah yang membedakan pengalihan dari backend.
Dua jalur yang tampak serupa dalam konfigurasi
Pengalihan mengakhiri pertukaran dengan sebuah respons. Klien membaca Location dan memulai permintaan baru dari mana pun klien berada, yaitu jaringan yang tidak pernah Anda kendalikan. Proxy tidak lagi terlibat. Semua yang berikutnya bergantung pada DNS, rute, dan kepercayaan klien itu sendiri, jadi hasilnya berbeda-beda menurut tempat pengguna membuka browser:
GET /app client -> proxy
302 Location proxy -> client (http://10.40.0.20:8080/)
GET /app client -> 10.40.0.20:8080 client network, no route
Backend proxy menahan tahap kedua di sisi server. Proxy membukanya lewat jalur yang sudah dimilikinya, dan klien tetap berbicara dengan satu nama publik. Jika terowongan putus, klien menerima galat alih-alih URL yang tidak bisa diikutinya. Perbedaan itulah yang membuat kegagalan bisa didiagnosis, karena galat muncul di tempat log berada:
GET /app client -> proxy
GET /app proxy -> 10.40.0.20:8080 over the VPN
response proxy -> client
Dokumentasi pengalihan HAProxy menarik garis persis itu: menjawab klien dengan pengalihan adalah tindakan berbeda dari meneruskan permintaan ke backend. Kedua direktif itu hanya berjarak beberapa baris dalam berkas konfigurasi dan berperilaku sangat berbeda. Satu mengakhiri permintaan, yang lain memulai permintaan kedua yang dimiliki proxy.
Apa yang dibutuhkan browser dan tidak diberikan VPN server kepadanya
Permintaan browser itu sendiri membutuhkan empat hal yang mungkin tidak dimilikinya: jawaban DNS untuk nama privat, rute ke alamat itu, izin mencapai layanan yang mendengarkan, dan kepercayaan pada sertifikat yang disajikan layanan tersebut. Host proxy memiliki keempatnya lewat terowongannya. Tidak satu pun berpindah ke klien yang tidak pernah berada di terowongan itu, karena terowongan adalah sifat host, bukan sifat URL.
Celah itulah yang menjelaskan gejala hampir-berhasil. Permintaan pertama berhasil, bilah alamat berubah, lalu koneksi menggantung atau gagal sementara proxy sehat sepanjang waktu. Tidak ada yang rusak dalam konfigurasi proxy, dan menyesuaikannya tidak menolong klien yang tidak punya jalur ke 10.40.0.20. Entah klien mendapat rute, atau proxy harus membuat koneksi atas namanya.
Ketika hanya proxy yang bisa mencapai aplikasi
Hapus aksi pengalihan dan kirim permintaan itu ke backend yang menunjuk ke alamat privat. Frontend mempertahankan nama publiknya sementara backend memutuskan ke mana permintaan sebenarnya pergi. Tidak ada yang berubah pada jalur klien, karena proxy berhenti menggambarkan tujuan dan mulai menjadi tujuan. Untuk aplikasi yang sengaja mendengarkan pada port internal 8080, blok server-nya singkat:
backend private_app
mode http
option httpchk GET /health
server app1 10.40.0.20:8080 check
Baca blok itu sebagai pernyataan tentang tabel perutean proxy: 10.40.0.20 harus dapat dijangkau dari host proxy itu sendiri, yang di sini berarti lewat antarmuka VPN dan bukan lewat rute default. Kata kunci check hanya melaporkan apa yang dilakukan rute itu, dan jalur kesehatan harus ada di aplikasi atau setiap pemeriksaan menandai server mati. Pemeriksaan yang lolos tidak membuktikan apa pun tentang klien dan tidak menggantikan kebijakan yang menentukan siapa boleh memakai backend.
Fragmen itu bukan frontend lengkap. Pertahankan listener, autentikasi, pemilihan host dan jalur yang diizinkan, serta aturan yang menentukan siapa saja boleh mencapai aplikasi. Sesuaikan juga protokol backend, karena backend HTTPS memerlukan verifikasi sertifikat dan konfigurasi identitas server, dan melewati pemeriksaan itu mengubah koneksi privat menjadi tidak terverifikasi.
Pastikan jalur balik di kedua arah sebelum menyatakan kemenangan. Aplikasi kini melihat koneksi dari proxy, jadi log-nya dan semua metadata alamat klien menggambarkan proxy kecuali Anda mengaturnya lain. Putuskan bagaimana identitas dan alamat yang diteruskan ditangani, dan uji keputusan itu alih-alih menganggapnya.
Pengalihan milik aplikasi masih menunjuk ke dalam
Meneruskan permintaan pertama hanyalah separuh integrasi. Aplikasi dapat mengeluarkan pengalihan absolut, URL aset yang dikodekan keras, atau cookie yang dibatasi pada nama yang dikenalnya secara internal, dan masing-masing mengirim browser kembali ke alamat yang tidak bisa dijangkau. Header Location yang menunjuk nama internal terlihat identik dengan masalah awal, karena itu salah didiagnosis sebagai kegagalan proxy.
Atur URL eksternal terdokumentasi aplikasi dan opsi proxy-nya, lalu samakan header Host dengan host virtual dan harapan sertifikat. Cookie yang dibatasi pada nama internal tidak akan kembali lewat nama publik, dan putaran masuk yang mengikutinya terbaca sebagai bug autentikasi. Ubah URL eksternal lebih dulu, uji ulang dari profil browser bersih, dan perkirakan pengaturan yang baru setengah termigrasi menghasilkan login yang berhasil dan sesi yang langsung mati.
Percayai metadata yang diteruskan hanya dari proxy yang ditunjuk. Header yang bisa diatur klien mana pun tidak boleh pernah menjadi nilai otorisasi, atau proxy berubah menjadi cara bagi pemanggil untuk mengklaim identitas orang lain. Aturan itu tidak bergantung pada pertanyaan pengalihan dan bertahan pada setiap desain ulang berikutnya.
Putuskan desain mana yang sebenarnya Anda miliki
Jika setiap pengguna sudah memiliki akses VPN yang diotorisasi, pengalihan ke URL privat bisa menjadi desain yang disengaja. Pastikan persyaratan itu secara eksplisit alih-alih menganggapnya, karena kedua desain melayani populasi yang sangat berbeda. Salah satunya tidak berfungsi sama sekali dari jaringan hotel, dan yang lain memaparkan aplikasi kepada siapa pun yang bisa memuat URL publik. Perbedaan itu termasuk dalam catatan desain.
Jalankan pemeriksaan dari mesin di jaringan pengguna dan ikuti setiap lompatan yang dilakukan browser, bukan hanya respons pertama. Awasi bilah alamat dan setiap permintaan berikutnya, karena satu URL absolut di tag aset sudah cukup untuk memutus alur yang lolos pada lompatan pertama. Masuk harus bekerja lewat nama publik, dan sumber daya yang seharusnya ditolak harus tetap ditolak.
Menerbitkan reverse proxy adalah keputusan akses tersendiri, bukan perluasan transparan VPN milik proxy kepada siapa pun yang bisa memuat URL publiknya. Keduanya terlihat mirip dalam diagram, dan berbeda dalam siapa yang boleh masuk. Memutuskan pertanyaan itu setelah penerapan adalah cara aplikasi internal menjadi publik secara tidak sengaja.
Tuliskan mana dari keduanya yang Anda bangun dan mengapa. Orang berikutnya yang menyentuh konfigurasi akan menganggap yang lain. Satu pengalihan yang ditambahkan demi kenyamanan sudah cukup untuk menciptakan kembali kegagalan awal, dan gejalanya akan tampak persis seperti yang baru saja Anda perbaiki.