بایگانی دسته: روزنوشت

یک خط کد که نیمی از اینترنت رو پایین آورد!

چند وقت پیش به مدت حدودا یک ساعت و پانزده دقیقه قطعی توی اینترنت اتفاق افتاد که تقریبا نیمی از اینترنت برای بعضی از آدما توی دنیا قابل دسترس نیود. توی این مطلب سعی می‌کنم دلیل قطعی رو بگم و دقیق تر ببینیم چه اتفاقی افتاده.

در تاریخ 21 2022 June از ساعت 6:27 UTC تا ساعت 7:42 UTC نیمی از اینترنت از دسترس کاربران حارج میشه که دلیل قطعی مشکلی توی سرور های کلودفلر (cloudflare) بود که باعث شد 19 تا از دیتاسنتر های این شرکت از دسترس خارج بشن.
البته این قطعی فقط برای بعضی از کاربران بوده (با توجه به محلی که زندگی می‌کردند) و بقیه کاربران بدون مشکل به اینترنت دسترسی داشتن.
اگرچه این 19 تا سرور فقط 4% از کل شبکه کلودفلر رو شامل میشده اما همین قطعی باعث شده که 50% از کل درخواست های داخل شبکه تحت تاثیر قرار بگیرن.

همونطوری که می‌دونید سرویس هایی که روی اینترنت داده میشن به شکل کلی یک بخش پردازش دارن (برنامه های سمت سرور بخش اصلی این کار رو می‌کنند) و یک بخش که نیاز به پردازش نداره و فقط فایل های مربوط به اون سرویس ذخیره سازی می‌شه (به عنوان مثال فایل های استاتیک و کد های فرانت) و می‌دونیم که ذخیره سازی از پردازش ارزون تر هست. و این هم می‌دونیم که موقعیت مکانی شما و فاصله شما نسبت به سرور مهم هست.
کلودفلر که یک شرکت سرویس دهنده خدمات زیرساخت و شبکه هست، سرویسی به نام CDN یا Content Delivery Network داره.
به شکل ساده اگر بخوام بگم کلودفلر تعداد زیادی دیتاسنتر توی نقاط مختلف دنیا داره و مثلا فایل های استاتیک سایت های مختلف رو داخل سرور های این دیتاسنتر ها کپی کرده در نتیجه مثلا وفتی شما می‌خواید به فلان سایت برید که از CDN کلودفلر استفاده می‌کنه با توجه به موقعیت مکانی شما درخواست شما به نزدیک ترین سرور می‌رسه . (مسلما من تخصصی توی شبکه و این شکل از مباحث ندارم و سعی کردم به شکل کلی توضیح بدم . اگر شما به این مسئله مسلط هستید توی کامتت ها می‌تونید بهم بگید که من متن رو اصلاح کنم 🙂 )

نکته ای که در مورد اینترنت خوبه بدونیم این هست که اینترنت شبکه ای از کامپیوتر ها نیست و در واقع شبکه ای از شبکه هاست که بهم وصل هستند
پروتکلی به نام BGP وجود داره که وظیفش این هست که داخل شبکه کوتاه ترین مسیر رو پیدا کنه
برای پیدا کردن کوتاه ترین مسیر داخل شبکه باید به ‌ip کامپیوتر ها نگاه کنیم. از روی ip می‌تونیم محل کاربر رو پیدا کنیم و بر اساس همین مورد کوتاه ترین مسیر رو تا رسیدن به مقصد پیشنهاد بدیم.

مشکل کلودفلر به خاطر آپدیتی بود که قبل از قطع شدن سرویس ها انجام داده بود
برای پیدا کردن کوتاه ترین مسیر داخل شبکه می‌تونیم بر اساس ip کاربر یکسری سیاست رو مشخص کنیم.
کد زیر بخشی از سیاست ها تعیین شده بر اساس ip کاربر رو نشون میده که توی آپدیت کلودفلر تغییر کرده بودن.

