-->

יום רביעי, 16 בנובמבר 2016

אז... אתם רוצים Continuous Deployment?

נתקלתי בארגונים שרצו לעשות Continuous Delivery (או Deployment, או אפילו Integration) משום שרצו להידמות לארגונים מצליחים אחרים. הייתה מן מחשבה מעורפלת שאם נעשה את "זה" - דברים יסתדרו טוב יותר, כל זאת ללא התעמקות אמיתית בהבנת התמורות הצפויות ממהלך שכזה.
המחשבה כנראה הולכת כך: "CD זה טוב => אנחנו רוצים להיות טובים יותר => בואו נעשה CD".
(ייתכן, כמובן, והייתה התעמקות - אך פשוט לא נחשפתי אליה.)

Continuous Delivery היא כבר שאיפה סטנדרטית: כמעט כולם רוצים להיות שם. כ"כ הרבה נמצאים "בתהליך...". כרגיל...

בפוסט הזה אני רוצה לחזור ולדבר על הציפיות הסבירות מ CD, על המשמעות, המעבר, וכו׳...






הפשט


בדומיין שאנו מדברים עליו יש 3 פרקטיקות דומיננטיות, שנהוג לפרש אותן בערך כך:
  • Continuous Integration (בקיצור CI) - יש לנו שרת Build עם בדיקות אוטומטיות. כל כמה זמן (לילה?) - כל הבדיקות רצות ואנו מגלים אם יש בעיות בקוד - ואז מתקנים.
  • Continuous Delivery (בקיצור CD) - יש לנו שרת Build אוטומטי, שגם אורז את הקוד ל Delivery. למשל: בונה את ה ISO (אם אנו מפיצים את המערכת על DVD - פחחח) או Docker Image - שניתן להטמיע בפרודקשיין (SaaS או On-Premises).
  • Continuous Deployment (בקיצור גם CD, לצורך הפוסט אשתמש בקיצור CDD) - כמו Continuous Delivery, אבל ההחלטה לשלוח ל Production היא אוטומטית. כל קוד שנכנס למערכת - מגיע ל Production. לכאורה, תוספת קטנה לתהליך.

התיאור הזה הוא נכון בגדול - אך גם שטחי למדי.


נכון, אך פשטני משהו...
מקור: notafactoryanymore.com



מוטיבציה - אז למה לנו CD עכשיו...?


CD אמור לשפר כמה מדדים במערת, הנה העיקריים:
  • צמצום אי-ודאות - היכולת לשחרר קוד מהר יותר, מספקת לנו פידבק מהיר ותדיר יותר מהשטח. ״לפגוע בקרקע בתדירות גבוהה יותר״. (רלוונטי בעיקר ל Continuous Deployment)
  • פישוט תהליכי ה Integration / Deploy - ארגונים רבים נאבקים לסיים גרסאות בזמן, ובאיכות טובה. CD היא דרך לשפר את התהליכים, בכמה צורות.
  • יציבות, או Uptime של המערכת בפרודקשיין.
איזה מדד הכי חשוב? - תלוי בארגון.


אני רוצה להרחיב מעט יותר על המוטיבציות:

צמצום אי-ודאות / סיכון

כשמנהלים פרויקט או מוצר בארגון, תמיד יש לנו חוסר ודאות מסוים: לפעמים הוא בינוני, ולפעמים - גדול.
  • חוסר ודאות מה הלקוחות צריכים -לפעמים הם בעצמם לא יודעים, ופשוט יש לראות כיצד הם משתמשים במוצר.
  • חוסר ודאות לגבי התוצאות של פעולות שנעשות - האם המעבר ל NoSQL DB יספק את ה Scalability הצפוי. האם ה Design החדש של מודול Y יעמוד יפה בשטף הדרישות העתידיות?
  • חוסר ודאות לגבי הבנת תוכנית הפעולה והתיאום בין אנשינו - כאשר האנשים שעובדים איתנו לא מבינים את אותה התוכנית - הם עלולים למשוך לכיוונים מנוגדים.
שווה לציין שהרעיון של Continuous Deployment קיבל תנופה גדולה מתנועת ה Lean Startup, שם צמצום מחזורי הלמידה והפידבק הם ערך מרכזי. הדרישה ל CDD, ע״פ המתודולוגיה, אמורה להגיע כיעד עסקי מה CEO - זה לא עניין ״פנימי״ של ה R&D...

במקום להיות ״נביאים״, או ״יודעי-כל״, תהליך ה CDD מאפשר לנו לנסות בשטח.
הפיצ'ר של אמזון של "אנשים שקנו את X קנו גם את Y", נדחה ע"י אנשי המוצר כ"מטופש" - ובארגון אחר היה נקבר לעד.

התרבות הארגונית של אמזון, שגובתה בעזרת יכולות CDD, אפשרה למפתח שמאוד מאמין במשהו לבצע A/B test (על אוכלוסיה קטנה) - ולנסות להוכיח את צדקתו. כל אחד כמעט - יכול להציע ולהתניע ניסוי.
הניסוי הנ״ל הראה גידול של כ 3% במכירות (נתון מרשים מאוד!) - מה שהסיר מייד כל התנגדות, והפך אותו בן רגע לפיצ׳ר רצוי ע"י הפרודקט.

