Mengenal app.set('trust proxy') di Express.js: Fungsi, Value, dan Cara Menggunakannya

Agung Dirgantara
By -
0

Kalau kamu pernah menjalankan Express.js di belakang Nginx, Cloudflare, load balancer, atau reverse proxy lainnya, ada satu konfigurasi yang sebaiknya kamu pahami: app.set('trust proxy', ...).



Sekilas, konfigurasi ini terlihat sederhana. Kita hanya perlu memanggil satu method dan memberikan sebuah value. Namun, pengaruhnya cukup besar terhadap cara Express membaca alamat IP pengguna, protokol koneksi, dan informasi lain yang diteruskan oleh proxy.

Nah, mari kita bahas dari dasar, lengkap dengan analogi, contoh kode, dan cara menentukan konfigurasi yang tepat.

1. Apa Itu trust proxy?

trust proxy adalah pengaturan Express.js yang menentukan apakah aplikasi boleh mempercayai informasi forwarding dari proxy di depannya.

Informasi tersebut biasanya dikirim melalui HTTP header seperti:

  • X-Forwarded-For: alamat IP klien yang diteruskan oleh proxy.
  • X-Forwarded-Proto: protokol asli yang digunakan klien, misalnya http atau https.
  • X-Forwarded-Host: hostname asli yang diteruskan oleh proxy.

Informasi tersebut bisa digunakan Express untuk menentukan nilai beberapa properti request, seperti req.ip, req.protocol, req.secure, dan req.hostname.

Namun, ada satu hal penting: header forwarding bukan otomatis informasi yang tepercaya. Klien bisa saja mengirim header palsu jika proxy tidak menangani header tersebut dengan benar.

Itulah alasan kita perlu memahami konfigurasi trust proxy, bukan sekadar mengaktifkannya.

2. Memahami Konsepnya Lewat Analogi

Bayangkan kamu memiliki sebuah kantor dengan resepsionis.

Pengunjung tidak masuk langsung ke kantor, melainkan melewati petugas keamanan terlebih dahulu. Petugas keamanan kemudian meneruskan informasi pengunjung kepada resepsionis.

Dalam skenario ini:

  • Pengunjung adalah pengguna aplikasi.
  • Petugas keamanan adalah reverse proxy.
  • Resepsionis adalah aplikasi Express.js.

Ketika pengunjung tiba, resepsionis perlu mengetahui siapa pengunjung sebenarnya. Namun, koneksi yang diterima resepsionis berasal dari petugas keamanan, bukan langsung dari pengunjung.

Reverse proxy dapat meneruskan informasi pengunjung melalui header HTTP. Express kemudian menentukan apakah informasi tersebut boleh dipercaya berdasarkan konfigurasi trust proxy.

Dengan kata lain, konfigurasi ini seperti memberi tahu resepsionis:

Informasi dari petugas keamanan ini boleh dipercaya, selama petugas tersebut memang termasuk pihak yang kita percayai.

Jadi, masalahnya bukan sekadar apakah kita percaya kepada proxy, melainkan proxy mana yang dipercaya dan bagaimana informasi tersebut diteruskan.

3. Apa yang Terjadi Jika trust proxy Tidak Diaktifkan?

Secara default, Express menggunakan:

app.set('trust proxy', false);

Artinya, Express tidak mempercayai informasi forwarding dari proxy untuk menentukan properti request yang dipengaruhi oleh pengaturan tersebut.

Misalnya, arsitektur aplikasi kamu seperti ini:

Pengguna
   |
   v
Nginx (10.0.0.2)
   |
   v
Express.js (3000)

Pengguna memiliki alamat IP 203.0.113.10, tetapi koneksi langsung yang diterima Express berasal dari Nginx.

Jika trust proxy tidak diaktifkan, req.ip biasanya berisi alamat IP Nginx, bukan alamat IP pengguna.

Hal ini tidak selalu menjadi masalah. Jika aplikasi memang menerima koneksi langsung dari pengguna, konfigurasi default justru sesuai.

Namun, ketika aplikasi berada di belakang proxy, kita perlu menentukan apakah informasi forwarding dari proxy tersebut memang dibutuhkan dan dapat dipercaya.

4. Mengenal Value yang Didukung trust proxy

Express mendukung beberapa jenis value untuk konfigurasi ini. Setiap value memiliki perilaku yang berbeda.

A. false: Tidak Memercayai Proxy

app.set('trust proxy', false);

Ini adalah nilai default Express.

Gunakan konfigurasi ini ketika aplikasi tidak perlu mempercayai informasi forwarding dari proxy.

Contohnya, Express menerima koneksi langsung dari klien dan tidak menggunakan header forwarding untuk menentukan IP atau protokol klien.