[edit policy-options policy-statement AGGREGATES-OUT]
term 6-DISABLED_PREFIXES { ... }
!    term 6-ADV-TRAFFIC-PREDICTOR { ... }
!    term 4-ADV-TRAFFIC-PREDICTOR { ... }
!    term ADV-FREE { ... }
!    term ADV-PRO { ... }
!    term ADV-BIZ { ... }
!    term ADV-ENT { ... }
!    term ADV-DNS { ... }
!    term REJECT-THE-REST { ... }
!    term 4-ADV-SITE-LOCALS { ... }
!    term 6-ADV-SITE-LOCALS { ... }
[edit policy-options policy-statement AGGREGATES-OUT term 4-ADV-SITE-LOCALS then]
community delete NO-EXPORT { ... }
+      community add STATIC-ROUTE;
+      community add SITE-LOCAL-ROUTE;
+      community add AMS07;
+      community add EUROPE;
[edit policy-options policy-statement AGGREGATES-OUT term 6-ADV-SITE-LOCALS then]
community delete NO-EXPORT { ... }
+      community add STATIC-ROUTE;
+      community add SITE-LOCAL-ROUTE;
+      community add AMS07;
+      community add EUROPE;

برای پیدا کردن مشکل کافی هست که فقط به این سه خط بیشتر توجه کنید

!    term REJECT-THE-REST { ... }
!    term 4-ADV-SITE-LOCALS { ... }
!    term 6-ADV-SITE-LOCALS { ... }

همونطوری که می‌بینید این قسمت از کد داره پیشوند های ip ها رو بررسی می‌کنه و میگه که اگر این ip با فلان پیشوند بود از کدوم مسیر برده و اگر ip ما توی هیچ کدوم از این شرط ها صدق نکرد reject بشه.
اما اگر نگاه کنید بعد از reject دو خط کد دیگه وجود داره که هیچوقت اجرا نمیشن چون قبل از اینکه بررسی بشن reject میشن و همین باعث شده بود که حجم زیادی از درخواست ها reject بشن.
عکس زیر رو سایت کلودفلر منتشر کرده که ترافیک شبکه رو در لحظه قطع شبکه و بعد از برگشت شبکه نشون می‌ده.

همونطور که گفتم تخصص من شبکه نیست در نتیجه سعی کردم چیز هایی رو که از جا های مختلف خونده بودم بهم وصل کنم و توضیح بدم

اگر خواستید خبر رو دقیق‌تر بخونید این گزارش از کلودفلر رو ببینید.

استاندارد نویسی و code convention در جاوا

در ادامه مجموعه پست‌های کد تمیز که می‌تونید اینجا همشون رو ببینید، ای پست در رابطه با code convention خواهد بود.

code convention یعنی چی ؟

زمانی که یک زبان برنامه نویسی منتشر میشه، شرکت یا گروهی که پشت این زبان هست مجموعه ای از مستندات رو منتشر میکنه و توضیح میده که این زبان چطوری کار میکنه و چطوری شما میتونید ازش استفاده کنید.
مثلا توی زبان جاوا برای تعریف متغیر میگه که شما می‌تونید اسم متغیر هاتون رو با استفاه از کارکتر های زبان انگلیسی مشخص کنید و اگر لازم داشتید با استفاده از underline قسمت های اون رو جدا کنید و همچنین نمی‌تونید اسم متغیرتون رو جوری مشخص کنید که با عدد شروع بشه.
این ها جزو ساختار های اون زبان حساب میشن و شما مجبورید که حتما رعایتشون کنید و اگر رعایت نکنید برنامتون اجرا نمیشه.
در کنار مستنداتی که برای زبان برنامه نویسی منتشر میشه توسعه دهنده های اون زبان یک مستند هم با عنوان code convention منتشر میکنه که داخل اون توضیح‌ میده که بهتره کدتون رو به این شکل و با این استایل خاص بنویسید.
این کار باعث میشه که تمام برنامه نویس ها روی یک سری چیز ها توافق کنن تا بتونن کد های خوانا و تمیز تری بنویسن.
به عنوان مثال داخل زبان جاوا من میتونم اسم متغیرم رو age یا AGE بذارم. از نظر کمپایلر این دو تا اسم قابل قبول هستن و کد من بدون مشکل اجرا میشه.
اما code convention مربوط به جاوا میگه بهتره اسم متغیر هایی که به شکل final معرفی میشن و در طول اجرای برنامه تغییر نمی‌کنن رو با حروف بزرگ مشخص کنیم و اگر می‌خوایم یک متغیر معمولی داشته باشیم اون رو با حروف کوچیک بنویسیم.
این یکی از convention های مربوط به جاوا بود که بهتره برنامه نویس ها توی کد هاشون اون رو رعایت کنند.این کار باعث میشه توی پروژه ها بتونید گروهی کار کنید و برنامه بنویسید.
رعایت کردن این اصول باعث میشه کد های برنامه های مختلف یکپارچه باشن و درک کد ها ساده تر باشه.