אם כולם מאמינים במערכת ובנתונים שהיא מייצרת,  אזי נתונים מהשטח הם ״מחסלי ויכוחים ארגוניים״.

CDD, אם כן, בשילוב A/B Tests ותרבות ארגונית מתאימה - מספקת Empowerment לעובדים, ויכולה להביא רעיונות חכמים שלהם - לידי יישום.

מיחסים ל CDD גם שיפור בשביעות הרצון של המפתחים, שכבני-אדם, גם הם צמאים לפידבק מהיר. מה יותר כיף: לפתח פיצ׳ר במשך שנה - ואם לראות אותו עובד (אם בכלל), או לראות שינוי בפרודקשיין כל שבוע-שבועיים? להרגיש את העשייה בצורה מתמשכת?



פישוט תהליכי ה Integration / Deploy

כשהחברה גדלה, תהליכי ה Integration וה Deploy הם לא פעם - כאב ראש רציני!

כמה עבודה אתם משקיעים בהגדרה ושיפור של התהליכים?
בתחקור של גרסאות שהתעכבו או יצאו באיכות לא-מספקת?
במינוי ״אחראים״ ושינוי מנגנונים - על מנת ש ״זאת תהיה הפעם האחרונה שזה קורה״?
 - אם אתם ראשי צוותים או מנהלים בכירים יותר, אתם בוודאי חשופים למאמצים הללו יותר.

כאשר התוצאות מבוששות להגיע, המנהלים לוקחים פיקוד: מגדירים תהליכים, וממנים אחראיים - שלא תמיד בנויים מתוך הבנת הדקויות של המציאות היומיומית, ושלא תמיד יעילות במידה מירבית.

ככל שהמערכת גדולה יותר וסבוכה יותר - כך קשה יותר להגיע לתהליך מוצלח ו"חלק".
תהליכי CD עוזרים לשקף את קצב הפיתוח והבעיות בצורה טובה יותר: במהלך כל יום בספרינט יודעים מה הבעיות שצצו - וניתן לפתור אותן מייד, ולהתאים את התכנון בהתאם. כך ניתן לכוונן את סוף הגרסה עם כמות הקוד האמיתית שניתן להכניס באיכות טובה.

אין כאן קסם:

בתהליכי Integration/Deploy תקופתיים (נאמר: פעם בחודש) - משקיעים המון.
וגם בתהליכי CD - משקיעים המון.

התמורה היא שב CD הסיכויים להגיע לתהליך מוצלח - הם טובים יותר. במיוחד כאשר המערכת שלנו מחולקת למודולים נפרדים (למשל: microservices) ואז ניתן לייצר pipeline נפרד ומותאם לכל חלק במערכת (sub-system).


מקור: http://www.mindtheproduct.com


יציבות

לאחר מעבר מוצלח ל CD/CDD, המערכות נוטות להיות יציבות יותר.
זה לכאורה פרדוקס: שינוי בפרודקשיין הוא סיכון - והנה אנחנו הולכים לעשות הרבה יותר כאלה. במקום שינוי בחודש, אולי כמה שינויים כל יום!
מצד שני, כשהשינויים הם מאוד קטנים - הסיכון מאוד קטן, יכולת האיתור של תקלות משתפר פלאים, וכמו שאומרים: Practice Makes Perfect. הרבה אימון בתהליך מאפשר להשתפר בצורה מהירה יותר.

מודל היציבות של CD הוא MTTR (קרי: Mean Time To Resolve) על פני מודל של MTBF (כלומר: Mean Time between Failures). יהיו לנו יותר תקלות במספר - אך הן יתוקנו מהר, וסה״כ ה downtime שלנו יהיה נמוך יותר.

שאלה מפורסמת ב Lean היא: "כמה עבודה עליכם לעשות בכדי לבצע Deploy של שורת קוד בודדת במערכת?" (כלומר: נזניח את תוכן השינוי, ואז - מהי התקורה על כל deploy של גרסה?). התרגיל הזה ידוע גם כ Single Line of Code DevOps Kata.

בארגונים ללא CD, מדובר בד"כ על כמה ישיבות, עבודה ידנית של ביצוע רגרסיות ומעבר על התוכן, ואף כמה פעולות ידניות של איש Operations שמלווה את ה deploy. כמה שעות עבודה, וכמה דקות של פחד (במקרה הטוב).

אם אתם רוצים לעשות deploy כל יום, זה נראה כחוסר-יעילות, ולכן ה"Best Practice" שהיה מקובל במשך שנים הוא להפחית את מספר ה releases, או לפחות למתן אותו - נאמר, פעם או פעמיים בחודש, ולא יותר.