B. true: Memercayai Semua Hop Proxy

app.set('trust proxy', true);

Dengan konfigurasi ini, Express menganggap semua hop proxy dalam rantai forwarding tepercaya.

Akibatnya, Express dapat menggunakan informasi X-Forwarded-* untuk menentukan alamat IP dan protokol klien.

Namun, jangan menganggap true sebagai pilihan yang otomatis lebih baik.

Jika aplikasi dapat diakses melalui jalur yang tidak tepercaya atau proxy tidak membersihkan header forwarding dengan benar, pengguna bisa memalsukan informasi yang digunakan aplikasi.

Gunakan konfigurasi ini hanya jika seluruh rantai proxy dan penanganan header sudah dikendalikan dengan aman.

C. Angka: Memercayai Berdasarkan Jumlah Hop

app.set('trust proxy', 1);

Angka menunjukkan jumlah hop proxy yang dipercaya, dihitung dari aplikasi ke arah klien.

Misalnya:

Pengguna → Nginx → Express

Jika hanya ada satu proxy antara pengguna dan Express, angka 1 bisa sesuai.

Contoh lain:

Pengguna → Load Balancer → Nginx → Express

Pada topologi tersebut, terdapat dua hop proxy. Angka 2 mungkin sesuai jika jalur koneksi selalu konsisten dan semua proxy menangani header dengan benar.

app.set('trust proxy', 2);

Perlu diperhatikan bahwa konfigurasi berdasarkan jumlah hop berisiko jika aplikasi bisa menerima koneksi melalui jalur dengan panjang berbeda. Penyerang dapat memanfaatkan perbedaan jalur tersebut untuk memengaruhi informasi IP yang dipilih Express.

Jadi, jangan menentukan angka hanya berdasarkan perkiraan. Cocokkan dengan topologi jaringan yang sebenarnya.

D. IP atau Subnet: Memercayai Proxy Tertentu

Jika alamat IP proxy diketahui, kamu dapat menentukan proxy yang dipercaya secara lebih spesifik.

Contohnya:

app.set('trust proxy', '10.0.0.2');

Untuk subnet internal:

app.set('trust proxy', '10.0.0.0/8');

Express juga menyediakan nama subnet tertentu, seperti loopback.

app.set('trust proxy', 'loopback');

Pendekatan ini berguna ketika kamu ingin membatasi kepercayaan hanya kepada alamat atau jaringan yang memang digunakan oleh proxy tepercaya.

Tetap pastikan rentang IP tersebut sesuai dengan infrastruktur yang sebenarnya. Jangan mempercayai subnet yang terlalu luas tanpa alasan yang jelas.

E. Array: Memercayai Beberapa IP atau Subnet

Jika proxy tepercaya berada di beberapa jaringan, kamu dapat menggunakan array.

app.set('trust proxy', [
  'loopback',
  '10.0.0.0/8',
]);

Dengan konfigurasi tersebut, Express menggunakan daftar alamat dan subnet tersebut sebagai aturan kepercayaan.

Pendekatan ini lebih fleksibel ketika infrastruktur memiliki beberapa proxy atau jaringan internal.

F. Function: Membuat Aturan Sendiri

Express juga memungkinkan kita menentukan aturan kepercayaan menggunakan function.

app.set('trust proxy', (ip) => {
  return ip === '10.0.0.2';
});

Function tersebut mengembalikan true hanya ketika alamat yang diperiksa cocok dengan 10.0.0.2.

Pilihan ini cocok untuk kebutuhan khusus ketika aturan IP tidak cukup sederhana untuk dinyatakan dengan konfigurasi biasa.

Perlu diingat, function tersebut harus mengimplementasikan aturan yang benar-benar sesuai dengan topologi jaringan. Jangan sekadar mengembalikan true untuk semua alamat.

5. Apa Pengaruhnya terhadap req.ip, req.protocol, dan Properti Lain?

Untuk melihat pengaruh konfigurasi ini, kita bisa membuat endpoint sederhana.

app.get('/debug/request', (req, res) => {
  res.json({
    ip: req.ip,
    ips: req.ips,
    protocol: req.protocol,
    secure: req.secure,
    hostname: req.hostname,
  });
});

Berikut penjelasan setiap properti.

Properti Fungsi
req.ip Alamat IP klien yang ditentukan Express
req.ips Daftar alamat IP dari rantai forwarding yang dikenali Express
req.protocol Protokol yang diketahui Express, yaitu http atau https
req.secure Bernilai true jika req.protocol adalah https
req.hostname Hostname request, yang dapat dipengaruhi oleh header forwarding

Misalnya, pengguna membuka aplikasi menggunakan HTTPS, tetapi koneksi dari reverse proxy menuju Express menggunakan HTTP.