آیا مجبور به رعایت code convention هستیم ؟

هم آره و هم نه 🙂
نه به این خاطر که کمپایلر یا ادیتور شما رو مجبور به رعایت کردن این اصول نمیکنه و آره به این خاطر که اگر می‌خواید جزئی از یک تیم برنامه نویسی باشید و یا توی پروژه های آدم های دیگه مشارکت کنید باید این ها رو رعایت کنید در غیر این صورت توی بازی راهتون نمیدن.

code convention ها رو از کجا پیدا کنیم ؟

همونطو که اول پست هم گفتم شرکت یا گروه سازنده زبان به شکل مستند اون رو منتشر میکنه.
کافیه توی گوگل سرچ کنید code convention و بعدش اسم زبان برنامه نویسیتون رو اضافه کنید.
من برای جاوا از این مستند استفاده می‌کنم.ساده و راحت 🙂

تجربه من از محیط کار Unity و KDE

لینوکس معروفه به سیستم عاملی که شما می‌تونید داخل اون کاپوت رو بزنید بالا و خودتون سیستم رو دستکاری کنید. این یکی از دلایلی هست که لینوکس رو به عنوان اولین انتخاب برای من تبدیل می‌کنه.
توی توزیع های مختلف لینوکسی، اوبونتو رو من استفاده می‌کنم به خاطر جامعه‌ی بزرگی که پشتش هست در نتیجه توش کمتر به مشکل می‌خورم و اگر هم چیزی بخوام سریع می‌تونم برطرفش کنم.
از دلایل دیگه ‌ای که اوبونتو رو استفاده می‌کنم سازگاری اون با کارت گرافیک NVIDIA هست که روی سیستمم دارم .
قبلا توزیع های دیگه ای مثل fedora، suse و … رو هم امتحان کردم ولی در نهایت اوبونتو روی سیستم من بهتر جواب می‌داده.

توی سایت اوبونتو قسمتی هست به نام Flavours که اجازه میده اوبونتو رو با محیط گرافیکی مختلف و با نرم‌افزار های پیشفرض مختلف داشته باشیم .
من همیشه اوبونتو پیشفرض که با محیط unity هست رو استفاده می‌کردم ولی ایندفعه توزیعی رو به نام kubuntu نصب کردم.
همونطور که از اسمش احتمالا حدس میزنید محیط گرافیکیش KDE هست و نرم‌افزار های پیشفرض خودش رو داره

توی این پست در مورد تجربه خودم داخل این دو محیط می‌نویسم و این که من کدوم رو ترجیح میدم. شاید توی پست های بعدی هم در مورد I3 که یک مدیر پنجره هست هم بنویسم و در مورد اون هم نظر و تجربه ام رو بگم.

مزیت ها و معایب Unity

یونیتی اولین محیطی بود که من با لینوکس تجربش کردم . محیط ساده و سرراست و بدون دردسر بود.
محیط کار مجازی یا virtual desktop ساده ای داره که راحت میشه بینشون جا‌به‌جا بشید.
اگر نمیدونید virtual desktop چی هست باید بگم که فرض کنید می‌تونید چنتا مانیتور رو به شکل مجازی داخل سیستم داشته باشید و هر موقع که با برنامه‌ای کار داشتید برید سراغ اون مانیتور.
از مشخصه های این محیط نوار عمودی کنار صفحه (سمت چپ) هست که برنامه های باز یا برنامه هایی که پین شدن رو نشون میده تا دم دست باشن.
اون پایین هم یک مربع سفید رنگ داره که با فشار دادنش پنجره‌ای باز میشه که تمام نرم‌افزار های سیستم رو نشون میده.

در کل می‌تونم بگم که این محیط خیلی ساده و معمولیه. در کمتر از ۱۰ دقیقه می‌تونید تمام تنظیمات و محیط گرافیکی سیستم رو ببینید و امتحانش کنید.
به شکل پیشفرض امکان گرافیکی خاصی مثل انیمیشن یا شخصی سازی بهتون نمیده و شاید خفن ترین کاری که می‌شه داخلش انجام داد تغییر تم باشه.
البته اینم بگم که با نصب کردن برنامه هایی مثل tweak tool و یا تغییراتی که مستقیم توی فایل های کانفیگ میدید می‌تویند تغییراتی که میخواید رو بوجود بیارید.

