सर्वर की पहुँच सीमित करें और अपने app के आगे WAF लगाएँ

पहले deploy से ही, erpc worker SSH को सिर्फ़ आपके address से अंदर आने देता है और बाकी हर आने वाला कनेक्शन ड्रॉप करता है। एक [waf] table आपके API के आगे फ़िल्टर करने वाली प्रॉक्सी लगाती है।
यह पेज ERPC CLI v0.1.0-rc.4 के बारे में है, जो एक प्री-रिलीज़ है।

फ़ायरवॉल

Deploy, app के पहली बार शुरू होने से पहले सर्वर का फ़ायरवॉल सेट करता है:
  • SSH सिर्फ़ firewall.ssh_allow से और उस address से, जहाँ से deploy आता है;
  • बाकी हर आने वाला कनेक्शन ड्रॉप, सिवाय firewall.app_allow से run.port के; WAF के पीछे वाले app के लिए उसकी जगह WAF का पोर्ट, और वह भी सिर्फ़ वहाँ, जहाँ सर्वर पर WAF पहले से वे नियम चला रहा हो जो [waf] अब बनाता है (नीचे)।
हर बदलाव 120 सेकंड के रोलबैक टाइमर के तहत चलता है और तभी रखा जाता है जब कोई नया कनेक्शन अंदर आ पाए, इसलिए कोई गलत बदलाव आपको बाहर लॉक नहीं कर सकता।
फिर भी, allowlist उस address के बदल जाने के बाद भी बनी रहती है जिससे वह बनी थी: अगर आपके घर का address बदल जाए, तो वापस अंदर आने का रास्ता ERPC सर्वर के लिए ERPC सपोर्ट है, या आपके अपने सर्वर के लिए provider का console। घर वाले address पर भरोसा करने से पहले, firewall.ssh_allow में एक दूसरा address रखें जिससे आप सर्वर तक पहुँच सकें (कोई office, कोई VPN exit)।
अगर आपका address बदलता है, तो आपके admins जो भी fixed address इस्तेमाल करते हैं, वे सब जोड़ें:
bash
erpc worker firewall allow --to ssh 203.0.113.10 198.51.100.7
कमांडयह क्या करता है
erpc worker firewall listदिखाता है कि सर्वर तक कौन पहुँच सकता है: erpc.toml और उसके साथ-साथ सर्वर की table
erpc worker firewall allow --to ssh|app <addresses>Addresses को अंदर आने देता है, और इसे लागू करता है। SSH सिर्फ़ अलग-अलग addresses से allow होता है; network सिर्फ़ --to app के साथ स्वीकार होता है
erpc worker firewall deny --to ssh|app <addresses>उन्हें अंदर आने देना बंद करता है
erpc worker firewall syncसर्वर के फ़ायरवॉल को फिर से वैसा बनाता है जैसा erpc.toml कहता है

अपने app के आगे WAF लगाएँ

erpc.toml में एक table जोड़ें:
toml
[waf]
port = 8080
इसके बाद erpc worker deploy सर्वर पर एक HTTP रिवर्स प्रॉक्सी चलाता है, उसकी अपनी systemd यूनिट में (erpc-waf-<app>-<env>): यह एक बिना विशेषाधिकार वाले dynamic user के रूप में चलता है, जिसके पास न कोई key है, न कोई secret, न worker की कोई चीज़, और जो 1 GiB मेमोरी तक सीमित है। यह waf.port पर सुनता है, हर request को app से पहले पढ़ता है, जिन चीज़ों का नाम इसके नियमों में है उन्हें अस्वीकार करता है, और बाकी को 127.0.0.1:<run.port> पर app तक भेजता है।
  • App loopback पर रहता है। उसका अपना पोर्ट बाहर से कभी नहीं खुलता। erpc worker api और हेल्थ चेक, WAF से गुज़रे बिना, loopback पर app तक पहुँचते हैं।
  • कौन कनेक्ट कर सकता है, यह अब भी फ़ायरवॉल की सूची तय करती है, और WAF का पोर्ट ही वह अकेली जगह है जहाँ वह सूची "हर कोई" कह सकती है:
    sh
    erpc worker firewall allow --to app 0.0.0.0/0     # and ::/0
    अगर सूची में कोई नहीं है, तो WAF सुनता है पर किसी को अंदर नहीं आने दिया जाता, और deploy यह बताता है।
  • पोर्ट तभी खुलता है जब WAF उस पर सुनने लगे, उससे पहले कभी नहीं। जिस deploy का WAF शुरू नहीं होता, वह विफल होता है और वजह बताता है, जबकि app चलता रहता है।
  • जब आप [waf] बदलते हैं, तो पोर्ट किसी नए व्यक्ति के लिए तब तक नहीं खुलता जब तक कोई deploy नए नियम लागू न कर दे।
  • [waf] को हटाना: इसे erpc.toml से हटाकर deploy करने पर सर्वर से WAF हट जाता है।