לא שעות העבודה שמושקעות ב deployment הן המחסום העיקרי - אלא הפחד מתקלות: תקלת Deploy עלולה לגרום להפסדים כספיים ("פגיעה בביזנס"), לעלות עשרות שעות עבודה של מפתחים ,ולגרום לפגיעה במוניטין החברה.

הגישה של CD נקראת: Bring the Pain forward (כמו באג'ייל).
אם זה כואב, עשו את זה בתכיפות רבה יותר - עד שתשתפרו וזה כבר לא יכאב.

בפועל, באימוץ CD אתם הולכים "לשבור דברים" כ"כ הרבה פעמים - כך שתוך כדי אתם צפויים לפתח יכולות Recovery טובות במיוחד ולשפר מאוד את ה MTTR. כמובן שחשוב מאוד לשבור דברים קטנים, ולהיות עם יכולת recovery כמעט מיידית, למשל: לסגור את ה feature flag או לחזור ל deployment הקודם תוך שניות (ע"י blue/green deployment - פרטים בהמשך).

המערכת לא תהיה יציבה יותר כי היא "תשבר פחות".
אם תציבו לארגון ה R&D מדד פנימי של "מינימום תקלות" - קרוב לוודאי שתהרגו את תהליך ה CD.

המדד צריך להיות: תוך כמה זמן אנו מתקלים תקלה, end-to-end: זיהוי התקלה עד אימות התיקון.

באופן זה, המערכת תהיה יציבה יותר כי (כמעט) כל שבירה תאותר ותתוקן לפני שמישהו בכלל ישים לב. בדרך תדעו היכן הרגישויות של המערכת - ותחזקו את האזורים הללו. תבנו מנגנוני הגנה מתאימים, ואז - תוכלו להתקדם בקצב גבוה מבעבר.






Continuous Integration (בקיצור: CI)


זהו הרעיון שקוד המערכת יהיה כל הזמן במצב תקין ("working state").

בניגוד למיתוס מקובל, המשמעות איננה שעליכם להתקין ולהגדיר מערכת של Jenkins או Cruise Control.
זכרו: הכלי - הוא החלק השולי. התהליך - הוא העיקר.

העיקרון הוא שאינטגרציה של קוד ("merge") הוא הכלי האולטימטיבי לזהות שבירות במערכת - ולכן עליכם לבצע אינטגרציה כל הזמן.

כפי שאמרו זאת מייסדי ה Extreme Programming (שהיו הראשונים לאמץ את הפרקטיקה בצורה רחבה):
"אם אינטגרציה של קוד היא טובה - עשו אינטגרציה של קוד כל הזמן."

המדד המקובל ליישום CI הוא:
כל מפתח, מבצע בכל יום עבודה - לפחות פעם אחת merge של הקוד שלו ל branch המרכזי. (ועדיף: חמש פעמים)


(רמז: Jenkins לא גורם לזה לקרות.)

שימו לב: זה לא שכל מפתח מושך את ה branch המרכזי (נקרא לו לצורך הפוסט: master) ועושה merge לתוך ה feature branch. זה פחות מועיל / מלמד על שברים. העניין הוא לבצע merge לתוך ה master בכל יום.

Feature Branches? לא כ"כ מומלצים, אלא אם אתם מקפידים לבצע merge ל master.
זה מחייב את המפתחים לחשוב ביחידות קטנות, לפרק את הפיצ'ר לשלבים קטנים (שזה טוב - בפני עצמו), ולדאוג כל הזמן שהקוד הנכתב - לא שובר את המערכת.

מה קורה עם קוד שמשנה חלק גדול במערכת? איך אפשר לעשות merge כאשר הקוד לא "מוכן"? - פשוט הכניסו feature flag, ואל תדליקו אותו עד שהקוד מוכן. תחשבו איזה יופי יהיה להדליק את הפיצ'ר רק עבור המשתמש שלכם בפרודקשיין - ולבדוק איך הפיצ'ר עובד בלייב עם traffic/data אמיתי!

העיקרון החשוב השני של CI הוא:
כאשר ה Build נשבר - לתקן אותו זו עדיפות עליונה של הארגון. לפני כל דבר אחר.

יעד מקובל הוא תיקון תוך 10 דקות - לרוב ע"י rollback.
אפילו יותר טוב: בדקו את ה merge בצד, ורק לאחר שהצליח - בצעו את ה merge בפועל. השיטה הזו עובדת יותר טוב כאשר יש code bases קטנים (למשל: microservices) ואין race condition על merges.

הרעיון העיקרי לעקרון הזה הוא לדאוג לשיפור מתמיד. כל עוד הארגון מוכל לסבול כמה שעות של build שבור - לא יהיה ניתן יהיה לעמוד ביעד הראשון, ויש סיכוי טוב שהארגון לא יצליח להתמיד בתהליך ה CI.

כל הרעיונות של פרסום ברבים של שם האדם ששבר את ה build, או לבקש ממנו לחבוש כובע מצחיק - הם שגויים מהיסוד בעיני, ופשוט לא אפקטיביים. זו פשוט דרך להרוג את הרצון של אנשים לבצע merge תכוף.


