Mengunci server dan memasang WAF di depan aplikasi Anda

Sejak deploy pertama, erpc worker hanya mengizinkan SSH masuk dari alamat Anda dan men-drop semua koneksi masuk lainnya. Tabel [waf] memasang proxy penyaring di depan API Anda.
Halaman ini menjelaskan ERPC CLI v0.1.0-rc.4, versi pra-rilis.

Firewall

Deploy mengatur firewall server sebelum aplikasi dijalankan untuk pertama kalinya:
  • SSH hanya dari firewall.ssh_allow dan dari alamat asal deploy;
  • semua koneksi masuk lainnya di-drop, kecuali run.port dari firewall.app_allow; untuk aplikasi di belakang WAF, port WAF menggantikannya, dan hanya jika WAF di server sudah menjalankan aturan yang sekarang dibuat oleh [waf] (di bawah).
Setiap perubahan berjalan di bawah timer rollback 120 detik dan hanya dipertahankan setelah koneksi baru berhasil masuk, sehingga perubahan yang keliru tidak dapat mengunci Anda di luar.
Namun, allowlist bertahan lebih lama daripada alamat yang menjadi asalnya: jika alamat rumah Anda berubah, jalan untuk masuk kembali adalah lewat tim dukungan ERPC untuk server ERPC, atau konsol penyedia untuk server milik Anda sendiri. Simpan alamat kedua yang dapat Anda pakai untuk menjangkau server (kantor, exit VPN) di firewall.ssh_allow sebelum Anda mengandalkan alamat rumah.
Jika alamat Anda berubah, tambahkan setiap alamat tetap yang dipakai admin Anda:
bash
erpc worker firewall allow --to ssh 203.0.113.10 198.51.100.7
PerintahFungsinya
erpc worker firewall listMenampilkan siapa yang boleh menjangkau server: erpc.toml berdampingan dengan tabel milik server
erpc worker firewall allow --to ssh|app <addresses>Mengizinkan alamat masuk, lalu menerapkannya. SSH diizinkan dari alamat tunggal; jaringan hanya diterima dengan --to app
erpc worker firewall deny --to ssh|app <addresses>Berhenti mengizinkan alamat tersebut masuk
erpc worker firewall syncMengembalikan firewall server agar sesuai dengan isi erpc.toml

Pasang WAF di depan aplikasi Anda

Tambahkan satu tabel ke erpc.toml:
toml
[waf]
port = 8080
Setelah itu erpc worker deploy menjalankan HTTP reverse proxy di server, dalam unit systemd tersendiri (erpc-waf-<app>-<env>): user dinamis tanpa hak istimewa, tanpa kunci, tanpa secret, dan tanpa apa pun milik worker, dibatasi 1 GiB memori. Proxy ini mendengarkan di waf.port, membaca setiap request sebelum aplikasi membacanya, menolak apa yang disebut oleh aturannya, dan meneruskan sisanya ke aplikasi di 127.0.0.1:<run.port>.
  • Aplikasi tetap di loopback. Port miliknya sendiri tidak pernah dibuka dari luar. erpc worker api dan health check menjangkau aplikasi di loopback, tanpa melalui WAF.
  • Siapa yang boleh terhubung tetap ditentukan oleh daftar firewall, dan port WAF adalah satu-satunya tempat daftar itu boleh menyebut semua orang:
    sh
    erpc worker firewall allow --to app 0.0.0.0/0     # and ::/0
    Jika tidak ada yang tercantum, WAF mendengarkan dan tidak ada yang diizinkan masuk, dan deploy memberitahukannya.
  • Port dibuka setelah WAF mendengarkan di port itu, tidak pernah sebelumnya. Deploy yang WAF-nya tidak berjalan akan gagal dan menyebutkan alasannya, sementara aplikasi tetap berjalan.
  • Saat Anda mengubah [waf], port tidak dibuka untuk siapa pun yang baru sampai sebuah deploy memasang aturan yang baru.
  • Menghapus [waf] dari erpc.toml lalu men-deploy akan menghapus WAF dari server.

Pengaturan WAF

