סיסמאות, תורכים וLastPass

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

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

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

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

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

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

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

פונקציות גיבוב לערבול סיסמאות

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

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

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

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

אגב, היום בבוקר גיליתי ש10BIS שומר את הסיסמאות כטקסט נקי, בצ'אט עם נציג שרות נאמר לי ש"האתר מאובטח על ידי קוד אמריקאי".
כמעט השפרצתי קולה מהנחיריים על המסך כשקראתי את זה, והבהרתי בעדינות לנציג החביב אך חסר המושג שכדאי לפתור את זה בכל זאת.

לעניינינו

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

מה שאומר שלפחות בתאוריה, הסיסמא הקבועה שלי מסתובבת אצל לועסי הרחת-לקום.

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

הפתרון

מנהל סיסמאות טוב, שיאפשר לכם לעבוד עם סיסמא שונה לכל אתר, וידרוש מכם לזכור סיסמא אחת בלבד.
זכרתי שחייב להיות אחד טוב כזה, וזכרתי גם שסטיב גיבסון המליץ על משהו בSecurity Now. בבדיקה מסתבר שבדיוק היה פרק על האבטחה של פתרון בשם LastPass. למעשה עדיין לא שמעתי את האפיזודה הרלוונטית (אני אגיע לזה כשאני אסיים לשמוע את הספר הנוכחי – Under the dome של סטיבן קינג) – אבל ההערות של הפרק שכנעו אותי לנסות.

LastPass

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

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

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

אני ממליץ בחום לנסות את LastPass (בחינם, יש שרות פרמיום ב12$ לשנה שמוסיף תמיכה בטלפונים חכמים ועוד כל מני דברים חביבים אך לא הכרחיים לרוב האנשים). גם אם החברה נעלמת – יש אפשרות ליצא את הסיסמאות שלכם לקובץ CSV (או ישירות לתוך מנהל הסיסמאות של פיירפוקס).

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

מטוס סולארי טס שבוע רצוף

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

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

כבר היום, מטוס כזה יכול לשמש כמטוס ריגול, וכנקודת ממסר איזורית.

וגם סירטון:

יש דברים נשברים

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

מיומנו של פגוע ג'ט לאג

בשבוע שעבר חזרתי מביקור בן שבועיים בארצות הברית, ובאמתחתי ג'ט לאג עצבני.

יום ראשון

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

יום שני

ב00:30 התעוררתי, עשיתי סיבוב וחזרתי לישון.
ב2:00 התעוררתי שוב, ולבסוף ב4:30. החלטתי שזה מספיק למרות שעדיין היה חושך בחוץ.
התחלתי לראות סרט (From Paris with love, עם טרוולטה – ככה ככה).
אכלתי את הסלט מאתמול והלכתי לעשות קניות  בסופר בשבע בבוקר בקירוב (דאגתי לרוקן את המקרר לפני הטיסה).
פעם ראשונה שאני עושה קניות בשעה כזו של הבוקר, חוויה מעניינת.
כשחזרתי ראיתי פרק של דם אמיתי, והלכתי לעבודה.
חזרתי בערב, בסביבות 20:00, והלכתי לישון ב22:00 עקב מצב צבירה די נוזלי של המוח.

יום שלישי

יקיצה ראשונה ב1:00, ואז ב3:00 ואז לבסוף בסביבות 5:15.
שוב סרט, הפעם The crazies, נחמד למדי – כמו סרט זומבים, רק בלי זומבים.
ארוחת בוקר מוקדמת של סלט וביצת עין ב6:00. עוד כמה פרקים שונים ומשונים, והלכתי לעבודה.
חזרתי בערב, ניסיתי להשאר ער תוך צפיה באיזה סרט, לא זוכר איזה. עצרתי באמצע והלכתי לישון בסביבות 23:00.

יום רביעי

עוד לילה שזור יקיצות, אחרונה ב4:00 – החמרה מאתמול.
סיימתי לראות את הסרט מאתמול, והלכתי לחדר כושר ב6:30 (זה שיא אישי, בדרך כלל אני הולך ב9:00), במפתיע החדר כושר היה מלא במשכימים, את רובם לא ראיתי שם מעולם.
חזרתי הביתה, ראיתי עוד איזה פרק של דם אמיתי, והלכתי לעבודה.
חזרתי, החזקתי מעמד עד 00:00 הפעם.