WAF सेटिंग्स

सिर्फ़ port ज़रूरी है। हर सेटिंग key, उसके default के साथ:
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 }
Keyयह क्या करती हैजो अस्वीकार हो, उसे क्या मिलता है
methodsआगे भेजे जाने वाले methods, capital letters में (अधिकतम 16; CONNECT कभी नहीं)405, Allow के साथ
allow_pathsआगे भेजे जाने वाले paths; कोई न लिखा हो तो हर path। एक pattern एक path होता है, या, जब वह * पर खत्म हो, तो किसी prefix के नीचे सब कुछ: /api/* का मतलब है /api और उसके नीचे सब। इसे एक बार percent-decode किए गए path से मिलाया जाता है, case-sensitive404
deny_pathsअस्वीकार किए जाने वाले paths, उसी तरह लिखे जाते हैं और सबसे पहले जाँचे जाते हैं403
max_body_bytesrequest body का सबसे बड़ा आकार, 64 MiB तक413
max_header_bytesrequest line और headers का मिलाकर सबसे बड़ा आकार, 1024 से 65536431
rateएक address से प्रति सेकंड requests, और rate लागू होने से पहले एक साथ कितनी429, Retry-After के साथ
max_connections_per_addressएक address एक साथ कितने कनेक्शन रख सकता हैकनेक्शन बिना जवाब दिए बंद
banwindow_secs के भीतर after ब्लॉक हुई requests के बाद, address को for_secs तक अस्वीकार किया जाता है (अधिकतम 30 दिन)उसके कनेक्शन बिना जवाब दिए बंद
block_probesscanners जो माँगते हैं उसे अस्वीकार करता है (/.env, /.git, /wp-login.php और इसी तरह की चीज़ें)403
header_timeout_secsclient के पास request का head भेजने के लिए कितना समय है, 1 से 120। यही वह समय भी है जितना उस client का इंतज़ार किया जाता है जो body के बीच में रुक गया हो, या जिसने अपना जवाब लेना बंद कर दिया होhead के लिए 408; रुकी हुई body के लिए 400; न लिए गए जवाब के लिए कनेक्शन बंद
body_timeout_secsकिसी request की body को कुल कितना समय लग सकता है, 1 से 600, उस समय को गिने बिना जब WAF app का इंतज़ार करता है408
upstream_timeout_secsapp के पास कनेक्शन लेने और जवाब देना शुरू करने के लिए कितना समय है, 1 से 600504; जब app सुन नहीं रहा हो तो 502
new_connectionsWAF के पोर्ट पर एक address से प्रति सेकंड नए TCP कनेक्शन की फ़ायरवॉल की अपनी सीमा; प्रॉक्सी के देखने से पहले ही nftables इन्हें ड्रॉप करता है। जब तक nftables का addresses वाला set भरा है, उसमें न मौजूद address गिना नहीं जाता, इसलिए जब तक set में फिर से जगह न हो, यह सीमा उस पर लागू नहीं होती; प्रॉक्सी की अपनी सीमाएँ (rate, max_connections_per_address, ban) फिर भी लागू होती हैंpacket ड्रॉप
rate, max_connections_per_address, ban और new_connections को false से बंद किया जाता है (ban = false), और जो key छोड़ दी जाए, वह अपने default पर रहती है। erpc worker check किसी भी deploy से पहले बताता है कि [waf] table क्या करेगी, और उसमें क्या गलत है।

WAF बिना किसी सेटिंग के क्या करता है

  • जो request एक असंदिग्ध HTTP/1 request के रूप में न पढ़ी जा सके, उसे 400 मिलता है, और ऐसे path को भी जो normal form में न हो।
  • protocol बदलने की request (Upgrade) को 501 मिलता है।
  • हर अस्वीकृति ban की गिनती में जुड़ती है, और हर अस्वीकृति अपना कनेक्शन खत्म करती है।
  • एक address का मतलब है एक IPv4 address, या एक IPv6 /64।
  • WAF, client और प्रॉक्सी के बीच वाले कनेक्शन के headers आगे नहीं भेजता (Connection और वे headers जिनका वह नाम लेता है, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailer), न Expect, न वे headers जिनके नाम में underscore हो, न client के अपने Forwarded, X-Real-IP और X-Forwarded-Proto। यह X-Real-IP को उस address पर सेट करता है जिससे कनेक्शन आया, और उस address को X-Forwarded-For के अंत में जोड़ता है; X-Forwarded-For की सिर्फ़ आखिरी एंट्री प्रॉक्सी की कही हुई बात है।

देखें कि WAF क्या करता है

कमांडक्या दिखाता है
erpc worker statusWAF का पोर्ट, वह कहाँ आगे भेजता है, कब से, और तब से की गिनतियाँ
erpc worker firewall listWAF के पोर्ट तक कौन पहुँच सकता है, और नियम के हिसाब से क्या ब्लॉक हुआ
erpc worker logs --wafहर ब्लॉक हुई request: नियम, status, client का address, method और target के पहले 200 bytes
आगे भेजी गई request लॉग की कोई पंक्ति नहीं छोड़ती, और कोई header या body कभी लॉग नहीं होता; ब्लॉक हुई request की query लॉग होती है, जहाँ तक 200 bytes पहुँचते हैं। Client जो भेजता है, वह आपके टर्मिनल पर कुछ नहीं लिख सकता: WAF अपना journal printable ASCII में लिखता है।

WAF क्या नहीं करता

  • TLS नहीं। यह अपने पोर्ट पर सादा HTTP/1.1 बोलता है।
  • HTTP/2 नहीं: इसके जवाब में यह 400 देता है।
  • WebSocket नहीं, और न कोई दूसरा Upgrade: 501।
  • Body के अंदर नहीं देखता। Body मापी जाती है, कभी पढ़ी नहीं जाती। Probe की सूची छोटी है और एक noise filter है, कोई गारंटी नहीं: app अब भी अपना input खुद जाँचता है।
  • Authentication नहीं। App को कौन call कर सकता है, यह app को तय करना है, और फ़ायरवॉल की सूची को।
  • एक address, एक client है। एक ही NAT, प्रॉक्सी या CDN के पीछे के clients एक rate और एक ban साझा करते हैं; कई addresses वाले client के पास उतने ही rates होते हैं।
  • Bans और गिनतियाँ भुला दी जाती हैं जब WAF restart होता है।
  • यह अधिकतम 8192 addresses याद रखता है और एक साथ अधिकतम 1024 कनेक्शन रखता है।
  • यह सिर्फ़ IPv4 पर सुनता है, इसलिए app_allow में IPv6 एंट्री अभी किसी चीज़ तक नहीं पहुँचती।
  • Path की तुलना उन bytes के रूप में होती है जिनमें वह decode होता है। जो app paths को ज़्यादा ढीले ढंग से पढ़ता है (case को अनदेखा करना, ; parameters, दो बार decode करना), उस तक ऐसे नाम से पहुँचा जा सकता है जिसे deny_paths कवर नहीं करता। allow_paths में ऐसी कोई कमी नहीं है: जो सूची में नहीं है, वह आगे नहीं भेजा जाता।
  • धीमे पढ़ने वाले को अंत तक serve किया जाता है। जो client जवाब लेता रहता है, चाहे कितना भी धीरे, उसे अंत तक serve किया जाता है।
  • Requests की बाढ़ किसी बड़े upload को काट सकती है। WAF एक thread पर चलता है, इसलिए बाढ़ किसी बड़े upload को 408 के साथ काट सकती है। जो app बड़ी bodies लेता है, वह max_body_bytes के साथ body_timeout_secs भी बढ़ाता है।
Worker गाइड में हर नियम है, यह भी कि app_allow में कोई बदलाव अगले deploy तक कब रोका जाता है।