Cloudflare-ന്റെ ബോട്ട്-ചലഞ്ച് സിസ്റ്റം സാധാരണ HTML ഫോം സബ്മിഷനുകളെ നിശബ്ദമായി തടയാൻ സാധ്യതയുണ്ട്, ഇത് ഒരു ലളിതമായ പേയ്മെന്റ് ക്ലിക്കിനെ യഥാർത്ഥ ഉപയോക്താക്കൾക്ക് ഒരു പ്രതിസന്ധിയാക്കി മാറ്റുന്നു. ഒരു നേറ്റീവ് നാവിഗേഷൻ POST-ൽ നിന്ന് fetch-first ഫ്ലോവിലേക്ക് റിക്വസ്റ്റ് മാറ്റുന്നത് സുരക്ഷയെ ബാധിക്കാതെ തന്നെ അനുഭവം മെച്ചപ്പെടുത്തുന്നു.
ഈ പ്രശ്നം എന്തുകൊണ്ട് പ്രധാനമാണ്
ഒരു ഡെവലപ്പർ curl ഉപയോഗിച്ചും ലോക്കൽ സെർവറിലും എല്ലാ ടെസ്റ്റ് സ്യൂട്ടുകളിലും പ്രവർത്തിക്കുന്ന ഒരു പേയ്മെന്റ് ഫോം പുറത്തിറക്കി. എന്നാൽ ഉപഭോക്താവ് Chrome ഉപയോഗിച്ചപ്പോൾ, അതേ ഫോം ആദ്യത്തെ ക്ലിക്കിന് ശേഷം ഒരു സെക്യൂരിറ്റി എററും രണ്ടാമത്തെ ക്ലിക്കിൽ “timeout-or-duplicate” എന്ന സന്ദേശവും കാണിച്ചു. ഈ പരാജയം മൂന്ന് ഹോട്ട്-ഫിക്സ് റിലീസുകൾക്കും ഒരു ദിവസം മുഴുവൻ ഡീബഗ്ഗിംഗിനും കാരണമായി.
മറഞ്ഞിരിക്കുന്ന വശം
ഒരു സാധാരണ HTML <form> എലമെന്റിനെ ആശ്രയിക്കുന്ന ഓപ്പൺ സോഴ്സ് Astro പാക്കേജിലാണ് ഈ ഫോം ഉള്ളത്. ഉപയോക്താവ് Pay ക്ലിക്ക് ചെയ്യുമ്പോൾ, സെർവർ Stripe-ലേക്ക് ഒരു 303 റീഡയറക്റ്റ് നൽകുന്നു, ബ്രൗസർ യാതൊരു JavaScript-ഉം ഇല്ലാതെ തന്നെ ആ റീഡയറക്റ്റ് പിന്തുടരുന്നു. സ്ക്രിപ്റ്റുകൾ ഡിസേബിൾ ചെയ്യപ്പെട്ടാൽ ഒരു ബദൽ മാർഗമായി സൈറ്റുകൾ ഈ രീതി ഉപയോഗിക്കുന്നു.
സൈറ്റിന് മുന്നിലായി Cloudflare ഒരു ബോട്ട്-ഡിറ്റക്ഷൻ എൻജിൻ പ്രവർത്തിപ്പിക്കുന്നുണ്ട്. സാധാരണ GET റിക്വസ്റ്റുകൾക്കായി ഇതിന് ഒരു ഇന്റർസ്റ്റീഷ്യൽ ചലഞ്ച് (ഒരു CAPTCHA അല്ലെങ്കിൽ JavaScript ചെക്ക്) കാണിക്കാൻ കഴിയും. ബ്രൗസർ ആ ചലഞ്ച് പാസാക്കിയ ശേഷം റിക്വസ്റ്റ് മുന്നോട്ട് പോകുന്നു.
എന്നാൽ, ഒരു നാവിഗേഷൻ POST-നെ ചലഞ്ചിനായി തടഞ്ഞുവെക്കാനോ അതിന്റെ ബോഡി (body) നഷ്ടപ്പെടാതെ പുനരാരംഭിക്കാനോ കഴിയില്ല. എഡ്ജ് (edge) ആ റിക്വസ്റ്റ് തള്ളിക്കളയുകയും 503 സ്റ്റാറ്റസ് നൽകുകയും ചെയ്യുന്നു, ഇത് ബ്രൗസറിൽ ഒരു ശൂന്യമായ പേജോ അല്ലെങ്കിൽ ഒരു ജനറിക് എററോ അവശേഷിപ്പിക്കുന്നു. Cloudflare വിശ്വസിക്കുന്ന അതേ ഫിംഗർപ്രിന്റ് ഉള്ള ഓട്ടോമേറ്റഡ് ടെസ്റ്റ് ബ്രൗസറുകൾ ഈ ചലഞ്ച് ട്രിഗർ ചെയ്യില്ല, അതിനാൽ യഥാർത്ഥ ഉപയോക്താവ് സൈറ്റ് സന്ദർശിക്കുന്നത് വരെ ഈ പ്രശ്നം ശ്രദ്ധിക്കപ്പെടാതെ പോകുന്നു.
ലോഗുകൾ വെളിപ്പെടുത്തിയത്
ഒരു ഉപയോക്താവിന്റെ Chrome സെഷനിൽ നിന്നുള്ള ലൈവ് നെറ്റ്വർക്ക് ട്രേസ് ഒരേ എൻഡ്പോയിന്റിലേക്ക് രണ്ട് വ്യത്യസ്ത റിക്വസ്റ്റുകൾ കാണിച്ചു:
- Navigation POST → 503 റെസ്പോൺസ്, ടാബ് ഹാങ്ങ് ആയി.
- fetch() POST → റിക്വസ്റ്റ് പൂർത്തിയായി.
രണ്ട് റിക്വസ്റ്റുകളും ഒരേ ഒറിജിനിൽ നിന്നാണ് വന്നത്, ഒരേ ക്രെഡൻഷ്യലുകൾ ഉപയോഗിച്ചു, ഒരേ സമയത്താണ് നടന്നത്. അവ തമ്മിലുള്ള ഏക വ്യത്യാസം ട്രാൻസ്പോർട്ട് രീതി (transport method) മാത്രമായിരുന്നു. fetch റിക്വസ്റ്റ് നാവിഗേഷൻ POST-കളെ തടയുന്ന ഇന്റർസ്റ്റീഷ്യൽ ഫ്ലോയെ മറികടന്നു.
ഫലമില്ലാത്ത ശ്രമങ്ങൾ
ഡെവലപ്പർ യഥാർത്ഥ കാരണം കണ്ടെത്താതെ തന്നെ പല പരിഹാരങ്ങളും പരീക്ഷിച്ചു:
- Turnstile ടോക്കണുകൾ കാലാവധി കഴിഞ്ഞതാണെന്ന് കരുതി അവ പുതുക്കി.
- ബ്ലോക്ക് ചെയ്യുന്നത് ലൊക്കേഷൻ അടിസ്ഥാനത്തിലാണെന്ന് കരുതി IP റേഞ്ചുകൾ വൈറ്റ്ലിസ്റ്റ് ചെയ്തു.
- എക്സ്റ്റൻഷനുകൾ ഡിസേബിൾ ചെയ്തു, സർവീസ് വർക്കറുകൾ ക്ലിയർ ചെയ്തു, കുക്കികൾ ഡിലീറ്റ് ചെയ്തു.
ഓരോ മാറ്റവും പിഴവ് മാറ്റുന്നതിൽ പരാജയപ്പെട്ടു, കാരണം പരാജയം ക്ലയന്റിലോ സെർവർ കോഡിലോ അല്ല, മറിച്ച് എഡ്ജിൽ (edge) ആണ് സംഭവിച്ചിരുന്നത്.
പ്രായോഗികമായ പരിഹാരം
Cloudflare-ന്റെ സംരക്ഷണം ഓഫ് ചെയ്യുന്നതിന് പകരം, ഫോം ഒരു fetch-first പാറ്റേൺ ഉപയോഗിക്കുന്ന രീതിയിൽ പുനർനിർമ്മിച്ചു:
- ഫോം ഡാറ്റ ശേഖരിക്കുക, അത്
fetch()ഉപയോഗിച്ച് ഒരു JSON പേലോഡ് ആയി അയക്കുക. - സെർവറിന്റെ റെസ്പോൺസ് കൈകാര്യം ചെയ്യുക. സെർവർ പേയ്മെന്റ് ഗേറ്റ്വേയ്ക്കായി ഒരു URL നൽകുന്നുണ്ടെങ്കിൽ, ഒരു ലളിതമായ GET റിക്വസ്റ്റ് ഉപയോഗിച്ച് അവിടെ എത്താൻ
location.assign()ഉപയോഗിക്കുക.
Fetch റിക്വസ്റ്റുകൾ ഇന്റർസ്റ്റീഷ്യൽ ചലഞ്ച് ട്രിഗർ ചെയ്യില്ല, അതിനാൽ POST റിക്വസ്റ്റ് ഒറിജിൻ സെർവറിൽ എത്തുന്നു. തുടർന്നുള്ള GET റീഡയറക്റ്റിന് സുരക്ഷിതമായി ചലഞ്ചുകൾ കടന്നുപോകാൻ കഴിയും, കാരണം GET ബോഡികൾ ശൂന്യമാണ്, ഉപയോക്താവ് ചലഞ്ച് പൂർത്തിയാക്കിയ ശേഷം അവ വീണ്ടും ഉപയോഗിക്കാം.
ഡെവലപ്പർമാർ നേരിടുന്ന വെല്ലുവിളികൾ
- ഉപയോക്താക്കളുടെ വിശ്വാസം: നിശബ്ദമായി പരാജയപ്പെടുന്ന ഒരു പേയ്മെന്റ് ഫോം വിശ്വാസം നഷ്ടപ്പെടുത്തുകയും വരുമാന നഷ്ടത്തിന് കാരണമാവുകയും ചെയ്യും.
- മെയിന്റനൻസ് ഭാരം: ഈ സംഭവം മൂന്ന് പാച്ച് റിലീസുകൾക്കും ഒരു ദിവസം മുഴുവൻ അന്വേഷണത്തിനും കാരണമായി.
- ടെസ്റ്റിംഗിലെ പോരായ്മകൾ: ആന്തരിക ടെസ്റ്റ് എൻവയോൺമെന്റുകളെ മാത്രം ആശ്രയിക്കുന്നത് യഥാർത്ഥ ലോകത്ത് മാത്രം കാണുന്ന പ്രശ്നങ്ങൾ തിരിച്ചറിയാതിരിക്കാൻ കാരണമായേക്കാം.
കമ്മ്യൂണിറ്റിക്ക് നൽകുന്ന പാഠങ്ങൾ
- യഥാർത്ഥ ബ്രൗസറുകൾ ഉപയോഗിക്കുക. ഒരു പ്രശ്നം യഥാർത്ഥ ഉപയോക്താക്കൾക്ക് മാത്രമാണ് സംഭവിക്കുന്നതെങ്കിൽ, ഓട്ടോമേറ്റഡ് ടെസ്റ്റുകളെ മാത്രം വിശ്വസിക്കാതെ ആ സെഷനുകളിൽ നിന്നുള്ള നെറ്റ്വർക്ക് ലോഗുകൾ ശേഖരിക്കുക.
- എഡ്ജിനെ സ്റ്റാക്കിന്റെ ഭാഗമായി കാണുക. ക്ലയന്റും സെർവറും ഇടയിൽ Cloudflare ഇരിക്കുന്നു; അതിന്റെ പ്രവർത്തനം റിക്വസ്റ്റുകൾ എങ്ങനെ സ്ട്രക്ചർ ചെയ്യണം എന്നതിനെ സ്വാധീനിക്കുന്നു.
- ശരിയായ ട്രാൻസ്പോർട്ട് രീതി തിരഞ്ഞെടുക്കുക. നാവിഗേഷൻ POST-കളും fetch POST-കളും എഡ്ജിൽ വ്യത്യസ്ത പാതകളിലൂടെയാണ് സഞ്ചരിക്കുന്നത്. ആ വ്യത്യാസം മനസ്സിലാക്കി API രൂപകൽപ്പന ചെയ്യുക.
- എറർ വിവരങ്ങൾ വ്യക്തമാക്കുക. ഡെവലപ്പർമാർക്ക് ലോഗുകൾ പരിശോധിക്കാതെ തന്നെ കൃത്യമായ പരാജയം മനസ്സിലാക്കാൻ 503 അല്ലെങ്കിൽ “timeout-or-duplicate” സന്ദേശങ്ങൾ UI-ൽ കാണിക്കുക.
ശ്രദ്ധിക്കേണ്ട കാര്യങ്ങൾ
ഡെവലപ്പർമാർ നാറ്റീവ് POST നാവിഗേഷനെ ആശ്രയിക്കുന്ന ഫോം അധിഷ്ഠിത വർക്ക്ഫ്ലോകൾ പരിശോധിക്കണം, പ്രത്യേകിച്ച് Cloudflare അല്ലെങ്കിൽ സമാനമായ CDN സുരക്ഷാ സേവനങ്ങൾ സൈറ്റിന് മുന്നിലുണ്ടെങ്കിൽ. ഒരു ലഘുവായ fetch wrapper ചേർക്കുന്നത് ഇത്തരം പരാജയങ്ങൾ ഒഴിവാക്കാൻ സഹായിക്കും. എഡ്ജിൽ നിന്ന് ഉണ്ടാകുന്ന സ്റ്റാറ്റസ് കോഡുകൾ നിരീക്ഷിക്കുന്ന ടൂളുകൾ, പ്രശ്നം ഉപഭോക്താക്കളിൽ എത്തുന്നതിന് മുമ്പ് തന്നെ അത് തിരിച്ചറിയാൻ സഹായിക്കും.
പ്രധാന പാഠം: Cloudflare-ന്റെ ബോട്ട് ചലഞ്ചുകൾ (bot challenges) സജീവമായിരിക്കുമ്പോൾ, സാധാരണ രീതിയിലുള്ള HTML ഫോം സബ്മിഷനുകൾ നിശബ്ദമായ പരാജയത്തിന് (silent failure) സാധ്യതയുണ്ട്. fetch() ഉപയോഗിച്ച് POST റീ-റൂട്ട് ചെയ്യുകയും ഒരു GET റീഡയറക്റ്റിലൂടെ പ്രക്രിയ പൂർത്തിയാക്കുകയും ചെയ്യുന്നത് സുരക്ഷാ ക്രമീകരണങ്ങൾ നിലനിർത്തിക്കൊണ്ടുതന്നെ എഡ്ജിന്റെ (edge) പരിമിതികളെ മറികടക്കാൻ സഹായിക്കുന്നു. എഡ്ജിനെ വെറുമൊരു നെറ്റ്വർക്ക് ഹോപ്പ് (network hop) ആയിട്ടല്ല, മറിച്ച് കോഡ് ആയിട്ടാണ് കാണേണ്ടത്; അതനുസരിച്ച് നിങ്ങളുടെ ട്രാൻസ്പോർട്ടുകൾ രൂപകൽപ്പന ചെയ്യുക.
