תוכנית ביניים לשרת שחוסמת סורקי מזויפים לפני שהם מגיעים לאפליקציה שלך
קו סדרתי של בקשות באפליקציה ווב הוא דבר אלגנטי. בקשה מגיעה לשרת האינטרנט, עוברת דרך ערימה של תוכניות ביניים, מגיעה לכמות משלבת, והחוזרת תגובה. לכל תוכנית ביניים בערימה יש הזדמנות לבחון את הבקשה, לשנות אותה, להעביר אותה הלאה, או לדחות אותה לחלוטין. הארכיטקטורה הזו מושלמת ליישום זיהוי בוטים מכיוון שהאימות מתרחש לפני שהבקשה משפיעה על כל היגיון היישום. סורק מזויף הטוען שהוא Googlebot מזוהה ונחסם בשכבת התוכנית הביניים, והבקרה לא אפילו יודעת שהבקשה קיימת. שום מחזור CPU לא נשמר לרינדור של עמוד. אין שאילתות מסד נתונים בעדכון. אין ערכי זיכרון מזהה. הבוט המזויף עוצר בדלת, והשרת משאבים שהיו צורכים בהם שמורים למבקרים לגיטימיים.
הנסיון לבנות תוכנית ביניים זו הגיע מבעיה קונקרטית ויקרה. יישום גדול היה צורך בפס רחב ומשאבי שרת בשערים שלא היו קשורים לבסיס המשתמשים בפועל שלו. ביומן הגישה הוצגו כמויות거대e של בקשות מסוכנים משתמשים הטוענים להיות Googlebot, Bingbot וסורקים לגיטימיים אחרים שונים. החקירה אישרה שרוב אלה היו מזויפים, מקורם בספקי אחסון ענן ולא במנועי חיפוש שהם טוענים להם. כל בקשה מזויפת צרכה משאבי שרת זהים כמו בקשה אמתית: זמן הרצה PHP זהה, שאילתות מסד נתונים זהות, הקצאת זיכרון זהה, רוחב פס זהה לתגובה. כפול בחלוף אלפי בקשות מזויפות לשעה, העלות הייתה משמעותית. פתרון התוכנית הביניים תוכנן לחסל בזבוז זה בתפיסת סורקים מזויפים לפני שהם צרכו משאבי יישום כלשהם.
היישום עוקב אחרי דפוס פשוט שכל מפתח backend יכול להסתגל אליו. התוכנית הביניים מיירטת כל בקשה נכנסת, בודקת אם מחרוזת סוכן המשתמש תואמת דפוס סורק מנוע חיפוש ידוע, ואם כן, מאמתת את כתובת ה-IP של הבקשה כנגד התשתית הידועה של הסורק באמצעות ממשק API לזיהוי בוטים. בקשות שטוענות להיות סורקים אך נכשלות באימות נחסמות עם תגובת 403. בקשות שעוברות אימות, או שלא טוענות להיות סורקים בכלל, ממשיכות דרך ערימת התוכנית הביניים בכלל. הבדיקה כולה מוסיפה זיכרון מינימלי מכיוון שתוצאות האימות מטומנות לפי כתובת IP, כלומר כל IP ייחודי מאומת רק פעם אחת.
היגיון ההחלטה מאחורי חסימה בשכבת התוכנית הביניים
בחירה לחסום בשכבת התוכנית הביניים ולא ברמת שרת האינטרנט (Nginx או Apache) או ברמת היישום (בתוך בקרים) היא החלטה ארכיטקטוניית חשובה עם פשרות ספציפיות. חסימה ברמת שרת האינטרנט היא האפשרות היעילה ביותר מבחינת צריכת משאבים מכיוון שהבקשה לא מגיעה לפי בכלל. עם זאת, התצורה של שרת אינטרנט לזיהוי בוטים בדרך כלל כרוכה בעוהדות IP סטטיים בעלי קדימות או התאמה פשוטה של סוכן משתמש, אף אחד מהם לא מספק את האימות הדינמי המונע API הדרוש להבחנה מדויקת בין סורקים אמתיים לחלק מהם. השמירה על עוהדות סטטי של מיליוני כתובות IP היא בלתי אפשרית, והתאמת סוכן משתמש בלבד לא יכולה לאמת זהות מכיוון שסוכני משתמשים קלים בזיופים.
חסימה ברמת היישום, בתוך בקרים או שיעורי שירות, היא האפשרות הגמישה ביותר אך הפחות יעילה. כשהבקשה מגיעה לבקרה, ערימת התוכנית הביניים כבר בוצעה, הנתיב נפתר, וכנראה פעולות יקרות כמו התחלה של סת וסימוכין כבר התרחשו. חסימה בנקודה זו חוסכת זמן הרצה של הבקר אך מבזבזת הכל שקרה לפניו. עבור יישומים בתנועה גבוהה כאשר בקשות בוט מזויף מספיקות לאלפים בשעה, כל בזבוז בעיבוד מוקדם מתמצא.
שכבת התוכנית הביניים יושבת בנקודה האופטימלית בקו סדרתי. הוא מבוצע לפני טיפול בסת, לפני סימוכין, לפני תוכנית ביניים ספציפית לנתיב, וכמובן לפני כל היגיון בקר. אך יש לו גישה לאובייקט הבקשה המלא, כולל כתובות ראש, כתובות IP וגדלים שאילתה, כלומר זה יכול לבצע היגיון אימות מתוחכם למעט התאמה פשוטה של דפוס. התוכנית הביניים יכולה לקרוא ל-API חיצוני, תוצאות מטומנות, יישומים היגיון מתוך הטענה זהות, וניסיון אימות עבור ניתוח. שילוב זה של יעילות וגמישות עושה את התוכנית הביניים הבית הטבעי לזיהוי בוטים באפליקציה ווב.
אסטרטגיית הזיכרון חשובה במיוחד לביצועים. בלא זיכרון, כל בקשה מסורק טוען יידרוש שיחת API לאימות כתובת ה-IP. אפילו עם ממשק API מהיר, זה היה מוסיף זמן השהיה לכל בקשה. הפתרון הוא לזיכרון תוצאות אימות בחזקת כתובת IP, עם זמן קיום של מספר שעות או אפילו יום שלם. סורקי מנוע חיפוש פועלים מטווחי IP יציבים המשתנים בתדירות נמוכה, לכן תוצאת אימות מטומנה נשארת תקפה למשך זמן מורחב. כשבקשה מגיעה מ-Googlebot טוען, התוכנית הביניים תחילה בודקת את הזיכרון. אם ה-IP אומת כלגיטימי בתקופת הזיכרון, הבקשה מעברת הלאה מיד. אם ה-IP אומת כמזויף, הוא חסום מיד. רק כתובות IP במצב ראשון דורשות שיחת API בפועל, ואחרי זה קריאה ראשונית, התוצאה מועברת מזיכרון בעלות זמן השהיה זניחה.
מה קורה לבקשות שנחסמו
חסימת סורק מזויף היא לא פשוט חזרה של תגובת 403 והמשך הלאה. החלטת חסימה וההקשר שלה צריכים להיות מתועדים לניתוח. כל בקשה חסומה מהווה נקודת נתונים אודות מי מנסה לגשת לאתר, מה הם מתיימרים להיות, ומאיפה הם מגיעים. לאורך זמן, עיתון זה חושף דפוסים שמעבירים החלטות אבטחה רחבות יותר. אולי ASN ספציפי אחראי לנתח לא פרופורציונלי של סורקים מזויפים. אולי בקשות Googlebot מזויפות זינקות בשעות מסוימות ביום. אולי נתיב URL מסוים משכך בוטים מזויפים יותר מאחרים, מה שמציע שבוטים מכוונים תוכן ספציפי.
התגובה לבקשה חסומה יכולה להיות גם יותר מגוונת מ-403 בחוקה. כמה יישומים חוזרים 429 (בקשות רבות מדי) כדי להסתיר את העובדה שהבוט זוהה, מה שמקשה על מפעיל הבוט להסתגל לגישה שלו. אחרים חוזרים ל-200 עם תוך ריק, זה מבזבז רוחב פס מינימלי תוך שמנעו לבוט לדעת שהוא זוהה. גישות אגרסיביות יותר חוזרות 403 עם הודעה המעידה שאימות סורק נכשל, מה שהוא שקוף אך נותן למפעילי בוט מידע על מנגנון הגילוי. הבחירה תלויה בפילוסופיה של מפעיל האתר על שקיפות מול אבטחה פעולה.
עבור בוטים הטוענים להיות סורקים אך הם למעשה שירותים לגיטימיים ש במקרה להשתמש בסוכני חיפוש כמו סוכני משתמשים בצורה שגויה, החסימה יכולה להיות הרבה יותר שיבשה מאשר בכוונה. כמה כלים של ניטור SEO, למשל, משתמשים בסוכני משתמשים דומים ל-Googlebot כדי לדמות כיצד גוגל רואה עמוד. כלים אלה ייכשלו אימות מכיוון שהם אינם גוגל, גם כי מטרתם היא לגיטימית מנקודת המבט של מפעיל אתר. התוכנית הביניים יכולה להתאים זאת על ידי שמירה על רשימה לבנה של טווחי IP עבור שירותים של צד שלישי ידועים, או על ידי יישום אימות רק לדפוסי סוכן משתמש ספציפיים תוך התעלמות מאחרים. הגמישות של הגישה התוכנית הביניים מאפשרת סוג זה של מדיניות מדויקת ללא הצורך בשינויים בתצורת שרת האינטרנט או קוד היישום.
אימות סינכרוני מול אסינכרוני
השאלה של אם לאמת בוטים באופן סינכרוני או אסינכרוני משפיעה על יעילות החסימה וגם על השפעת הביצועים באפליקציה. אימות סינכרוני פירושו התוכנית הביניים מעצרת את הבקשה, קוראת ל-API אימות, מחכה לתגובה, ולאחר מכן מאפשרת או חוסמת את הבקשה על סמך התוצאה. הגישה זו מספקת חסימה מידית אך מוסיפה זמן השהיה לבקשה הראשונה מכל כתובת IP. עם זיכרון, זמן ההשהיה משפיע רק על הבקשה הראשונה, אך עבור יישומים בתנועה גבוהה גם בת遅延 כלשהו מאי-קבילה.
אימות אסינכרוני לוקח גישה שונה. הבקשה הראשונה מ-IP חדש מעברת הלאה בזמן שעבודת אימות בתור ברקע. כשתוצאת האימות חוזרת, היא מטומנת, וכל בקשות עוקבות מ-IP זה מטופלות על פי התוצאה. הגישה זו מוסיפה זמן השהיה אפס לצינור הבקשה אך מאפשרת מספר בקשות התחלתיות מבוטים מזויפים לעבור לפני שהאימות יושלם. עבור רוב היישומים, פשרה זו קבילה. בוט מזויף ששיגר שלוש בקשות לפני שנחסם צרך משאבים הרבה פחות מאחד ששיגר אלפים בקשות ללא עיכוב.
מערכת התור הופכת את הגישה האסינכרונית לפשוטה. התוכנית הביניים משדרת עבודת אימות שקוראת ל-ממשק API לזיהוי בוטים, מאחסנת את התוצאה בזיכרון, ובאופן אחיד משיקה אירוע שחלקים אחרים באפליקציה יכולים להאזין אליו. העבודה רץ בשניות, מה שפירושו החלון שבו תנועת בוט לא מנוהלת יכולה לעבור היא מאוד צרה. עבור יישומים המשתמשים בזיכרון מהיר בזיכרון, התוצאה המטומנת זמינה לכל הופעות הרישום מיד, לכן אפילו בסביבה עמוסה בעומס, האימות צריך להתרחש רק פעם אחת לכל כתובת IP בכל השרתים.
גישה היברידית משלבת את הטוב של שניהם. סוכנים בוטים ידועים שתואמים דפוסי בעלי ביטחון גבוה יזוממו סינכרוני אימות עם תוצאות מטומנות, מוסיף זמן השהיה מינימלי. דפוסים בעלי ביטחון נמוך יותר יזוממו אסינכרוני אימות, תוך כדי אפשור הבקשה הראשונה דרך בזמן שאימות רץ ברקע. הגישה המדורגת זו משפרת את המקרה הרגיל תוך טיפול מקרים צדדיים בחן. מעמדו של התוכנית הביניים בצינור הבקשה עושה אותו מקום אידיאלי ליישום היגיון זה, מכיוון שיש לו גישה לכל המידע הדרוש כדי לבצע החלטת ניתוב וביצוע לפני כל היגיון היישום יקר.
ההשפעה הניתנת למדידה של חסימה בדלת
התוצאות של יישום תוכנית ביניים גילוי בוטים גלויות כמעט מיד במדדי שרת. השינוי הדרמטי ביותר הוא בצריכת רוחב פס. סורקים מזויפים מבקשים דפי HTML שלמות, כולל כל הנכסים המסוגלים בתגובה. כל בקשה חסומה חוסכת את רוחב הפס שהיה משמש להעברת התגובה המלאה, אשר לדפים כבדי תוכן יכולים להיות עשרות או מאות קילו-בתים בכל בקשה. על פני אלפי בקשות חסומות בשעה, חיסכון רוחב הפס מתצבר ל- ירידות הוצאה משמעותיות, בתכנן עבור יישומים מתורגמים בספקים שמחייבים להעברה לגיגה-בתים.
השימוש ב-CPU יורד מכיוון שהשרת לא עוד רץ קוד PHP, שאילתות מסד נתונים, וערכות תבניות עבור בקשות המייצרות ערך. הירידה בולטת ביותר בשעות שיא כאשר תנועת אדם נמוכה אך תנועת בוט נשארת קבועה. לפני יישום התוכנית הביניים, השרת שמר שימוש ממוזער ב-CPU גם בשלוש בבוקר מכיוון שבוטים לא ישנים. לאחר היישום, השימוש שיא נפל ליד אפס, תוך כדי תנאים לשרת חדריים עבור תנועה לגיטימית בזמני עומס.
זמני תגובה עבור מבקרים לגיטימיים משתפרים כתוצאה ישירה של עומס שרת מופחת. שרת ווב הטיפול בחמש מאות בקשות לשנייה, שלוש מאות מהן בוטים מזויפים, יש פחות קיבולת זמינה עבור מאתיים מבקרים אמתיים מאשר שרת הטיפול רק בחמש מאות בקשות לשנייה, כולם לגיטימיים. התוכנית הביניים לא רק חוסכת משאבים על הבקשות החסומות. זה משפר את איכות השירות לכל בקשה שעוברת דרך, מכיוון שהשרת יש קיבולת רבה יותר זמינה לעבודה אמתית.
עומס מסד נתונים יורד פרופורציונלי. אם היישום שואל את מסד הנתונים לכל בקשת דף, חסימה של שלוש מאות בקשות מזויפות לשנייה מחסלת שלוש מאות שאילתות מסד נתונים לא הכרחיות לשנייה. עבור יישומים עם שאילתות מורכבות או חיבורי מסד נתונים מוגבלים, ירידה זו יכולה להיות ההבדל בין תפעול יציב לעומס תקופתי. התוכנית הביניים מגנה על הערימה כולה, משרת האינטרנט דרך שכבת היישום למסד הנתונים, על ידי עצירת תנועה לא רצויה לפניה מגיע כל אחד מהם.
שאלות נפוצות
האם הוספת תוכנית ביניים גילוי בוטים מאטה את האתר למשתמשים אמתיים?
עבור משתמשים אמתיים, התוכנית הביניים מוסיפה תחומי זניח. הוא בודק את מחרוזת סוכן המשתמש כנגד דפוסי סורק, אשר לוקח מיקרו-שניות. רק בקשות הטוענות להיות סורקים יזוממו היגיון אימות, וגם אז, תוצאות מטומנות אומתות שה-API קוראת רק פעם אחת לכל כתובת IP. מבקרים רגילים חווים עלייה בזמן השהיה זניחה.
מה קורה אם ממשק API זיהוי בוטים זמני אינו זמין?
התוכנית הביניים צריכה לכלול אסטרטגיית נפילה. גישה נפוצה היא לאפשר את הבקשה דרך אם ה-API לא זמין, מה שמבטיח שהפסקת שירות אימות לא חוסמת סורקים לגיטימיים. תוצאות מטומנות קודמות ממשיכות לתפקד במהלך הפסקות API, ודפוס מפסק קצר מנע שיחות API כושלות חוזרות מירידת ביצועים.
האם גישת התוכנית הביניים זו יכולה לעבוד עם כל מסגרת ווב?
היגיון הליבה של בדיקת סוכני משתמשים, אימות כתובות IP, וזיכרון תוצאות הוא גישתי לכל מסגרת. דפוס התוכנית הביניים קיים בכל מסגרת ווב גדולה. קריאה ל-API וזיכרון ניתוח יכול להסתגל לכל מסגרת התוכנית הביניים או אירוע מערכת. העיקרון המרכזי זהה ללא קשר לטכנולוגיה: יירוט מוקדם, אימות לפי IP, זיכרון תוצאה.
כיצד אני מטפל בחיובים שליליים כאשר כלי לגיטימי מזוהה בטעות כבוט מזויף?
שמור על רשימה לבנה של טווחי IP עבור כלים לגיטימיים ידועים המשתמשים בסוכני משתמשים דומים לסורק. התוכנית הביניים בודקת את הרשימה הלבנה לפני ביצוע אימות, תוך כדי אפשור שירותים מהימנים לעבור ללא קריאות API. העיתון אימות עוזר לזהות חיובים שליליים על ידי הצגת כתובות IP שנחסמו ומידע ASN שלהם.
האם עלי לחסום בוטים מזויפים עם 403 או קוד סטטוס שונה?
הבחירה תלויה בתכליות שלך. 403 מתקשרת בבירור כי גישה נדחתה. 429 מציע גבלת קצב ללא הסתרת יכולת גילוי. 200 עם גוף ריק נותן לפחות מידע למפעיל הבוט. עבור רוב היישומים, 403 היא הבחירה הישרה והתקנית ביותר.
כמה לעתים קרובות צריך זיכרון אימות IP להיות רענן?
טווחי IP של מנוע חיפוש משתנים בתדירות נמוכה, לכן משכי זיכרון של שתים עשרה עד עשרים וארבע שעות בטוחים עבור רוב היישומים. משכי זיכרון קצרים יותר מגבירים כמות שיחות API אך מספקים נתונים אימות רעננים יותר. עבור רוב האתרים, מטמון של עשרים וארבע שעות משכך היקף זה בין דיוק ויעילות.