עם CI אולי תכניסו קצת פחות פיצ'רים - אבל תוכלו לסיים את הספרינט בזמן, ובאיכות שהחלטתם.


בדיקות יחידה (Unit-Tests) או אינטגרציה (Integration-Tests) הגיעו לתהליך ה CI מאוחר יותר - והפכו לחזות עיקר התהליך. אין ספק: הן חשובות מאוד, ומועילות מאוד. מה היה קודם לכן? קומפליציה + בדיקת המערכת end-to-end (שאורכת זמן רב, ותופסת רק חלק מסוים מהבעיות).

האם בדיקות אוטומטיות טובות מספיקות, ויכולות לייתר את הצורך ב merges תכופים?
אם אתם רואים שאצלכם זה עובד - אדרבא.

בד"כ השבירות בקוד (גם אם הן נתפסות ע"י Unit tests) מגיעות אחרי merges של קוד - ואתם לא רוצים "לחטוף אותן" בסוף הספרינט - חשוב לבצע אינטגרציה כל הזמן.

בדיקות אוטומטיות שמגלות בעיות ביום האחרון של הספרינט, בלחץ - שקולות לרופא שנקרא לטפל בחולה, לאחר שזה כבר גוסס: הסיכוי להציל אותו הוא כבר קטן.

כל מיני פשרות של "רק את הפיצ'ר הזה נפתח בצד" - הן דרכים מצוינות לא להגיע ל CI עובד, שמצדיק את עצמו.


האם שווה לעשות CI ע"י merges תכופים, אך ללא בדיקות יחידה מקיפות?
- גם על זה לא הייתי ממליץ. זה כנראה עדיף במעט על בדיקות ללא merges תכופים - אך זה לא ייתן את האפקט המלא.


CI הוא האב הרוחני של CD, ולרוב מגיע איתו ביחד.
האם חובה ליישם CI לפני שמתחילים לעבוד על CD? - נדבר על זה בהמשך...



סיכום


בפוסט זה ניסיתי להסביר מה הציפיות הסבירות מ CI/CD/CDD - תהליך חשוב שלאט הולך ומוטמע באמת בעוד ועוד חברות. אימוץ תהליכים אלו הם לרוב מאמץ ארגוני אינטנסיבי של חודשים - אבל גם השיפור עשוי להיות משמעותי למדי.

בפוסט זה פירטתי קצת על CI. הפוסט הבא ארצה להמשיך ולפרט על CD ו CDD - בהתאמה, ולעלות כמה נקודות לגבי תהליך ההטעמה של תהליכים כאלו.


שיהיה בהצלחה!



יום שני, 24 באוקטובר 2016

התקפת מניעת-שירות, וכיצד האינטרנט בחוף המזרחי - הושבת?

התקפת מניעת שירות, או בקיצור DoS (קיצור של Denial of Service), היא התקפה פשוטה יחסית לביצוע אך אפקטיבית למדי. מכיוון שרבים ממנגנוני ההגנה הקיימים לא רלוונטיים עבורה - היא הפכה לפופולארית למדי.

DDoS (כלומר: Distributed Denial of Service) היא כבר התקפה שיש מאחוריה סיפור מרגש: אלפי מחשבים (אולי אפילו מיליונים) - תוקפים שירות גדול וחזק: ענק אינטרנט, בנק, תשתית ממשלתי, וכו'. האם להקת הציפורים, שכל אחת ממנה חסרת חשיבות - יצליחו ביחד להפיל את הענק?
המטאפורה של רבים מול יחיד - היא חומר מצוין לסיפורים "ויראליים", וכך התקפות ה DDoS זוכות לחשיפה רחבה - גם בקרב אנשים לא טכניים שאין להם מושג בסיסי במערכות מחשבים.


סצנה מתוך סרט "הציפורים" של היצ'קוק. מקור: http://www.filminamerica.com/Movies/TheBirds

כיצד נראית התקפת DoS?


להלן דוגמה פשוטה מאוד:

אני מתחבר לאתר ״האכל חתול״ (שעוקב אחר חתולים עזובים ונקודות בהן ניתן למצוא אותם ולהאכיל אותם) ולוחץ על כפתור ה refresh ללא הפסקה. יודעים מה? אני משתמש ב Refresh Monkey, תוסף סטנדרטי לכרום - בכדי שהמחשב יעשה זאת עבורי.

Refresh Monkey. הטאב יבצע refresh חמש פעמים בשנייה - ואני יכול גם לפתוח מאה טאבים כאלו.

בפעולה פשוטה זו הגדלתי, לבדי, את סה"כ העומס על האתר: נניח שפי 4 - כי זה אתר נישתי עם מעט traffic.
גם אם המערכת לא קורסת, היא לא מוכנה לטפל בכמות כזו של בקשות - והיא תאלץ לדחות חלק מהבקשות.
חלק מהבקשות שיידחו הן שלי, אבל חלק נוסף של משתמשים לגיטימיים - וכך יצרתי נזק: מנעתי ממשתמשים לגיטימיים שירות - Denial of Service.