יום חמישי

המצב מתחיל להשתפר, פחות יקיצות ליליות, וקמתי ב5:45.
משום מה חפצה נפשי בפסטה, אז הכנתי לי (שיא אישי, לבשל בשש בבוקר).
תוך כדי ראיתי סרט (הארי בראון, די טוב).
עבודה, בית, הלכתי לישון ב00:30.

יום שישי

הג'ט לאג נשבר, קמתי בפעם הראשונה ב6:00,

עשיתי לי ארוחת בוקר על בסיס הרוטב הנותר של הפסטה וניסיתי לראות את אינלנד אמפייר של דייויד לינץ'.
התייאשתי באמצע – זה הסרט האחרון של לינץ' שאני רואה, אני שונא אותו.
חזרתי לישון והתעוררתי ב9:30.

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

במחשבה שניה, אני אסתדר גם בלי.

הקלות הבלתי נסבלת של הפרת הפטנט

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

הבנתם?
הבחור פיתח אב טיפוס בסוף שבוע, והבהיל את החברה כל כך עד שהם החליטו להפחיד אותו ולמנוע ממנו לפרסם את הקוד.

דעתכם?

לינוקס בתוך לינוקס, chroot

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

דבר אחד לעשות זה לנסות לקמפל את התוכנה ב64 ביט, אבל לפעמים זה לא אפשרי – בין אם כי הקוד של התוכנה לא זמין או כי מסיבות אלו או אחרות היא לא מתקמפלת ב64 ביט או אולי מתקמפלת אבל לא עובדת).

אז מה אפשר לעשות?
יש בלינוקס פקודה בשם chroot, עם דף man קצר במיוחד.

[code]
NAME
chroot – run command or interactive shell with special root directory

SYNOPSIS
chroot NEWROOT [COMMAND [ARG]…]
chroot OPTION
[/code]

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

נחזור לדוגמא של תוכנית 32 במערכת 64 ביט.
אפשר ליצור מערכת 32 ביט בספריה מסויימת, עם כל הספריות הדרושות – כולן ב32 ביט ולהריץ את התוכנית הסוררת – והיא תעבוד בלי בעיה.
יש פקודה נפלאה בדביאן בשם debootstrap, שלמעשה מסוגלת ליצור לנו מערכת דביאן מינימלית בארכיטרקטורה שנרצה (i386 במקרה הזה) ומהגרסא שנרצה – נניח stable.

[code lang="bash"]
$ mkdir stable-i386
$ sudo debootstrap –arch i386 stable stable-i386/
I: Retrieving Release
I: Retrieving Packages
I: Validating Packages

I: Base system installed successfully.
[/code]
בסוף התהליך יהיה לכם דביאן קטן ורזה למדי בתוך אותה ספריה (בסדר גודל של 200 מגה-בייט).
כדי שהוא יעבוד באמת כדאי לתת לו גישה לספריות dev וproc, ואת זה נעשה בעזרת פקודת mount עם פרמטר bind:
[code lang="bash"]
$ sudo mount –bind /dev stable-i386/dev
$ sudo mount –bind /proc stable-i386/proc
[/code]
אפשר כמובן להוסיף את הפקודות לfstab כדי שהן יורצו אוטומטית בעליה של המחשב.
[code lang="bash"]
/dev /stable-i386/dev none bind 0 2
/proc /stable-i386/proc none bind 0 2
[/code]

יש מי שעושים bind גם לספרית הבית שלהם, כדי שאותם קבצים יהיו זמינים (זהירות עם זה, אם אתם מוחקים את הstable-i386 אחרי שעשיתם את זה הוא יעיף לכם גם את ספריית הבית).
בכל מקרה, אחרי כל זה אפשר פשוט להריץ chroot כדי להכנס "למערכת" החדשה:
שימו לב שקצת קשה לדעת שאנחנו אכן בפנים, אפשר לבדוק שהקבצים מסביב הם לא מה שאתם רגילים לראות.
בדביאן יש טריק חביב, צרו קובץ debian_chroot בתוך etc, שימו בתוכו את השם של הchroot ומהלוגין הבא השם יופיע במקום בולט ונוח:

[code]
omry@falcon:~$ sudo chroot stable-i386/
root@falcon:/#
root@falcon:/# echo "i386 stable" > /etc/debian_chroot
root@falcon:/# bash
(i386 stable)root@falcon:/#
[/code]