مزیت ها و معایب KDE

محیط KDE نسبت به Gnome و Unity سابقه بیشتری داره و در سال 1996 ساخته شده.
مثل محیط های گرافیکی دیگه یک نوار ابزار داره که به شکل پیشفرص پایین صفحه قرار داره اما خودتون می‌تونید اون رو به هر طرف که می‌خواید منتقل کنید. من ترجیح میدم که بالا‌ی صفحه باشه.
داخل این نوار هم می‌تونید widget هایی که میخواید رو اضافه کنید مثلا من دو تا ویجت رو که ترجیح میدم داشته باشم رو اضافه کردم . یکی وضعبت کارت شبکه رو نشون میده و اون یکی هم وضعیت cpu رو .
اگر دکمه windows رو که ما توی لینوکس بهش میگیم super فشار بدید یک منو شبیه start ویندوز باز میشه که میتوندی داخل اون لیست برنامه ها و یا امکانات دیگه مثل خاموش کردن و خروج سیستم و …چیز های دیگه رو ببینید.
محیط KDE نسبت به Unity امکانات گرافیکی بیشتری بهتون میده. توی قسمت تنظیمات این سیستم تقریبا میتونید هر چیزی رو شخصی سازی کنید حتی شکل صفحه لاگین به سیستم و یا splash screen (صفحه ای که موقع لود شدن سیستم نشون داده میشه و لوگوی سیستم عامل رو داره).
تکرار می‌کنم که این کار ها توی محیط Unity هم شدنی هست اما برای این کار مستقیما باید فایل ها کانفیگ رو دست کاری کنید و از داخل منو ها و محیط گرافیکی این امکان رو ندارید.

به نظر من یکی از مزیت هایی که توی KDE هست شکل مدیریت کردن پنجره ها و فضا‌ی کاری یا همون work space هست.
توی KDE شما میتونید هر چنتا که میخواین work space بسازید. هر work space رو مثل یک کامپیوتر جدا در نظر بگیرید که پنجره های کاملا متفاوتی نسبت به بقیه work space ها می‌تونه داشته باشه .مثلا توی تصویر بالا من دو تا work space دارم که یکیش مربوط به کار های شرکته و اون یکی هم مربوط به کار های شخصی خودمه . هر کدوم از این work space ها هم 8 تا virtual desktop دارن.

KDE یا Unity ?

من جواب دقیق به این سوال نمی‌تونیم بدم و این کاملا سلیقه ای محسوب میشه. هر دوشون کارایی و سرعت خوبی دارن و بدون مشکل می‌تونید باهاشون کار کنید.
انتخاب من در حال حاضر KDE هست اون هم به خاطر اینکه میذاره پنجره هام رو راحت تر مدیریت کنم.
اگر توی انتخاب این دوتا محیط شک دارید بهترین راه تست کردن و تجربه ای هست که از این محیط ها بدست میارید . پیشنهاد میکنم روی ماشین مجازی هر دو محیط رو تست کنید و بعد محیط سیستم اصلیتون رو انتخاب کنید.
من فعلا از KDE استفاده می‌کنم و راضی هستم. البته محیط های دیگه مثل XFCE و LXDE و خیلی محیط های دیگه هم هستن که میتونید اون ها رو هم تست کنید.
از خوبی های لینوکس میشه به همین تفاوت ها اشاره کرد که دست کاربر رو باز میذاره تا اون چیزی رو که خودش می‌خواد داشته باشه و در آخر این جمله از کتاب انسان خردمند رو یاد آوری میکنم که تکامل نتیجه تفاوت هاست.

پلاگین Time Tunnel برای وردپرس

مدتی بود که دنبال پلاگینی می‌گشتم که بتونه نشون بده که سال ها پیش در این روز مشخص چه پست هایی رو نوشتم و خب امروز به شکل اتفاقی پیداش کردم.

اسم پلاگین TimeTunnel هست و اگر از وردپرس برای مدیریت وبلاگتون استفاده می‌کنید پیشنهاد می‌کنم که نصبش کنید.
این پلاگین کمک می‌کنه پست هایی که به خاطر گذر زمان فراموش شدن دوباره بالا بیان و فرصت دوباره خونده شدنشون فراهم بشه