שימו לב לזה: שום מערכת לא נפרצה, לא שיבשתי שום התנהגות של המערכת, לא השתלתי וירוסים או נוזקות, ולא הוצאתי מהמערכת נתונים. ארבעה כלי אבטחה שאולי מוטמעים מערכת - לא רלוונטיים לסוג ההתקפה שלי. הידד!


--

עכשיו אני רוצה לשכלל את ההתקפה שלי. פגעתי עד כה ב10% מהמשתמשים הלגיטימיים (והחתולים שתלויים בהם).
לצורך הפוסט, נניח ויש לי אג׳נדה אנטי-חתולית מובהקת ואני מעוניין להגביר את הפגיעה.

הדף הראשי של האתר - הוא דף שמתוכנן להיות מהיר. רוב ה traffic מגיע אליו. העבודה שנעשית בו היא שליפה של חתולים באזור נתון. בחולון, העיר בה אני גר יש כמות ממוצעת של חתולים שמוזנים במערכת, אולם אם אדווח על המיקום שלי במרכז ת"א - צפיפות החתולים המתועדים גדולה פי שלושה!
בכדי לשפר את ההתקפה שלי - עלי לחשוב כיצד אני גורם לשרת לעבוד יותר קשה. אם אוכל לגרום לדף הראשי באתר לעבוד קשה יותר, אולי כך אפגע ביותר משתמשים, נניח 15% מהמשתמשים.


מה שבעצם אני רוצה למצוא, הוא את הבקשה הקלה ביותר עבורי לייצר, שתגרום למערכת המותקפת - להכי הרבה עבודה.


מצאתי באתר דף שנקרא: ״פריסה ארצית של חתולים ויחס האכלות״. בינגו! זה כנראה דף שלמערכת הרבה יותר קשה לרנדר (כי הרינדור מבוסס על חיתוכים וסיכומים בבסיס הנתונים). אם הנתונים אינם cached בצורה יעילה (מה שיכול ממש לקלקל!) - אני מסודר.
כמו כן, סביר יותר שדף שולי במערכת זכה לפחות שיפורי ביצועים - פשוט כי התנועה הדלילה אליו פחות משפיעה על סה"כ ביצועי המערכת.
עבורי  - זו הזדמנות מצויינת! אני אלמד את בוני האתר כמה לא יעיל הקוד מאחורי הדף הזה (!Muahaha). אני משגר עשרות בקשות בשנייה לרינדור הדף, ומייד מנתק את ה connection (ללא RST - מבלי להודיע). לשרת ייקח כמה שניות להבין שנעלמתי - ובזמן הזה הוא עדיין יעבוד להכין את הדף ולנסות לשלוח אותו אלי.

התקפה כזו עשויה להיות הצלחה גדולה: אמנם ״פריסה ארצית של חתולים ויחס האכלות״ - הוא דף שאינו חשוב במערכת, אבל אותם CPU ו Database שמשרתים אותו - משרתים גם את שאר המערכת. ברגע שתפסתי אותם, הצלחתי למנוע שירות מ90% מהמשתמשים הלגיטימיים שמנסים לגשת לאתר הבית, ולהאט משמעותית את זמני התגובה ל 10% המשתמשים שכן הצליחו לקבל שירות. הצלחה גדולה!


מקור: Scudlayer



על DDoS ו SDoS


לאחר שהבנו כיצד התקפת DoS עובדת - מה בעצם המשמעות של DDoS, מונח שהוא כנראה אפילו יותר מוכר?

אתרים גדולים מסוגלים לעמוד בעומס רב, ובכדי להשפיע עליהם ולמנוע כמות משמעותית של traffic לגיטימי - יש לייצר כמות גדולה מאוד של traffic לא-לגיטימי להתקפה. אם יהיו ברשותי 10000 מחשבים - יהיה לי קל יותר לייצר כמות משמעותית של traffic.

יתרה מכך, מנגנוני ההגנה המקובלים בפני התקפת DoS היא לזהות כמות לא סבירה של traffic ממשתמש יחיד - ואז לחסום אותו ברמה היעילה ביותר (למשל: לדחות בקשות ל tcp connection, הנדרש בכדי לבצע בקשת HTTP, על בסיס כתובת IP של השולח).

אם אני מבצע התקפה מ 10000 מחשבים, כאשר כל אחד מהם מייצר כמות traffic סבירה (נניח: 3 בקשות בדקה) - יהיה הרבה יותר קשה למערכת להתגונן ולבדל traffic עויין מ traffic לגיטימי. אם המערכת תחסום כל משתמש שמבצע יותר מ-2 בקשות בדקה - ניצחתי: מנעתי שירות מהרבה משתמשים לגיטימיים! (ואז אין לי בעיה לשנות מעט את ההתקפה, ולבצע רק 2 בקשות בדקה).