בתוך הchroot אפשר להתפרע ולהריץ מה שרוצים, למשל apt-get כדי להתקין חבילות כאוות נפשכם.

אחד הדברים המעניינים ביותר הוא שכל העניין הזה מאפשר להריץ הפצת לינוקס אחת בתוך הפצת לינוקס אחרת.
לאחרונה נאלצתי לעבוד עם Centos 64bit, שהיא הפצה מבוססת רד-האט ועובדת עם חבילות rpm.
המשימה היתה להריץ תוכנה שנבנתה ונבדקה בדביאן בגרסאת 32 ביט, וההתקנה שלה הכילה כעשרה קבצי deb שיצרתי בעצמי מספריות בגרסאות שונות ומשונות (ולפעמים כוללת שינויים שלי).
במקום ליצור קבצי rpm מקבילים, פשוט התקנתי chroot של דביאן 32 ביט (אם מדברים על שתי ציפורים במכה אחת), ופשוט התקנתי את הdebים בפנים כאילו זה דביאן למהדרין.
נתקלתי בבאג בודד שנבע מכך שהקרנל של אותה גרסאת Centos היה ישן יותר מזה של הדביאן ואחת מקריאות המערכת (mmap) השתנתה בין הגרסאות בצורה שגרמה לקוד שעבד בגרסא החדשה של הקרנל לקרוס בגרסא הישנה, אבל שינוי קטן בתוכנה שלי פתר את הבאג.

אגב:
הפוסט הזה לא יהיה שלם בלי להזכיר את schroot שמאפשר גם למשתמשים שאינם root להשתמש בchroot, ובגדול הוא הרבה יותר נוח מאשר שימוש ישיר בchroot.

PXE, ISCSI ושאר ירקות

לפני כשנה ארגנתי לי מכונת אחסון ביתית שמריצה OpenSolaris (להלן Iron, או איירון).
איירון מכיל היום שישה דיסקים בגדלים שונים (בתצורת MIRROR, ככה שאני מקבל חצי מנפח האחסון נטו).
בהתחלה השתמשתי במכונה בתור כונן גדול לאחסון סרטים ומוסיקה (גדול מאוד, נטו 4TB וכאמור כל ביט כתוב על שני דיסקים), אבל עוד מההתחלה היו לי מחשבות על אחסון של ספריית הבית שלי על המכונה הזו כדי להרוויח מהירות שרידות וגיבויים נוחים ויעילים (הכל בחסות ZFS).
מכיוון שהדיסקים החדשים יותר שלי נמצאים באיירון המחשב הראשי שלי זכה לקבל שני דיסקים ישנים למדי, של 200GB ו500GB.
על הדיסק של ה200GB מותקנת חלונות 7 שמשמשת אותי למשחקים, ועל הדיסק של ה500 מותקן דביאן לינוקס (Squeeze) שמשמש לכל השאר.
לאחרונה התחילו לצוץ רמזים שהמצב של הדיסקים האלו די ירוד – bad sectors (מגזרים רעים!), שגיאות קריאה וסריקה (seek) אקראיות, תקיעות אקראיות וכו'.
הצעד הטבעי במצב כזה הוא לקנות דיסקים חלופיים, אבל זה די בזבוז לקנות דיסקים חדשים כשיש כל כך הרבה מקום איכותי מהיר ופנוי על איירון.
אז התחלתי לחשוב על האפשרות של איתחול דרך הרשת לשתי מערכות ההפעלה על המחשב הראשי.
מחשבים מודרניים תומכים באיתחל רשת דרך PXE (פיקסי).

מילה מקדימה:
כמעט את כל הבדיקות והמשחקים להלן ביצעתי תוך שימוש בVirtualBox.
ווירצ'ואל בוקס תומך היטב באיתחול פיקסי. כדי לעשות את זה צריך לשנות את הגדרות המכונה הוירטואלית לאיתחול מהרשת.
בנוסף, אם אתם משתמשים כמוני בשרת DHCP ברשת האמיתית, חשוב לשנות את הגדרות כרטיס הרשת של המכונה הוירטואלית למצב Bridged (ברירת המחדל היא NAT) אחרת זה לא יעבוד.