پی‌نوشت : مدتی هست که دارم سعی می‌کنم هفته ای حداقل سه تا پست رو داخل وبلاگ داشته باشم اما زمانی که تعداد پست ها میره بالا ممکنه کیفیت تحت تاثیر قرار بگیره . الان که پلاگین رو اضافه کردم پستی رو نشون نمیده به خاطر اینکه من خیلی منظم نمی‌نویسم ولی امید وارم همین پلاگین مجبورم کنه بیشتر وقت بزارم

git logo

معرفی سایت oh shit git

گیت، معروف ترین و پر استفاده ترین VCS یا همون سیستم مدیریت نسخه در حال حاضر هست. تقریبا توی هر شرکت معقولی که تصمیم بگیرید کار کنید باید گیت رو بلد باشید.

git logo


یک از مشکلاتی که اغلب اوقات موقع کار کردن با گیت براتون پیش میاد این هست که اشتباهی کار رو انجام می‌دید و استرس می‌گیرید که چطوری می‌تونید کاری که کردید رو برگردونید.
خب اولین راه حل همیشه اینجور مواقع سرچ کردن مسئله داخل گوگل هست اما اگر این کار رو کرده باشید میدونید که بعضی اوقات پیدا کردن راه حل از داخل اینترنت هم کار سختی هست.

نویسنده وبسایت oh shit git اومده چنتا از مشکلاتی که معمولا توی کار با گیت پیش میان رو اونجا نوشته و راه حل شون رو هم گفته.
نگاه کردنشون جالبه، شاید روزی مشکلی رو حل کنند

Arpanet پدربزرگ اینترنت فعلی

Arpanet اولین شبکه پکت سوئیچ گسترده، که به شکل توزیع شده کنترل می‌شد و جزو اولین شبکه هایی بود که از tcp/ip استفاده می‌کرد.
این شبکه توسط آرپا (ARPA) که میشه Advanced Research Projects Agency که زیر مجموعه ای از سازمان دفاع آمریکا محسوب میشه بوجود اومد و به مرور بزرگ شد تا تبدیل شد به اینترنتی که امروز داریم.
توی عکس های زیر می‌تونید مراحل تبدیل شدن یک ایده‌ی ساده و اولیه و تبدیل اون به شبکه آرپا رو ببینید. اگر عکس های بیشتر رو می‌خواید به اینجا سر بزنید.

ARPANET in 1969

ARPANET in 1977

چرا من از لینوکس استفاده می‌کنم : اتوماتیک کردن کارهام

امروز تصمیم گرفتم یکسری پست داخل وبلاگ داشته باشم که توی اون ها توضیح بدم که چرا از لینوکس استفاده میکنم و چجوری توی کار هام بهم کمک می‌کنه .
این اولین پست از این مجموعه پست ها هست و قراره توضیح بدم که لینوکس چطوری توی رزرو غذای دانشگاه بهم کمک می‌کنه.

الان که دارم این پست رو می‌نویسم دانشجوی ترم دو ارشد هستم و این اولین ترمی هست که بعد از تموم شدن کرونا داره به شکل حضوری برگزار میشه.
اینجا برای رزرو غذای هفته بعد باید یک هفته زودتر غذاتون رو رزرو کنید و اگر تا ساعت ۲ بعد از ظهر روز چهارشنبه هفته جاری غذایی رزرو نکنید، هفته بعد کاملا بدون غذا میمونید و باید غذای روزفروش بگیرید که قیمتش چند برابر غذای رزروی هست و عملا برای یک دانشجو نمی‌ارزه 🙂
من رزرو غذام رو هیچ وقت فراموش نمی‌کنم اما الان به ذهنم رسید خوبه که هر هفته یک ایمیل هم به شکل خودکار برام ارسال بشه که این رو بهم یاد‌آوری کنه .این کار هم باعث میشه چیز های جدید یاد بگیرم و هم خغن تره .

کاری که می‌خوام بکنم این هست که به شکل خودکار هر هفته روز های یکشنبه ساعت ۸ شب که تقریبا مطمئنم سیستمم روشنه یک ایمیل برام بیاد که رزرو غذا رو بهم یاد آوری کنه. البته اگر سیستمم هم خاموش باشه مشکلی نیست و راه حلش استفاده از anacron هست ولی من اینجا از اون استفاده نمی‌کنم

برای این کار به دوتا چیز نیاز دارم :
۱- اول اینکه بتونم یک ایمیل ارسال کنم
۲- بتونم این کار رو به شکل خودکار توی ساعت و روز خاصی انجام بدم