Hanya port yang wajib. Setiap key, beserta nilai default-nya:
toml
[waf]
port = 8080          # the public port, 1024 or above; the app keeps [run] port
methods = ["GET", "POST", "PUT", "DELETE"]
allow_paths = []     # every path
deny_paths = []
max_body_bytes = 1048576
max_header_bytes = 16384
rate = { per_second = 50, burst = 100 }
max_connections_per_address = 32
ban = { after = 100, window_secs = 60, for_secs = 600 }
block_probes = true
header_timeout_secs = 10
body_timeout_secs = 30
upstream_timeout_secs = 30
new_connections = { per_second = 50, burst = 100 }
KeyFungsinyaYang didapat jika ditolak
methodsMethod yang diteruskan, dalam huruf kapital (paling banyak 16; tidak pernah CONNECT)405, dengan Allow
allow_pathsPath yang diteruskan; jika tidak ada yang tercantum, semua path diteruskan. Sebuah pola adalah satu path, atau semua yang berada di bawah sebuah prefix jika diakhiri *: /api/* berarti /api dan semua yang di bawahnya. Dibandingkan dengan path setelah percent-decoding satu kali, peka huruf besar-kecil404
deny_pathsPath yang ditolak, ditulis dengan cara yang sama dan diperiksa lebih dulu403
max_body_bytesBody request terbesar, hingga 64 MiB413
max_header_bytesRequest line dan header terbesar jika digabungkan, 1024 hingga 65536431
rateJumlah request per detik dari satu alamat, dan berapa banyak sekaligus sebelum rate berlaku429, dengan Retry-After
max_connections_per_addressJumlah koneksi yang dapat dipegang satu alamat sekaligusKoneksi ditutup, tanpa jawaban
banSetelah after request yang diblokir dalam window_secs, alamat tersebut ditolak selama for_secs (hingga 30 hari)Koneksinya ditutup, tanpa jawaban
block_probesMenolak apa yang diminta oleh scanner (/.env, /.git, /wp-login.php, dan sejenisnya)403
header_timeout_secsBerapa lama client boleh mengirim bagian kepala request, 1 hingga 120. Juga berapa lama client ditunggu jika berhenti di tengah body, atau berhenti menerima jawabannya408 untuk bagian kepala; 400 untuk body yang berhenti; koneksi ditutup untuk jawaban yang tidak diterima
body_timeout_secsBerapa lama body request boleh berlangsung secara keseluruhan, 1 hingga 600, tidak termasuk waktu WAF menunggu aplikasi408
upstream_timeout_secsBerapa lama aplikasi boleh menerima koneksi dan mulai menjawab, 1 hingga 600504; 502 jika aplikasi tidak mendengarkan
new_connectionsBatas milik firewall sendiri untuk koneksi TCP baru per detik dari satu alamat ke port WAF, di-drop oleh nftables sebelum proxy melihatnya. Selama set alamat milik nftables penuh, alamat yang tidak ada di dalamnya tidak dihitung, sehingga batas ini tidak berlaku untuk alamat tersebut sampai set itu kembali memiliki ruang; batas milik proxy sendiri (rate, max_connections_per_address, ban) tetap berlakuPaket di-drop
rate, max_connections_per_address, ban, dan new_connections dimatikan dengan false (ban = false), dan key yang tidak ditulis memakai nilai default-nya. erpc worker check menjelaskan apa yang akan dilakukan tabel [waf], dan apa yang salah di dalamnya, sebelum deploy apa pun.

Yang dilakukan WAF tanpa perlu pengaturan

  • Request yang tidak terbaca sebagai satu request HTTP/1 yang tidak ambigu mendapat 400, begitu juga path yang tidak dalam bentuk normal.
  • Request untuk mengganti protokol (Upgrade) mendapat 501.
  • Setiap penolakan dihitung untuk ban, dan setiap penolakan mengakhiri koneksinya.
  • Satu alamat adalah satu alamat IPv4, atau satu /64 IPv6.
  • WAF tidak meneruskan header milik koneksi antara client dan proxy (Connection dan header yang disebutnya, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailer), Expect, header yang namanya mengandung garis bawah, maupun Forwarded, X-Real-IP, dan X-Forwarded-Proto milik client sendiri. WAF mengisi X-Real-IP dengan alamat asal koneksi dan menambahkan alamat itu ke akhir X-Forwarded-For; hanya entri terakhir X-Forwarded-For yang berasal dari proxy.

Melihat apa yang dilakukan WAF

PerintahYang ditampilkan
erpc worker statusPort WAF, ke mana ia meneruskan, sejak kapan, dan hitungan sejak saat itu
erpc worker firewall listSiapa yang boleh menjangkau port WAF, dan apa yang diblokir, per aturan
erpc worker logs --wafSetiap request yang diblokir: aturannya, status, alamat client, method, dan 200 byte pertama dari target
Request yang diteruskan tidak meninggalkan baris log, dan header atau body tidak pernah dicatat dalam log; query dari request yang diblokir dicatat, sejauh 200 byte itu menjangkaunya. Apa yang dikirim client tidak dapat menulis di terminal Anda: WAF menulis journal-nya sebagai ASCII yang dapat dicetak.

Yang tidak dilakukan WAF

  • Tanpa TLS. WAF memakai HTTP/1.1 biasa di port-nya.
  • Tanpa HTTP/2: WAF menjawabnya dengan 400.
  • Tanpa WebSocket, maupun Upgrade lainnya: 501.
  • Tidak memeriksa isi body. Body diukur, tidak pernah dibaca. Daftar probe itu pendek dan merupakan penyaring gangguan, bukan jaminan: aplikasi tetap memeriksa input-nya.
  • Tanpa autentikasi. Siapa yang boleh memanggil aplikasi adalah keputusan aplikasi, dan daftar firewall.
  • Satu alamat adalah satu client. Client di belakang satu NAT, proxy, atau CDN berbagi satu rate dan satu ban; client dengan banyak alamat memiliki rate sebanyak alamatnya.
  • Ban dan hitungan dilupakan saat WAF di-restart.
  • WAF mengingat paling banyak 8192 alamat dan memegang paling banyak 1024 koneksi sekaligus.
  • WAF hanya mendengarkan di IPv4, sehingga entri IPv6 di app_allow belum menjangkau apa pun.
  • Path dibandingkan sebagai byte hasil decode-nya. Aplikasi yang membaca path dengan lebih longgar (mengabaikan huruf besar-kecil, parameter ;, decode dua kali) dapat dijangkau lewat nama yang tidak dicakup deny_paths. allow_paths tidak memiliki celah seperti itu: apa yang tidak tercantum tidak diteruskan.
  • Pembaca yang lambat dilayani sampai selesai. Client yang terus menerima jawaban, selambat apa pun, dilayani sampai selesai.
  • Banjir request dapat memutus upload besar. WAF berjalan di satu thread, sehingga banjir request dapat memutus upload besar dengan 408. Aplikasi yang menerima body besar menaikkan body_timeout_secs bersama dengan max_body_bytes.
Panduan worker memuat setiap aturan, termasuk kapan perubahan pada app_allow ditahan sampai deploy berikutnya.