כדי לאפשר למחשבים לבצע איתחול דרך פיקסי צריך את הרכיבים הבאים:

  • שרת DHCP – שמעביר אוטומטית למחשב הגדרות רשת ופרמטרים לפיקסי.
  • שרת  TFTP – שמכיל קבצים שמשמשים את תהליך האתחול. TFTP זה קיצור פרוטוקול טריויאלי להעברת קבצים, והוא מאוד פרימיטיבי ואיטי – אבל מספיק בשביל להתניע את התהליך.

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

  • TFTPsrvN :  שמכיל את השם או כתובת הIP של המחשב שמריץ את שרת הTFTP
  • BootFile : שמכיל את השם של קובץ ההפעלה הראשי שמתחיל את תהליך האתחול, ונמצא בתוך ספרית השורש של שרת הTFTP.

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

מכיוון שאני מתכוון להשתמש במכונת הOpenSolaris לשמירת הקבצים, זה טבעי שאני אשתמש בה גם בשביל שרתי הDHCP והTFTP.
שרת הDHCP הנפוץ ביותר הוא ISC DHCP ואולי כדאי לבחור בו כי רוב הדוגמאות שתמצאו ברשת לגבי הגדרת PXE יתאימו לשרת הזה.
אני החלטתי להשתמש בשרת הDHCP שמגיע עם OpenSolaris, יש הוראות התקנה וקינפוג בסיסיות כאן.
מה שחסר זה שם זה איך מגדירים את TFTsrvN ואת BootFile:
ככה אני עשיתי את זה:
[code lang="bash"]
pfexec dhtadm -M -m `hostname` -e BootFile=pxelinux.0
pfexec dhtadm -M -m `hostname` -e TFTPsrvN=10.0.0.4
[/code]
אפשר גם להשתמש בכלי הגרפי dhcpmgr שיפתח ממשק משתמש שיאפשר שינוים בהגדרות שרת הDHCP.

טועני בוט

לדעתי הטוען בוט הפופולרי יותר הוא pxelinux שהוא למעשה גרסא מיוחדת של syslinux.
כדי לעבוד עם פיקסילינוקס, צריך לשים את pxelinux.0 בספריית השורש של שרת הtftp (בדרך כלל /tftpboot).
כשפיקסילינוקס עולה, הוא מחפש קבצי הגדרות שמתאימות למחשב לפי סדר הגיוני למדי : קודם קובץ בשם של כתובת הMAC של המחשב, ואז בשם של כתובת הIP, ואז חלק יותר קטן מכתובת הIP וכו' ולבסוף קובץ השם default שיטען אם לא נמצא קובץ הגדרות יותר ספציפי.

פיקסילינוקס תומך במעין תפריט בוט פשוט, למשל:
[code]

LABEL sbm
KERNEL memdisk
APPEND initrd=sbm.bin

LABEL local
LOCALBOOT 0
[/code]