برای مورد اول از ترمینال لینوکس استفاده می‌کنم و با استفاده از آدرس ایمیل خودم به خودم ایمیل می‌زنم . اگر نمی‌دونید که چطوری از ترمینال ایمیل بفرستید کافیه مراحلی که اینجا گفته شده رو دنبال کنید .
برای قسمت دوم هم از cron job داخل لینوکس استفاده می‌کنم
cron job ها داخل لینوکس این امکان رو به ما میدن که بتونیم یکسری کار ها رو داخل زمان های مشخصی به شکل schedule انجام بدیم مثلا بهش بگیم که هر هفته ساعت ۲ شب که همه خوابن یک بکاپ از سیستم بگیر و اون رو روی هارد فلان با اسم و تاریخ فلان ذخیره کن.

خب اول یک برنامه یک خطی می‌نویسم و توی فایلی به نام food_reserve.sh ذخیره می‌کنم
کد برنامه میگه که یک ایمیل با متن reserve your food otherwise you have egg و موضوع Reserve Food برای ایمیل من که sinasoheili79[at]gmail.com هست ارسال کن

#!/bin/sh

echo "reserve your food otherwise you have egg" | mail -s "Reserve Food" sinasoheili79@gmail.com

حالا باید به cron بگیم که این فایل رو هر یکشنبه ساعت 8 شب که میشه ساعت 20 اجرا کن . برای این کار دستور crontab -e رو اجرا میکنم و محتوای فایلی که باز میشه رو به شکل زیر تغییر میدم

# m h  dom mon dow   command
  0 20   *   *   0    ~/bin/./food_email.sh

اگر براتون سوال هست که چرا مقدار dow رو 0 گذاشتم دلیلش این هست که خارجی ها روز اول هفتشون دو شنبه هست و توی کامپیوتر ما از 0 شروع می‌کنیم به شمردن پس روز یکشنبه رو باید 0 در نظر بگیریم. اگر برای مشخص کردن زمان داخل crontab شک دارید می‌تونید از این استفاده کنید.

پی‌نوشت : مسلما راه های ساده‌تری مثل استفاده از تقویم یا برنامه های reminder هم هست ولی من ترجیح میدم از این روش استفاده کنم چون باعث میشه با پیاده کردن همین برنامه ساده چیز های جدید یادبگیرم


حمله درب پشتی از طریق کامپایلر

حمله‌ی درب پشتی از طریق کامپایلر یا Compiler backdoor attack یکی از حمله هایی است که هنوز به شکل رسمی روشی برای جلوگیری از آن معرفی نشده است
توی این پست روش کار این حمله رو توضیح میدم و سعی میکنم اون رو برای کامپایلر زبان C پیاده کنم.

معرفی

کن تامسون، برنامه نویس سیستم عامل یونیکس در سال 1984 در مراسم Turing Award داخل سخنرانیش حمله درب پشتی از طریق کامپایلر رو معرفی و در موردش صحبت می‌کنه.
در سال 2015 نرم افزار XcodeGhost که برای ساخت برنامه های شرکت اپل از اون استفاده می‌شده از همین تکنیک استفاده می‌کرده و گفته میشه که این اولین حمله در مقیاس بزرگ برای اپ استور اپل بوده و باعث شده بیش از 4000 برنامه داخل فروشگاه اپل آلوده بشه.
همانطور که از اسم حمله هم مشخصه، کامپایلر شما زمانی که می‌خواهد کد شما رو کمپایل کنه بدون سر و صدا یک در پشتی رو داخل کد های شما ایجاد میکنه
شما هم که از این درب پشتی خبر ندارید پس برنامه خودتون رو منتشر می‌کنید و این شروع ماجراست. .

چرا این حمله مهمه ؟