על מנת לייצר התקפת DDoS יעילה, עלי לאסוף אלפי מחשבים, אולי עשרות אלפים, ואולי יותר - שאולי לשלוט בהם. כל מחשב כזה נקרא Zombie, וצבא של זומבים נקרא גם BotNet. האיסוף מתבצע בד"כ ע"י נוזקה שתתוקן במחשב ותהיה במצב רדום - עד אשר ארצה לבצע את ההתקפה. הנוזקה לא צריכה "להשתלט על המחשב": היא רק צריכה להתקין agent שמאזין ל port מסוים ומאזין לפקודות משרת ההפעלה שלי. בעת ההתקפה, בעל המחשב כנראה לא ירגיש בכלל שהוא שותף להתקפה. לא יפריע לו - ולא יהיה לו טריגר לנסות ולהסיר את ה agent שלי.
את הנוזקה אני יכול להפיץ באתרי הורדות קבצים במשך חודשים או שנים - עד לרגע ההפעלה. מי שרוצה לקצר תהליכים ויש ברשותו משאבים - יכול גם לרכוש רשתות BOTNET השוק העברייני, ממישהו שטרח והקים אותן.

בהתקפה שהתרחשה בימים האחרונים על Dyn - ספקית שירותי DNS ("ספר הטלפונים של האינטרנט") גדולה, השתמשו ברשת Mirai - רשת Botnets מוכרת, שכבר שימשה לכמה התקפות בעבר, אם כי לא בסדר גודל כזה (מקור).

ההתקפה על Dyn. מקור: TechCrunch

מה שהיה חדש יחסית בהתקפה הוא השימוש ב "מכשירים בסיסיים" או "דברים" (IoT - Internet Of Things) - לביצוע ההתקפה. כלומר: הזומבים ב Mirai Botnet הם טוסטרים, שואבי אבק, מצלמות אבטחה - רכיבים שונים בעלי גישה לאינטרנט. הנוזקה "Mirai" סורקת את האינטרנט וברגע שמזהה מכשיר שכזה מנסה להתחבר אליו כ Admin בעזרת רשימה של users/passwords נפוצים שיש ברשותה. אלו הם לרוב ה defaults שמסופקים מהיצרן או שם וססמה קבועים - שלא ניתן בכלל להחליף.

"למה שאשנה את הססמה של הטוסטר החכם שלי?" - תוהה לעצמו המשתמש הביתי המתוחכם (שבכלל מודע לאפשרות). "מה יעשו - ישרפו לי את הצנים בבוקר? חחחח".

לא ידידי, יותר מעניין לתפוס עוד חצי מיליון טוסטרים שכאלו ואז להשבית תשתית משמעותית באינטרנט. למשל - זו של Dyn. מיותר לציין שיצרני ה"מכשירים החכמים" השונים, לא מתעניינים באבטחה במיוחד - ויש להם מודעות נמוכה לנושא (לפחות הייתה להם עד לפני מספר ימים). גם אם המצב הולך להשתפר - ישנם מיליוני מכשירים לא מאובטחים / בעלי ססמאות מטופשות, וישווקו עוד מיליונים רבים שכאלו - ע"י יצרנים שהתחרות בשוק תעניין אותם יותר מסיכוי שהמכשירים שלהם יהיו מעורבים בהתקפה פוטנציאלית.


בעוד על DDoS כולם כבר שמעו, על SDoS כמעט ולא שומעים - אין גאווה גדולה לארגון לספר שהותקף בכזו התקפה.

SDoS הם ראשי תיבות של Self Denial of Serive (מושג מקביל: Unintended Denial of Service) בהם ארגון מייצר לעצמו traffic שהוא לא מסוגל לעמוד בו - ואז נאלץ לדחות (= לא לספק שירות), לכמות גדולה של משתמשים לגיטימיים.

