Peer soket versus header diteruskan: alamat mana yang Anda percayai?
Peer soket dan header diteruskan adalah bukti yang berbeda. Bandingkan apa yang dibuktikan masing-masing, dan percayai header hanya melalui rantai proxy yang Anda kendalikan.
Permintaan yang tiba di aplikasi Anda membawa dua jenis bukti alamat: peer yang membuka koneksi jaringan, dan bidang HTTP yang mengklaim alamat klien sebelumnya. Keduanya menjawab pertanyaan yang berbeda. Peer soket diamati, sedangkan header diklaim oleh siapa pun yang menulisnya, dan tidak satu pun seharusnya diam-diam menggantikan yang lain dalam log atau aturan akses. Perbandingan di bawah ini menjaganya tetap terpisah, lalu menunjukkan satu-satunya susunan ketika header menjadi berguna.
Jelaskan jalurnya sebelum membandingkan apa pun:
Client -> approved reverse proxy -> application originDalam susunan itu, peer soket asal biasanya adalah proxy, dan header penerusan dapat membawa klaim proxy tentang klien. Nilainya berasal dari hubungan yang terkendali dengan proxy itu, bukan dari nama header.
Dua jenis bukti alamat
Peer soket adalah fakta tentang satu koneksi TCP: sesuatu menyelesaikan jabat tangan dari alamat itu. Itu belum tentu orang, perangkat, atau akun yang Anda pedulikan, karena VPN atau pintu keluar Tor dapat secara sah menjadi sumber yang diamati layanan. Namun itu tetap satu-satunya alamat yang diverifikasi oleh host itu sendiri, dan di situlah seluruh nilainya.
Bidang penerusan adalah metadata tentang rantai. X-Forwarded-For, X-Real-IP dan bidang terstandar Forwarded dapat ditulis oleh klien mana pun yang mencapai titik akhir yang memantulkannya, sehingga keandalannya sepenuhnya bergantung pada siapa yang diizinkan menetapkannya.
Simpan keduanya dalam konteks permintaan dengan nama yang berbeda. Aplikasi yang menimpa peer dengan header kehilangan kemampuan merekonstruksi kesalahan kepercayaan nanti, dan itulah tepat saat Anda membutuhkannya.
Header tidak pernah mengalihkan rute koneksi
Menulis alamat ke bidang penerusan tidak mengubah sumber koneksi TCP yang tiba di server, dan tidak mengubah perutean di mana pun sepanjang jalur. Perutean VPN biasa atau NAT sumber mengantarkan lalu lintas tanpa header HTTP sama sekali. Demikian pula, gateway transit tidak menulis ulang pertukaran HTTPS yang terlindungi dengan benar tanpa mengubah susunan titik akhir TLS.
Kesalahan sebaliknya sama umumnya: HTTPS tidak membuat header penerusan yang diberikan klien menjadi benar. Ia melindungi pengangkutan klaim palsu sama baiknya dengan klaim yang benar.
Jika seorang kolega mengusulkan perubahan header untuk memperbaiki masalah perutean, diagnosisnya sudah salah arah. Perbaiki jalurnya, atau perbaiki konfigurasi proxy yang menulis header itu.
Namai proxy yang diizinkan mengklaim
Dua aturan membuat bidang penerusan berguna, dan keduanya adalah konfigurasi bukan kode. Tepi menormalkan atau membuang apa pun yang datang dari luar, mengikuti perilaku terdokumentasinya untuk bidang tersebut. Asal kemudian mengambil alamat pengganti dari jalur proxy yang Anda namai dan bukan dari tempat lain. Aturan kedua itu hanya berlaku selama klien tidak dapat mencapai asal dengan cara lain, karena asal yang menjawab permintaan langsung maupun melalui proxy tidak tahu mana yang dilayaninya.
Modul IP asli NGINX menunjukkan pemisahan itu dengan jelas. set_real_ip_from menyebut pengirim yang klaimnya diperhitungkan, dan real_ip_header mengatakan bidang mana yang membawanya; yang pertama melakukan kepercayaan, yang kedua hanya mengatakan ke mana harus melihat.
set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on - walk the list back past every trusted address
Direktif pemilihan header saja masih tidak menetapkan apa pun tentang siapa yang mengirim nilai itu.
Keamanan pengangkutan harus berjalan sepanjang jalan antara komponen yang Anda percayai. Tepi yang menormalkan dengan benar kehilangan nilai itu pada saat lompatan yang tidak terlindungi di hilir membiarkan orang lain menyunting klaim saat ia dalam perjalanan.
Tangani rantai banyak lompatan dengan sengaja
Beberapa proxy memerlukan model rantai yang eksplisit. Jangan mengambil nilai paling kiri atau paling kanan yang dipisahkan koma karena sebuah tulisan blog melakukannya; cari tahu proxy mana yang menambahkan, mana yang mengganti, dan mana yang mempertahankan bidang masuk. NGINX, misalnya, dapat menelusuri daftar ke belakang terhadap himpunan tepercayanya dan berhenti pada alamat pertama yang bukan miliknya, dan itu aturan produk tersebut, bukan hukum yang diikuti setiap kerangka kerja. Bacalah dokumentasi proxy Anda sendiri dengan dua pertanyaan yang sama: nilai mana yang dipilihnya, dan pengirim mana yang dipercayainya?
Tuliskan rantainya: urutan lompatan, lompatan mana yang menetapkan bidang, dan lompatan mana yang menghapus salinan masuk. Lalu simpan catatan itu di samping konfigurasi proxy, bukan hanya di tiket. Lalu ujilah dengan mengirim permintaan dengan header palsu melalui proses validasi yang disetujui dan memastikan asal mengabaikannya.
Ketika Anda menambahkan lompatan, tinjau kembali dokumen itu. Penyeimbang beban baru yang disisipkan di depan proxy tepercaya dapat mengubah alamat mana yang menang tanpa siapa pun menyunting aplikasi.
Simpan kedua pengamatan di log
Di tempat diagnostik diizinkan, catat peer koneksi dan alamat klien yang dinormalkan sebagai dua bidang terpisah, dan tambahkan hanya metadata penerusan yang benar-benar dibutuhkan tujuan. Lalu buktikan penerapannya dengan dua permintaan: satu melalui proxy yang seharusnya mencatat kedua nilai secara wajar, dan satu upaya langsung ke asal yang harus ditolak.
Ingat apa arti pasangan itu. Header menambahkan konteks yang disediakan komponen yang Anda pilih untuk dipercaya; peer tetap satu-satunya alamat yang benar-benar dilihat host Anda. Tidak satu pun merupakan bukti identitas individu, dan desain yang memperlakukan salah satunya sebagai bukti akan salah tentang seseorang.