برای جواب دادن به این سوال نیاز هست که کمی عمیق تر به مشکل نگاه کنیم.
بذارید اینجوری شروع کنیم که اصلا از کجا می‌تونیم مطمئن باشیم که کامپایلری که الان ازش استفاده می‌کنیم توی برنامه هامون درب پشتی درست نمیکنه ؟
احتمالا جواب این هست که خب کد های مربوط به کامپایلر به شکل open source هست و اگر چنین مشکلی وجود داشته باشه حتما هستند کسایی که اون کد رو بخونن و متوجه چنین مشکلی بشن.
حالا سوال جدید این هست که اگر فرض کنیم کد مربوط به کامپایلر منبع باز باشه و کسی هم باشه که اون کد رو کنترل کنه و بخونه، کد مربوط به خود کامپایلر نیاز داره که توسط یک کامپایلر دیگه کامپایل بشه و ما چطوری می‌تونیم مطمئن بشیم که اون کامپایلر، درب پشتی رو داخل کامپلر اول ایجاد نمی‌کنه ؟
ممکنه بگید که خب می‌تونیم از یک disassembler استفاده کنیم و چک کنیم که فایل های اجرایی کامپایلر ما کد مخربی داخلشون نباشه.
اما این روش هم جوابگو نیست چون disassembler هم در نهایت یک برنامه است و ممکنه خود این برنامه هم رفتار بدی از خودش نشون بده و زمانی که می‌خواهد کد های مربوط به کامپایلر رو برای ما ایجاد کنه، کد های بد رو در داخل سورس کد مخفی کنه و نمایش نده.
ممکنه دوباره در جواب بگید که خب این روش خیلی سخته و ممکنه اصلا کسی سراغ عملی کردن این مسئله نره و در جواب باید بگم که ساخت این کامپایلر خیلی ساده تر از اون چیزی هست که فکر می‌کنید و در ادامه نشون میدم که چطور توی کمتر از ۱۰۰ خط کد این کامپایلر رو میشه ساخت.

ساخت کامپایلر

برای نشان دادن این حمله من از این ریپوزیتوری استفاده می‌کنم.
برای شروع بیاید نگاهی به فایل Login.cpp بندازیم. توی این فایل برنامه ی ساده ای هست که میگه اگر کاربر رمز ورود رو test123 بزنه می‌تونه وارد بشه

#include <iostream>

using namespace std;

int main() {
    cout << "Enter password:" << endl;
    string enteredPassword;
    cin >> enteredPassword;
    if(enteredPassword == "test123")    
        cout << "Successfully logged in as root" << endl;
    else
        cout << "Wrong password, try again." << endl;
}

حالا بیایید این برنامه رو با استفاده از کامپایلری که داریم کامپایل کنیم. پس داخل ترمینال کد زیر رو می‌زنیم

./Compiler Login.cpp -o Login

حالا اگر کد کامپایل شده‌ی برنامه رو اجرا کنیم و به جای رمز ورورد backdoor رو بزنیم می‌بینیم که برنامه این پسورد رو درست تشخیص می‌ده و وارد می‌شه.
اما همونطور که داخل کد می‌بیندی ما فقط پسورد test123 رو قبول می‌کنیم.
احتمالا حدس میزنید که شاید مشکل از کامپایلری باشه که استفاده کردیم، پس بیاید نگاهی هم به سورس کد کامپایلر بندازیم.

#include <string>
#include <cstdlib> 

using namespace std;

int main(int argc, char *argv[]) {
    string allArgs = "";
    for(int i=1; i<argc; i++)
        allArgs += " " + string(argv[i]);
    string shellCommand = "g++" + allArgs;
    system(shellCommand.c_str());
}

همونطور که داخل کد هم مشخصه این کد از کامپایلر ++g استفاده ‌میکنه و فایل ما رو کامپایل می‌کنه
توی این کد هم مشکلی نیست پس چطوری این درب پشتی به کد ما اضافه می‌شه.

قبل از اینکه در مورد اضافه شدن درب پشتی به کد حرف بزنم خوبه که با اصطلاح self-hosting آشنا بشیم
اگر دفت کرده باشید کد کامپایلر ما خودش به زبان C نوشته شده و فایل اجرایی کامپایلر ما می‌تونه فایل برنامه خودش رو هم کامپایل کنه.
مثلا داخل کد زیر من کد برنامه کامپایلرم رو با فایل اجرایی همون کامپایلر، کامپایل می‌کنم.

./Compiler Compiler.cpp -o newCompiler