Pengguna --HTTPS--> Nginx --HTTP--> Express

Tanpa konfigurasi proxy yang sesuai, Express mungkin hanya mengetahui bahwa koneksi langsungnya menggunakan HTTP.

Jika Nginx meneruskan informasi protokol dengan benar dan Express mempercayai proxy tersebut, req.protocol dapat bernilai https dan req.secure dapat bernilai true.

Namun, hasilnya bergantung pada header yang dikirim dan konfigurasi kepercayaan yang digunakan.

Perlu diperhatikan juga bahwa req.hostname bukan otomatis nilai yang aman untuk digunakan dalam keputusan keamanan hanya karena trust proxy telah dikonfigurasi.

Endpoint debug seperti ini sebaiknya hanya digunakan saat pengembangan atau dilindungi dengan baik jika berada di lingkungan production.

6. Bagaimana Menggunakan TRUST_PROXY dari File .env?

Jika project menggunakan konfigurasi environment, kamu bisa menyimpan pengaturan proxy di .env.

TRUST_PROXY=1

Kemudian, terapkan konfigurasi tersebut saat membuat aplikasi Express.

Berikut contoh helper untuk mendukung boolean, angka, IP, subnet, dan nama subnet:

const parseTrustProxy = (
  value: string | undefined,
): boolean | number | string => {
  if (value === undefined || value === 'false') {
    return false;
  }

  if (value === 'true') {
    return true;
  }

  if (/^\d+$/.test(value)) {
    return Number(value);
  }

  return value;
};

app.set('trust proxy', parseTrustProxy(process.env.TRUST_PROXY));

Dengan pendekatan ini, beberapa konfigurasi yang bisa digunakan antara lain:

TRUST_PROXY=false
TRUST_PROXY=true
TRUST_PROXY=1
TRUST_PROXY=10.0.0.2
TRUST_PROXY=loopback

Contoh tersebut hanya menangani nilai boolean, angka, dan string. Jika ingin menggunakan beberapa IP sekaligus, format array, atau function, kamu perlu menambahkan penanganan khusus di kode.

Jangan lupa bahwa .env hanyalah tempat menyimpan konfigurasi. Memasukkan angka 1 tidak otomatis membuat topologi jaringan kamu benar-benar memiliki satu proxy tepercaya.

7. Jadi, Sebaiknya Menggunakan Value yang Mana?

Tidak ada satu value yang cocok untuk semua aplikasi. Pilih berdasarkan bagaimana aplikasi menerima koneksi.

Jika Express menerima koneksi langsung dari pengguna, biarkan konfigurasi tetap false.

Jika Express berada di belakang satu reverse proxy, kamu bisa mempertimbangkan IP proxy tertentu atau angka 1, selama topologi dan pengelolaan header sudah diverifikasi.

Jika aplikasi berada di belakang load balancer dan beberapa proxy, pahami rantai koneksinya terlebih dahulu. Konfigurasi IP atau subnet yang spesifik biasanya lebih mudah dikendalikan daripada mempercayai semua hop tanpa batasan.

Jika menggunakan platform hosting atau CDN, periksa dokumentasi platform mengenai header forwarding, jaringan proxy, dan cara mereka menangani header yang dikirim klien.

Sebagai aturan praktis, jangan memilih konfigurasi hanya karena aplikasi terlihat berjalan normal. Konfigurasi yang salah terkadang baru menimbulkan masalah ketika aplikasi mulai menggunakan IP untuk pembatasan request, logging, atau keputusan keamanan.

8. Kesimpulan

app.set('trust proxy', ...) bukan sekadar konfigurasi tambahan di Express.js. Pengaturan ini menentukan bagaimana aplikasi mempercayai informasi yang diteruskan oleh proxy.

Ada beberapa value yang dapat digunakan:

  • false untuk tidak mempercayai informasi forwarding dari proxy.
  • true untuk mempercayai seluruh hop proxy.
  • Angka untuk menentukan jumlah hop yang dipercaya.
  • IP, subnet, atau array untuk membatasi proxy yang dipercaya.
  • Function untuk menerapkan aturan khusus.

Kalau ada satu hal yang perlu diingat, ingatlah ini: percayai proxy berdasarkan infrastruktur yang benar-benar kamu kendalikan, bukan sekadar agar req.ip menampilkan alamat IP yang kamu harapkan.

Memahami hal ini sejak awal akan membantu kamu membangun aplikasi Express yang lebih mudah di-debug, lebih akurat dalam membaca informasi request, dan lebih aman ketika dijalankan di balik reverse proxy.

Referensi

Posting Komentar

0Komentar

Posting Komentar (0)