האינטרנט צומח בקצב עצום. יותר ויותר אפליקציות אינטרנט הן דינמיות, סוחפות ואינן מחייבות את רענון משתמש הקצה. ישנה תמיכה מתפתחת בטכנולוגיות תקשורת עם זמן אחזור נמוך כמו שקעי רשת. שקעי רשת מאפשרים לנו להשיג תקשורת בזמן אמת בין לקוחות שונים המחוברים לשרת.
הרבה אנשים אינם מודעים כיצד לאבטח את ארובות הרשת שלהם מפני התקפות נפוצות מאוד. תן לנו לראות מה הם ומה עליך לעשות כדי להגן על ארובות האינטרנט שלך.
# 0: הפעל CORS
WebSocket אינו מגיע עם CORS מובנה. עם זאת, פירוש הדבר שכל אתר יכול להתחבר לחיבור אינטרנט אחר של אתר אחר ולתקשר ללא כל הגבלה! אני לא נכנס לסיבות שבגללן זה ככה, אבל תיקון מהיר לכך הוא אימות Origin
כותרת על לחיצת היד של רשת האינטרנט.
בטח, כותרת מקור יכולה להיות מזויפת על ידי תוקף, אבל זה לא משנה, כי כדי לנצל אותה, התוקף צריך לזייף את כותרת המקור בדפדפן של הקורבן, ודפדפנים מודרניים אינם מאפשרים לשבת ב- JavaScript רגיל בדפדפני האינטרנט כדי לשנות את כותרת המקור. .
יתר על כן, אם אתה באמת מאמת משתמשים המשתמשים, עדיף, בעוגיות, אז זה לא באמת בעיה עבורך (עוד על כך בנקודה 4)
מס '1: הגבלת קצב יישום
הגבלת שיעורים חשובה. בלי זה, לקוחות יכולים ביודעין או שלא ביודעין להתקין DoS בשרת שלך. DoS מייצג את מניעת השירות. משמעות DoS היא שלקוח יחיד מעסיק את השרת כל כך עד שהשרת אינו מסוגל להתמודד עם לקוחות אחרים.
ברוב המקרים מדובר בניסיון מכוון של תוקף להפיל שרת. לפעמים יישומי לקוי חזיתיים יכולים גם להוביל ל- DoS על ידי לקוחות רגילים.
אנו נעשה שימוש באלגוריתם הדלי דולף (שהוא ככל הנראה אלגוריתם נפוץ מאוד ליישומי רשתות) לצורך יישום הגבלת קצב על ארובות האינטרנט שלנו.
הרעיון הוא שיש לך דלי שעל הרצפה שלו יש חור בגודל קבוע. אתה מתחיל לשים בו מים והמים יוצאים דרך החור בתחתית. כעת, אם קצב הכנסת המים לדלי גדול יותר מקצב הזרימה מהחור במשך זמן רב, בשלב מסוים, הדלי יתמלא ויתחיל לדלוף. זה הכל.
בואו עכשיו להבין איך זה קשור לשקע האינטרנט שלנו:
- מים הם תעבורת רשת האינטרנט שנשלחה על ידי המשתמש.
- מים עוברים במורד החור. המשמעות היא שהשרת עיבד בהצלחה את בקשת שקע הרשת הספציפית.
- מים שנמצאים עדיין בדלי ולא עלו על גדותיהם ממתינים בעצם לתנועה. השרת יעבד את התעבורה הזו בהמשך. זה יכול להיות גם זרימת תנועה עמוסה (כלומר יותר מדי תנועה לזמן קטן מאוד זה בסדר כל עוד הדלי לא דולף)
- מים שעולים על גדותיהם הם התנועה שנזרקת על ידי השרת (יותר מדי תנועה שמגיעה ממשתמש יחיד)
העניין כאן הוא שעליך לבדוק את פעילות שקע האינטרנט שלך ולקבוע את המספרים האלה. אתה מקצה דלי לכל משתמש. אנו מחליטים כמה הדלי צריך להיות גדול (תנועה שמשתמש יחיד יכול לשלוח על פני תקופה קבועה) תלוי כמה גדול החור שלך (כמה זמן בממוצע השרת שלך זקוק לעיבוד בקשת שקע אינטרנט יחיד, נגיד שמירת הודעה שנשלחה על ידי משתמש למסד נתונים).
זהו יישום מסודר בו אני משתמש ב- codedamn ליישום אלגוריתם דלי דולף עבור שקעי הרשת. זה נמצא ב- NodeJS אבל הרעיון נשאר זהה.
if(this.limitCounter >= Socket.limit) { if(this.burstCounter >= Socket.burst) { return 'Bucket is leaking' } ++this.burstCounter return setTimeout(() => { this.verify(callingMethod, ...args) setTimeout(_ => --this.burstCounter, Socket.burstTime) }, Socket.burstDelay) } ++this.limitCounter
אז מה קורה כאן? בעיקרון, אם חוצים את הגבול כמו גם את מגבלת הפיצוץ (שהם קבועים קבועים), חיבור שקע הרשת יורד. אחרת, לאחר עיכוב מסוים, אנו נאפס את מונה הפרץ. זה משאיר מקום שוב להתפרצות נוספת.
מס '2: הגבל את גודל המטען
יש ליישם זאת כתכונה בספריית שקעי הרשת שלך בצד השרת. אם לא, הגיע הזמן לשנות את זה לטוב יותר! עליך להגביל את אורך ההודעה המרבי שניתן לשלוח דרך שקע האינטרנט שלך. תיאורטית אין גבול. כמובן שקבלת מטען עצום עשויה מאוד לתלות את מופע השקע המסוים ולאכול יותר משאבי מערכת מהנדרש.
לדוגמה, אם אתה משתמש בספריית WS עבור Node ליצירת שקעי רשת בשרת, תוכל להשתמש באפשרות maxPayload כדי לציין את גודל המטען המקסימלי בתים. אם גודל המטען גדול מזה, הספרייה תפיל את החיבור באופן מקורי.
אל תנסה ליישם זאת בעצמך על ידי קביעת אורך המסר. איננו רוצים לקרוא תחילה את כל ההודעה בזיכרון המערכת. אם זה אפילו בת אחד גדול מהמגבלה שנקבעה, שחרר אותו. זה יכול להיות מיושם רק על ידי הספרייה (המטפלת בהודעות כזרם בתים ולא כמחרוזות קבועות).
מס '3: צור פרוטוקול תקשורת איתן
מכיוון שעכשיו אתה נמצא בחיבור דופלקס, אתה יכול לשלוח כל דבר לשרת. השרת יכול לשלוח כל טקסט בחזרה ללקוח. יהיה עליך להיות דרך לתקשורת יעילה בין שניהם.
אינך יכול לשלוח הודעות גולמיות אם ברצונך להגדיל את היבט המסרים באתר שלך. אני מעדיף להשתמש ב- JSON, אך ישנן דרכים אחרות המותאמות להגדרת תקשורת. עם זאת, בהתחשב ב- JSON, הנה איך תיראה סכימת מסרים בסיסית עבור אתר כללי:
Client to Server (or vice versa): status: "ok"
עכשיו יותר קל לך בשרת לבדוק אם יש אירועים ותבנית חוקיים. שחרר את החיבור מיד ונתן את כתובת ה- IP של המשתמש אם פורמט ההודעה שונה. אין שום סיכוי שהפורמט ישתנה אלא אם מישהו עקצוץ ידני בחיבור שקע האינטרנט שלך. אם אתה נמצא בצומת, אני ממליץ להשתמש בספריית Joi לצורך אימות נוסף של נתונים נכנסים מהמשתמש.
מס '4: אמת משתמשים לפני יצירת חיבור WS
אם אתה משתמש בשקעי רשת למשתמשים מאומתים, זה רעיון די טוב לאפשר למשתמשים מאומתים ליצור חיבור שקע אינטרנט מוצלח בלבד. אל תאפשר לאף אחד ליצור חיבור ואז להמתין לאימותו באמצעות רשת האינטרנט עצמה. קודם כל, יצירת חיבור לשקע רשת היא בכל מקרה קצת יקרה. אז אתה לא רוצה שאנשים לא מורשים יקפצו על ארובות האינטרנט שלך ויחברו קשרים שיכולים לשמש אנשים אחרים.
לשם כך, כאשר אתה יוצר חיבור בממשק הקדמי, העביר נתוני אימות לשקע הרשת. זה יכול להיות כותרת כמו X-Auth-Token:. כברירת מחדל, עוגיות יועברו בכל מקרה.
שוב, זה באמת מסתכם בספריה שבה אתה משתמש בשרת ליישום שקעי רשת. אבל אם אתה נמצא בצומת ומשתמש ב- WS, יש פונקציית VerifiedClient זו המאפשרת לך גישה לאובייקט מידע המועבר לחיבור שקע רשת. (בדיוק כמו שיש לך גישה לאובייקט req לבקשות HTTP).
מס '5: השתמש ב- SSL דרך שקעי רשת
זה לא מעניין, אך עדיין צריך לומר זאת. השתמש ב- wss: // במקום ב- ws: //. זה מוסיף שכבת אבטחה על פני התקשורת שלך. השתמש בשרת כמו Nginx לשקעי רשת מקושרים לאחור ולהפעיל SSL עליהם. הגדרת Nginx תהיה הדרכה אחרת לגמרי. אני אשאיר את ההנחיה שאתה צריך להשתמש ב- Nginx לאנשים שמכירים אותה. מידע נוסף כאן.
location /your-websocket-location/ { proxy_pass //127.0.0.1:1337; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; }
כאן ההנחה היא ששרת שקעי הרשת שלך מאזין ליציאה 1337 והמשתמשים שלך מתחברים לשקע הרשת שלך בצורה כזו:
const ws = new WebSocket('wss://yoursite.com/your-websocket-location')
שאלות?
יש לך שאלות או הצעות? שאל!