این به این معنا هست که برای کامپایل کردن سورس کد ورژن جدید کامپایلرمون می‌تونیم از ورژن های قبلی خودش استفاده کنیم.
زبان های دیگه ای هم مثل C++ ، Java و یا python هم این ویژگی رو دارند
جلوتر در مورد اینکه این ویژگی چه تاثیری داره صحبت می‌کنم اما حالا بیایید در مورد اینکه درب پشتی چطور به کد اضافه می‌شه صحبت کنیم.
زمانی که شما فایل Login.cpp رو کامپایل می‌کنید اتفاق های زیر داخل کامپایلر می‌افته:
1- فایل Login.cpp داخل یک فایل موقت به نام LoginWithBackdoor.cpp کپی می‌شود.
2- فایل LoginWithBackdoor.cpp به اون شکلی که می‌خوایم اصلاح میشه. مثلا یک کلمه عبور جدید به اون اضافه می‌شه.
3- فایل LoginWithBackdoor.cpp به جای فایل Login.cpp کامپایل میشه
4- در نهایت فایل LoginWithBackdoor.cpp پاک میشه
اگر به فایل EvilCompiler.cpp نگاه کنیم می‌تونید این مراحل رو ببینید

اما کسی از این کامپایلر استفاده نمی‌کنه چون با خوندن سورس کد ‌مربوط به EvilCompiler.cpp متوجه این مشکل می‌شه پس باید راهی پیدا کنیم که این مشکل رو هم حل کنه. برای حل این مشکل از self-hosting استفاده ‌می‌کنیم.

مخفی کردن ساخت درب پشتی در کامپایلر

فرض کنید کسی برای اطمینان از درست عمل کردن کامپایلر، سورس کد های کامپایلر را دانلود کند و بخواهد خودش آن را کامپایل و از ان استفاده کند.
در این حالت اگر سورس کد EvilCompiler.cpp رو به کاربر بدیم ، کاربر متوجه حمله ما میشه و اگر سورس کد Compiler.cpp رو به کاربر بدیم دیگه درب پشتی به وجود نمیاد

برای رفع این مشکل باید از خاصیت self-hosting استفاده کنیم.
کاربر زمانی که می‌خواهد سورس کد کامپایلر رو کامپایل کنه نیاز به یک کامپایلر داره. ما ( در نقش طراح حمله ) می‌تونیم سورس کد Compiler.cpp رو به عنوان اولین کامپایلر ساخته شده برای این زبان به کاربر نشون بدیم ولی فایل اجرایی EvilCompiler.cpp به عنوان اولین کامپایلر به کاربر داده بشه. در نتیجه هر بار که کاربر سورس کد Compiler.cpp رو با این فایل اجرایی کامپایل کنه، همون روش اضافه کردن درب پشتی تکرار می‌شه و درب پشتی به کامپایلر اضافه می‌شه.

عکس زیر کل این روش رو به خوبی نشون می‌ده :

استفاده از هش برای کشف درب پشتی

یکپارچه بودن اطلاعات یعنی کسی اطلاعات رو در حین انتقال تغییر نده و چیزی که توی مقصد تحویل می‌گیریم دقیقا همون چیزی باشه که در مبدا ارسال شده.
یکی از روش های مرسومی که این روز ها برای چک کردن بکپارچه بودن اطلاعات استفاده می‌شه هش هست. توی این روش فرسنتده‌ی اطلاعات، یک هش رو هم که هش اون اطلاعات هست در اختیار گیرنده قرار میده و با این روش گیرنده با هش کردن اطلاعات دریافتی و مقایسه کردن این دو تا هش با هم میتونه چک کنه آیا اطلاعات تغییر کردن یا نه.
مثلا وقتی که فایل ایزو اوبونتو رو دانلود می‌کنید هش اون هم همراهش به شما نشون داده می‌شه که می‌تونید با هشی که خودتون از فایل ایزو می‌گیرید مقایسه کنید.
اما باید حواسمون باشه که برنامه ای که هش رو برای ما محاسبه میکنه خودش ممکنه یک درب پشتی داشته باشه. اگر به نظرتون چنین چیزی خیلی عجیب، غیر ممکن و یا سخت هست کافیه به این فکر کنید که از gcc که معروف ترین کامپایلر برای زبان C هست برای کامپایل کردن خود gcc و sha256 استفاده میشه.

و اما درسی که ما می‌گیریم …

همانطور که دیدید حمله compiler backdoor attack حمله بسیار جالب و هوشمندانه ای محسوب میشه.
اما این حمله دو نکته مهم رو به ما یاد میده :
۱- به هیچ کدی که توسط شما نوشته و ایجاد نشده باشه نمیشه اعتماد کرد
2- هر چه به سمت لایه های پایین تر کامپیوتر ها و برنامه ها پیش میریم پیدا کردن باگ ها و درب های پشتی و .. سخت تر میشه

اگر توضیحات اضافه تری در مورد این حمله می‌خواید می‌تونید به منبع سر بزنید