דוגמה קלאסית: קמפיין שיווקי שלא תואם (או אולי תואם, ותוצאותיו לא נצפו ע"י ה R&D/Operations) - שמגדיל את התעבורה פי כמה מונים - אך המערכת לא יכולה לעמוד בכמות ה traffic שנוצר.

פאדיחות.


בהתקפת DoS/DDoS זה מה שאתם רוצים שבעלי האתר יראו: פחות traffic מטופל, וזה שמטופל - הוא איטי ומציק.
מקור התמונה: New Relic


סגנונות תקיפה נפוצים


התקפת DoS לא חייבת להיות ברמה הטכנולוגית. לדוגמה: נניח שאני רוצה לתקוף אפליקציית מוניות, מספיק שאבצע כמה מאות או אלפי הזמנות ואבטל אותן ממש לפני שהנהג מגיע ליעד - בכדי למנוע מנוסעים רבים שירות בזמן הזה. מספיק שאתקשר למסעדה ואבצע 20 הזמנות מפוברקות של שולחנות לאורך הערב - בכדי לפגוע במסעדה. במערכות של בתי קולנוע, בעת ביצוע ההזמנה - נשמרים המקומות שבחרתי למשך 15 דקות גם מבלי שסיפקתי פרטים מזהים או אמצעי תשלום. מספיק שאתחיל הזמנה אחת בכל דקה (ואסמן חמישה מקומות) - בכדי למנוע מ 75 מושבים להתמלא ע"י לקוחות אמיתיים.


בכל זאת, ניתן לאפיין ברמה הטכנולוגית כמה סגנונות נפוצים לביצוע התקפות DoS/DDoS:


HTTP Flood

התקפות HTTP Flood הן ההתקפות הפשוטות והישירות - כמו הדוגמה שנתתי למעלה.
את ההתקפה אפשר למקד בכמות בקשות גבוהה, או בתפיסת רוחב הפס ("Bandwidth attack") של האתר. את סוג ההתקפה הזו עושים ע"י הורדה של כמויות גדולות ככל האפשר של נתונים מהאתר (לזומבים, כמו בחשבון ביתי, יש לרוב יש יותר נפח הורדה - ופחות נפח העלאה).

כדי לייצר התקפה מוצלחת חשוב למצוא דפים / אלמנטים באתר שהם איטיים במיוחד, דורשים חישוב רב - והכי חשוב: אינם cached! חשוב למצוא כמה דפים כאלו. במהלך ההתקפה האתר יכול להתגונן ע"י השבתה מכוונת של דף שאנו תוקפים - ואז נרצה לעבור מהר מאוד לדף איכותי אחר.

האוייב הגדול ביותר שלנו הוא CDN (כלומר: cache יעיל במיוחד). CDN בנוי להגשת תוכן בכמויות גדולות בצורה אופטימלית - ואותו יהיה קשה מאוד להעמיס. תשתית ה CDN מנוהלת ע"י ספק שמשרת עשרות אלפי אתרים - והקיבולת של ה CDN היא אדירה.

טריק פשוט ומקובל הוא לייצר אלמנט אקראי (למשל: ב query string) ב URL - שיגרום ל CDN לחשוב שאין לו את המשאב - ולהעביר את הבקשה ישירות לאתר.
למשל:

https://feed_a_cat.co.il/comprehensive-cats-report?random=198982

הרכיב "random=198982" ב URL כמעט ואף פעם לא יגרום לשרת לדחות את הבקשה (מי מתגונן בצורה כ"כ הדוקה?) - ובד"כ יגרום ל CDN לחשוב שמדובר במשאב ייחודי שלא נמצא אצלו ב Cache.



התקפות רזות: SYN Flood ו UDP-Based

כפי שאמרנו קודם לכן: אנו רוצים לייצר את הבקשה הקלה ביותר עבורי לייצרשתגרום למערכת המותקפת - להכי הרבה עבודה.

סוג התקפה זה מתמקד בקלות הקריאות מצד התוקף, וכיצד כך ניתן במשאבים נתונים לייצר עוד ועוד קריאות.

הרעיון של התקפות אלו הוא להימנע מיצירת ה TCP connection, שהיצירה שלו אורכת זמן (גוזלת מהמתקיף משאבים) - ואז יש יעד ברור לתשובה.
להזכיר: TCP Connection הוא הבסיס לביצוע HTTP Request. לא יהיו לנו בקשות HTTP בסגנון ההתקפה הזה.

גרסה ראשונה של ההתקפה, היא לבקש לייצר connection, אך לשקר לגבי כתובת ה IP שלנו.
השרת אותו אנו תוקפים יקצה משאבים (זכרון, מערכת הפעלה) ליצירת TCP connection ואז יפנה לכתובת ה IP שהמצאנו על מנת להתקדם בתהליך יצירת ה connection ("לחיצת יד שנייה"). מכיוון שהמחשב בכתובת ה IP שמסרנו לא נמצא בתהליך של יצירת connection, הוא לא יידע במה מדובר - ויענה שזו בכלל טעות.

אולי אפילו טוב יותר: הוא לא יענה במשך זמן ממושך (או בכלל) - ואז המערכת אותה תקפנו לא תוכל בכל הזמן הזה לשחרר את המשאבים שהקצתה לצורך ה connection. רוב המערכות יחכו כמה שניות ואז יוותרו על המאמץ לייצר connection, מערכת שלא עושה זאת (אין לה timeout) - היא פשוט טרף קל!

מקור התמונה: Cisco
מבחינת יחס עלויות - אנחנו שלחנו הודעה יחידה של פרוטוקול IP (זול מאוד), אך המחשב המרוחק השקיע הרבה יותר משאבים בעקבותיה.

וריאציות אחרות של ההתקפה היא לשלוח הודעות UDP לפורטים שונים של המערכת - שסרקנו במעוד מועד, וראינו שהם מגיבים בהודעת destination unreachable. רוב הסיכויים שהשרת המרוחק משקיע יותר משאבים מאיתנו, בסדר גודל או שניים.

אפשר לבצע Ping / Echo ולתת לשרת לענות. אפשר לנסות Pings עם payload גדול - שעשויים להקשות על השרת המרוחק, ואפשר (זה ממש מרושע) לנסות לשקר שכתובת ה IP שלנו היא כתובת של שרת אחר ב cluster של המערכת המותקפת - ואז לתת לשרתים השונים של המערכת לבצע ping בינם לבין עצמם...

בכל המקרים הללו, אנחנו תמיד נשלח הודעות ונשקר לגבי כתובת ה IP שלנו (כלומר: של הזומבי) - כך שיהיה קשה יותר לאתר את מקור ההתקפה ולהתגונן בפניה. זה ייתרון שניתן לנו בכך שאנו לא מייצרים TCP connection.



התקפות Amplification (הגברה)

אם יש בשליטתי 10,000 זומבים, ואני יכול לחבר לכל אחד מהם "מגבר" שיאפשר לו לייצר פי 10 traffic - הרי שכללתי במידה רבה את כלי ההתקפה שלי!

מכפיל כוח פופולרי (עד לא מזמן) היה שרתי DNS: אני יכול לבצע query מורכב על רשימה של דומיינים, לשקר לגבי כתובת ה IP שלי - ולשלוח את התשובה לאתר המותקף. המסכן יצטרך לקבל את כל התשובה, רק בכדי להבין שהיא בכלל לא קשורה אליו!

בעקבות צפיפות גבוהה של התקפות DDoS שנעזרו בשרתי DNS הופעל לחץ כבד על ספקי ה DNS לשכלל את ההגנות שלהם, ולא לענות לכמות גדולה של Queries מורכבים שמגיעים לפתע למערכת.

מגברים "טבעיים" אחרים שניתן למצוא ברשת האינטרנט כוללים:
  • שרתים שעונים לפרוטוקול SNMP (פרוטוקול ניהול רשת) - היחס בין גודל הבקשה לגודל התשובה יכול להגיע לעד פי 600, יותר! לרוע המזל, אין הרבה שירותי SNMP שפתוחים לאינטרנט הרחב...
  • שירותי NTP (כלומר: Network Time Protocol, הפרוטוקול בעזרתו שרתים מסתנכרנים על השעה הנכונה) - הם יעד פופולארי. פקודת monlist של הפרוטוקול (המחזירה רשימה של 600 השרתים האחרונים שביקשו שירות) היא בעלת יחס החזרה של פי 200.
  • מערכות Peer to Peer - שניתן למצוא פרצה ולבלבל את כל ה Peer שאנו מתקשרים איתם באותו הרגע ולחשוב שהשרת המותקף הוא בעצם אני. הם עלולים לנסות שוב ושוב עד שיקבלו את התשובה שהם מצפים לה...
  • וכו'

התקפות הגברה נמדדות לרוב בכמות ה Bandwidth שהן מייצרות. השיאים נשברים כל הזמן, והשיא הידוע לי הוא 602 Gbps - כלומר: traffic של 602 ג'יגהביט בשנייה (או 75 ג'יגהבייט בשנייה). שיא שבוודאי יישבר.





סיכום


מה הופך התקפות DDoS לכ"כ פופולאריות?
  • הן פשוטות יחסית ליישום. הרבה יותר פשוטות מהתקפות אחרות. 
  • הן מתאימות כמעט לכל מטרה: הן לא תלויות ב stack טכנולוגי מסוים, או בפגיעויות מסוימות של המערכת.
  • קשה לאתר את התוקף - ובמיוחד בהתקפות שאינן מבוססות על TCP. היכולת להתחמק - היא אינטרס עליון של התוקף.

התקפות DDoS הן חלק מהתרבות הפופולארית - וזוכות לחשיפה תקשורתית מוגברת מצד העיתונות. הן פופולריות כנגד אתרים גדולים, נגד שירותים ממשלתיים, וגם נגד Online Games (שם המשתמשים מתקשים *מאוד* להתנתק מהמשחק האהוב עליהם - אפילו לשעות ספורות). פעמים רבות ישנה התקפה קטנה "לדוגמה", שלאחריה יש דרישת כופר - שתשלום עליה ימנע את ההתקפה "הגדולה" (ואז ניתן לעבור ליעד הבא).

כמובן, שאין לי שום קשר להאקינג או תקיפת חתולים (שלא מתנחלים על הגג של האוטו שלי), והמטרה של הפוסט היא לא לעזור לכם לתקוף - אלא לעזור להבין את האיום וכיצד להתגונן בפניו.


כיצד מתגוננים?
  • מעבירים את התעבורה לאתר דרך שירות שיודע לזהות ולסנן traffic של התקפת DDoS (כמו CloudFlare או Akamai) . שירות כזה עולה כסף, אך הוא מסוגל לאתר ולמנוע מכם את רוב ה traffic של התקפת DDoS. 
  • חוסמים לגישה מהאינטרנט כל port או endpoint שאינו הכרחי.
  • בונים את המערכת כך שיהיה ניתן להשבית (disable) בקלות מנגנונים יקרים במשאבים של המערכת. בעת התקפה, עדיף לאבד יכולת או שתיים של המערכת - מאשר את כל המערכת.


שיהיה בהצלחה!