עם התפריט הבא, פיקסילינוקס יציג לנו propmt שבו נוכל להקליד local כדי להמשיך לבוט מקומי או sbm כדי לטעון את  Smart boot manager (אפשר למצוא את sbm.bin פה.

דבר אחד שחסר לפיקסילינוקס הוא תמיכה בboot מכונן iscsi.
iscsi הוא פרוטוקול תקשורת שמאפשר שימוש בדיסק מרוחק כאילו הוא דיסק סקאזי מקומי.

מסתבר שפרוייקט אחר בשם gpxe (הידוע גם כ Etherboot) תומך בבוט מiscsi, ואפילו בבוט מhttp, ftp ועוד.
מסתבר עוד, שיש מעין הכלאה של pxelinux ושל gpxe שמאפשרת את היכולות של pxelinux וגם את היכולות של gpxe, ההכלאה נקראת gpxelinux (איזו הפתעה) והיא כלולה בהורדה של pxelinux.
כדי להשתמש בgpxelinux, צריך לקבוע בשרת הDHCP שקובץ הבוט הוא gpxelinux.0, שאר העבודה בדיוק כמו עם פיקסילינוקס.

על ISCSI

לISCSI יש טרמינולוגיה די מעצבנת:

  • Logical unit : המקבילה לדיסק או מחיצה
  • LUN : המספר של הלוג'יקל יוניט
  • Target : מעין מזהה שמגדיר גישה לאחד או יותר יחידות לוגיות, נראה ככה למשל : iqn.1986-03.com.sun:02:2775db99-0772-6e28-bb0e-bcbe420894ee
  • Initiator : הלקוח, קוד ששולח בקשות IO בפרוטוקול iscsi.

אפשר להרים שרת iscsi גם עם לינוקס כמובן, אבל אני משתמש באופן סולאריס בתור מערכת האחסון שלי.

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

יש פה פוסט די טוב שמתאר שימוש בסיסי בקומסטר כדי ליצור iscsi target.
מה שחסר זה שצריך בהתחלה להתקין את stmf ולעשות ריבוט אם זה לא עובד (כן, ריבוט – יש על זה באג פתוח).
[code]
pkg install SUNWstmf
[/code]
שימו לב שבדוגמא שם הוא מתאר איך ליצור מיפוי שבו כל היחידות הלוגיות זמינות דרך כל הtargetים. אם אתם רוצים משהו יותר מורכב מזה תקראו את התיעוד, ספציפית את הדף הזה.

ברגע שהגדרתם target בהצלחה, נשאר לבדוק אותו.
זה די פשוט גם בחלונות 7 או וויסטה וגם בלינוקס. חפשו קצת בגוגל.

לגבי התקנות ואיתחול של של מערכות הפעלה ספציפיות על iscsi, יש תיעוד לרוב בוויקי של Etherboot .
עדיין לא הצלחתי להגיע לבוט מלא של חלונות 7 או דביאן דרך הרשת, אבל אני מקווה להצליח בקרוב.

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

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

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

זליגת זכרון : הרוצח השקט

זליגת זכרון היא אחד הבאגים החמקמקים ביותר, ממש הרוצח השקט של תוכנות מחשב.
לא משנה באיזה שפה אתם כותבים, לא קשה במיוחד לכתוב קוד שידלוף כמסננת (אם כי זליגות זכרון בשפות מנוהלות כמו ג'אווה ו#C הן בעלות מאפיינים שונים לגמרי מזליגות זכרון בשפות בהן המתכנת אחראי על ניהול הזכרון ואין איסוף זבל אוטומטי).
כל משתמש מנוסה מכיר את התופעה המציקה, שתוכנה עובדת מהר בהתחלה ואחרי פרק זמן לא קבוע היא מתחילה להאט ולהאט עד כדי זחילה.
לפעמים היא מצליחה להאט את כל המחשב על הדרך, אם היא זולגת כמויות זכרון שגורמות למחשב להתחיל להשתמש בצורה מופרזת בקובץ הSWAP.
בניגוד להרבה בעיות תכנות אחרות, המתכנת לא מקבל אזהרה או שגיאה כאשר הוא כותב באג של זליגת זכרון, התוכנה לא קורסת מייד כמו למשל בגישה לזכרון דרך מצביע לNULL בC או בC++, והקומפיילר לא יספר למתכנת על הטעות שהוא עשה.
הסיבה לכך היא לא שמפתחי הקומפיילרים הם עצלים מכדי לכתוב קוד שמוצא את הבעיה – אלא שפשוט לא ניתן לכתוב קוד שיזהה זליגת זכרון בכל המקרים בצורה סטטית (על בסיס הקוד הכתוב בלבד).
הדוגמא הפשוטה ביותר היא תוכנית שמקצה ומשחררת זכרון על פי בקשת המשתמש (לאו דווקא במונחים האלו, המשתמש יכול לבקש לפתוח קובץ ובתגובה התוכנה תקצה זכרון בגודל הקובץ ותטען את הקובץ פנימה). אם התוכנה עובדת ישירות עם הזכרון אז הקומפיילר לא יכול להבטיח שהזכרון שיוקצה בשלב מסויים גם ישוחרר – ולו כי זה יקרה רק אם המשתמש יבקש את זה.

אז מה הבעיה עם זליגת זכרון?
הבעיה הראשונה והטריויאלית ביותר היא שתוכנה שזולגת משתמשת ביותר זכרון ממה שהיא צריכה, והמצב מחמיר בהדרגה ככל שאותו קוד שזולג רץ יותר. תוכנה שצורכת יותר מדי זכרון היא לא בהכרח בעיה חמורה. למעשה – כמעט כל תוכנה ברמת מורכבות בינונית ומעלה שנכתבה בשפת C או C++ זולגת זכרון כאילו אין מחר, ובדרך כלל זה לא גורם בעיות כי המשתמש סוגר את התוכנה לפני שהיא מגיע למצב של חוסר זכרון.
הבעיה הזו היא קצת יותר חמור משנדמה במבט ראשון:
כאשר המתכנת מבקש להקצות זכרון, נניח 1MB, הוא מצפה לקבל 1MB של זכרון רציף, שאפשר לעבור עליו בלולאה אחת מתחילתו ועד סופו.
דמיינו מערכת עם 2 מגה זכרון שעומדים לרשות תוכנה שרצה שם, מספיק לכאורה להקצות 2 בלוקים של 1MB.
עכשיו, אם נקצה סך הכל של 1K זכרון, ניתן להניח שנוכל להקצות עוד 1999K ובוודאי שנוכל להקצות 1MB, נכון?
אז זהו – שלא בדיוק : אם נקצה את ה1K בארבע בלוקים של 250 בתים, ובהפרשים של כ500K, למעשה נמנע מהתוכנה אפשרות לקבל זכרון רציף של יותר מכ500K.
כלומר, למרות שהזכרון הפנוי מספיק – בפועל הזכרון הפנוי שבור לחתיכות קטנות מדי (Fragmented), ואין לנו יכולת להקצות את הזכרון הדרוש.
מכאן אפשר להסיק שגם דליפת זכרון קטנה עלולה במצבים מסויימים לגרום לחוסר זכרון קריטי.
אני מקווה שזה שיכנע אתכם שדליפת זכרון זה דבר רע שראוי לטפל בו.

כל מתכנת מתחיל יודע שלשפות מודרניות יש איסוף זבל אוטומטי שאמור למנוע זליגת זכרון.
יש פה כמה בעיות, קודם כל – למרות שלרוב השפות יש איסוף זבל אוטומטי, ברוב המקרים מדובר בזבל של איסוף זבל, ואם להיות פחות ציורי ויותר ספציפי – מדובר בקוד איטי ודי מוגבל, שלא תופס את כל המקרים.
אבל אם נסתכל בג'אווה וב#C (שאני מניח שיש לה איסוף זבל בקליבר דומה לזה של ג'אווה) – הן בהחלט מסוגלות לאסוף את הזבל במהירות וביעילות.
הבעיה היא שההגדרה של זבל הוא אובייקט שהוקצה ואין אליו התייחסות משום מקום (Reference), ולפעמים המתכנת לא מבחין שבעצם יש אליו התייחסות.
למשל, קוד הג'אווה הטריואלי הבא ירוץ עד שיעוף עקב חוסר זכרון:
[code lang="java"]
import java.util.HashSet;
import java.util.Set;

public class a {
public static void main(String[] args) {
Set s = new HashSet();
int a = 0;
while(true)
s.add(String.valueOf(a++));
}
}
[/code]

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

בשפות עם ניהול זכרון ישיר יש מגוון רחב בהרבה של שגיאות שקשורות לזכרון, החל מזכרון שמוקצה ולא משוחרר, זכרון שמשוחרר פעמיים, זכרון שמוקצה עם Malloc של C ומשוחרר עם delete של C++, כתיבה או קריאה אל מחוץ לגבולות הזכרון שהוקצה ועוד ועוד.
הנה תוכנית C++ קטנה שמדגימה חלק מהשגיאות האפשריות:
[code lang="c++"]
#include

char* get1(){
return new char[10];
}

char* get2(){
return (char*)malloc(sizeof(char)*10);
}

char* get3(){
static char c[10];
return c;
}

int main() {
char *s1 = get1();
char *s2 = get2();
char *s3 = get3();

s1[11] = 'x'; // out of bounds access. mistake
free(s1); // mistake, should be delete[]
delete s2; // mistake should be free
delete s3; // mistake, should not be freed or deleted

char *s4 = new char[10];
delete s4; // mistake, should delete with delete[] and not with delete.
delete s4; // mistake, deleted twice.
char *s5 = new char[10]; // mistake, never deleted
return 0;
}
[/code]
כמו תמיד, C++ נותנת הרבה יותר חבל למתכנת התמים שרוצה לתלות את אח של אח שלו על עץ.
למעשה רק השגיאה האחרונה היא ממש זליגת זכרון, אבל כל השגיאות נפוצות וקשורות לזכרון.
יש טכניקות ידועות ומקובלות שמקטינות מאוד את הסבירות לטעויות שקשורות להקצאה ושחרור זכרון, ספציפית יש טכניקה שמוזכרת בספר The C++ programming language של סטראוסטרופ שנקראת Resource Acquisition Is Initialization או RAII בקיצור.
RAII הוא נושא שראוי לפוסט שלם בפני עצמו, אבל הנה דוגמת שימוש פשוטה (מדי, יש בה לא מעט חורים):
[code lang="c++"]
void direct_test(){
char *buffer = new char[100];
try{
work(buffer);
delete[] buffer;
}
catch(…){
delete[] buffer;
throw;
}
}
[/code]
הקוד למעלה מקצה זכרון, וקורא לפונקציה שעובדת עליו. לבסוף הוא משחרר את הזכרון וגם דואג שהוא ישוחרר כראוי אם הפונקציה תזרוק אקספשן.
התבנית הזו של טיפול ידני בשגיאות היא מאוד בעייתית ומועדת לטעויות.
אם היינו משתמשים בRAII, יכלנו להגדיר מחלקה בשם Buffer, שתדאג לשחרור ולהקצאה:
[code lang="c++"]
class Buffer{
char *buffer;
size_t size;

public:
Buffer(int size){
buffer = new char[size];
}

~Buffer(){
delete[] buffer;
}

char *get() {return buffer;}
};

void raii_test(){
Buffer buffer(100); // 100 bytes allocated in constructor
work(buffer.get());
// automatically freed when buffer destructor is called (will be called even if an exception is thrown).
}
[/code]

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

אחד הכלים החזקים ביותר לזיהוי בעיות שקשורות לעבודה עם זכרון הוא valgrind.
ואלגרינד הוא למעשה קבוצה של כלים, כשהידוע בהם הוא memcheck שבמגלה שגיאות בעבודה עם זכרון.
הוא כולל כלים אחרים לניתוח ביצועים (cachegrind, callgrind) ועוד.
ואלגרינד עובד על רוב מערכות ההפעלה ממשפחת היוניקסים (BSD, Linux, MacOS X וכו'), בתאוריה אפשר לבדוק איתו תוכנות חלונות דרך WINE.
ואלגרינד עובד בשורת הפקודה, מה שמרתיע משתמשים רבים. לאחרונה חיפשתי ומצאתי פתרון שמאפשר אינטגרציה של ולגרינד עם CDT:
התמיכה היא כחלק מפרוייקט בשם LinuxTools שמפותח על ידי RedHat (כנראה).
יש פה דמו וידאו של השימוש בפלאגין.
קובץ הוידאו נמצא כאן למי שלא מצליח לראות אותו בבלוג (דורש פיירפוקס 3.5 או דפדפן שתומך בתג וידאו).

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

API לזיהוי פנים

בתקופה האחרונה עבדנו קשה בface.com על API פתוח למציאה וזיהוי פנים, ואתמול בערב השקנו אותו.
זיהוי פנים מורכב מכמה שלבים:
השלב הראשון הוא למצוא אוטומטית היכן בתמונה יש פנים, או face detection.
השלב השני הוא להשוות את הפנים שנמצאו למודל (או מודלים) שהכינונו מבעוד מועד של מי שאנחנו רוצים למצוא. (face recognition)
השלב המקדים הוא להכין את המודל, ובשביל זה צריך לתת דוגמאות אימון של אותו אדם למערכת (traininng).
הAPI תומך כרגע בשלוש קריאות שמתאימות לשלושת השלבים האלו ובעוד כמה קריאות עזר כמו שמירה ואיחזור של טאגים וכו'.
כמובן, יש שימושים רבים למציאת פנים שלא מערבים זיהוי.

אפשר להתנסות בכל מה שיש לAPI להציע בלי לכתוב שורת קוד דרך הAPI Sandbox.
יש באתר כמה דוגמאות לשימוש בAPI, כולל ווידג'ט לתיוג פנים בתמונות, ואפליקציה שמחפשת תמונות של מפורסמים בטוויטר.

שחררנו ספריית PHP וספריית JavaScript, אבל זה לא יהיה קשה לכתוב ספריות בשפות נוספות (הAPI מבוסס HTTP, והתשובות חוזרות כJSON או XML).
תתפרעו 🙂

נ.ב:
יש מגבלה של 200 בקשות זיהוי/מציאת פנים לשעה לAPI KEY, זה בטוח מספיק להתנסות וגם לרוב השימושים, יש עוד מידע פה.