به نام خدا
در قسمت قبل این مجموعه مقالات و هدفشون رو معرفی کردم و در مورد یه سری ابزار شبکهای در لینوکس صحبت کردم. در این قسمت میخوام در مورد ساختار شبکه در لینوکس به شکل کلی صحبت کنم. این که وقتی یک پکت وارد کرنل میشه چه اتفاقاتی براش میافته. چجوری یه به دست پردازهای که ازش استفاده میکنیم میرسه و از پردازه به یه مقصدی فرستاده میشه. این توضیحات به این دلیل لازمه که وقتی وارد کانتینرها شدیم بتونیم دید بهتری از اتفاقاتی که داره میفته پیدا کنیم. البته همهی اتفاقات رو نمیشه تو یه مقاله گفت و من هم به همهاش مسلط نیستم. چیزهایی که در ادامه به دردمون خواهد خورد رو قراره بگم.
قبل از این که شروع کنیم در مورد ساختار شبکه صحبت کنیم بهتره این دو مفهوم رو یه بار مرور کنیم. همونطور که میدونید کرنل وظیفهی مدیریت سختافزار و اجرای برنامههای کاربران روی اون رو بر عهده داره. خود کرنل هم یک برنامه است که باید در CPU اجرا بشه و نیاز به مموری داره. کارهایی که در کرنل انجام میشن رو میگیم در kernel space هستن. مثلا وقتی یه پکتی وارد سیستم میشه و قراره پردازش بشه قسمتی از این پردازش رو کرنل انجام میده و ما میگیم این بخش در kernel space هست. علاوه بر این قسمتی از پردازش هم توسط برنامههایی که کاربران سیستم عامل نوشتن انجام میشه. کارهایی که توسط این برنامهها انجام میشه رو میگیم در user space هستن.
در بخش قبل در مورد user space و kernel space گفتم. حالا اینجا میخوام بگم که در مورد شبکه کدوم بخش از پردازش در کرنل و کدوم بخش در user space انجام میشه. در مدل OSI برای شبکه ما هفت لایه داریم. از لایهی فیزیکی شروع میشه. بعد میرسه به لایهی دیتا لینک، شبکه و انتقال. سه لایهی آخر به ترتیب نشست یا session، نمایش و اپلیکیشن هستن.
لایهی فیزیکی توسط کارتهای شبکه انجام میشه. اونا هستن که با توجه به جنس محیط انتقال و شرایط ارسال به شکل مناسبی بستهها رو میفرستن به دستگاههای بعدی. بعد از اون لایهی ۲ میاد که دیتا لینک هست. این لایه توسط کرنل و کارت شبکه انجام میشه. قسمتی در کرنل هست به اسم network device driver که با کارتهای شبکه صحبت میکنه و پکتها رو به لایهی بعدی میفرسته. ما این کارتهای شبکه رو به شکل اینترفیس (interface) میبینیم و باهاشون تعامل میکنیم. این همون چیزیه که وقتی دستور ip addr میزنیم میبینیم. البته تمام اینترفیسهایی که نشون میده متصل به کارت شبکه نیستن و ممکنه اینترفیس مجازی هم نشون بده بهمون. ولی میشه اینترفیسهای فیزیکی رو هم باهاش دید. لایهی ۳ و ۴ هم توسط کرنل هندل میشه و از اون به بعد در اختیار پردازههای کاربران قرار میگیره. پردازهها هم با استفاده از سوکت محتویات بسته رو میگیرن. سوکت در اصل یه رابط برای برنامهنویسهاست که کرنل در اختیار قرار میده که بتونن راحت و بدون توجه به لایههای پایینتر شبکه کارشون رو بکنن. مثلا دیگه لازم نیست برنامهنویس توجه کنه که کانکشن TCP درست برقرار شده یا نه. فقط محتوا رو از طریق سوکت میده به کرنل و بقیهاش رو کرنل انجام میده.
البته گاهی اوقات خود پردازه در user space به کرنل درخواست میده که زودتر پکت رو بهش بده. یعنی میگه لایههای پایینتر رو هم خودم مدیریت میکنم. این ویژگی در لینوکس وجود داره و میشه برای موارد خاص و پیشرفته این کار رو هم کرد. راههای دور زدن کرنل در شبکه زیاده و هر کدوم میتونه به دلیلی استفاده بشه. ما راجع به اون موارد اینجا صحبت نمیکنیم و به همون حالت رایج میپردازیم.
خیلی از اوقات هم پیش میاد که ما مستقیم سوکت باز نمیکنیم. به جاش از یه فریمورک یا کتابخونه استفاده میکنیم که کارها رو راحت میکنه. مثلا در پایتون ما ماژول requests رو داریم که باهاش درخواست http میشه داد. این ماژول نه تنها سوکت و ارتباط با کرنل رو برای ما انجام میده بلکه خیلی از کارهای لازم برای ارتباط http رو هم داخلش داره. نکتهای که باید بهش توجه کنیم اینه که در این حالات هم باز کرنل داره با استفاده از سوکت با user space حرف میزنه فقط اون قسمتش از ما پنهان شده.
امیدوارم در بخش قبل یک دید کلی از شبکه در کرنل پیدا کرده باشید. در این بخش میخوام جزئیات بیشتری از لایهی ۳ در کرنل رو بگم که در ادامه برامون مهم خواهد بود. هدف اینه که بدونیم ابزارهایی که استفاده میکنیم در کدوم قسمت کار میکنن و ترتیبشون چیه.
در مسیر ورود پکت، بعد از این که کارهای لایه ۲ انجام میشه و میخواد پردازش لایهی ۳ شروع بشه ابزارهایی مثل tcpdump میان و یه کپی از پکت رو میگیرن تا خودشون در user space تحلیلش کنن. یعنی خیلی خیلی زود پکت رو میگیرن. قبل از این که routing یا netfilter انجام بشه. در شکل زیر میبینید بعد از درایور این رو نشون دادم.
بعدش پکت وارد جاهایی میشه که ما بیشترین کار رو باهاش داریم. اول میاد داخل netfilter. ما در کرنل ۵ تا جا داریم که به اونها netfilter hook میگن و میشه با نوشتن کرنل ماژول تغییراتی در پکتها اعمال کرد. اونهایی که در شکل بالا بیضی هستن هوکها رو نشون میدن. iptables هم بر همین اساس کار میکنه و اون دستوراتی که ما میزنیم تو این قسمتها اعمال میشن. در شکل بالا مسیر خروج پکت هم کشیده شده که هوک OUTPUT رو در این مسیر میبینید. در بخشهایی از این مسیر هم تصمیمات روتینگ گرفته میشه. مشخصه که در مسیر ورود بعد از PREROUTING روت انجام میشه. چون ممکنه ما در اونجا پکتی رو NAT کنیم و دوباره نیاز داشته باشه مسیرش مشخص شه. ممکنه یه پکت وارد سیستم بشه و اصلا به user space نرسه و از همون روتینگ اول به FORWARD بره و خارج شه. در مسیر خروج هم بعد از OUTPUT روتینگ انجام میشه. مسیر خروج مسیریه که یه پکت از user space شروع میکنه و وارد کرنل میشه. ممکنه تو این مسیر از سیستم خارج نشه پکت و به یک پردازهی دیگه در سیستم برسه. دونستن ترتیب اینا خیلی مهمه و در دیباگ کردن یا ساختن ابزارها کمکمون خواهد کرد. یه نکته رو هم توجه کنید دوباره. در مسیر خروج tcpdump یا وایرشارک بعد از همهی اینها و موقع ورود پکت به درایور قرار میگیره. در مسیر ورود هم قبل از همهی اینها و بعد از خروج از درایور قرار میگیره. این رو ایشالا در کارهای عملی آینده خواهیم دید.
در قسمت بعد برای این که با این مفاهیم و ابزارهای قسمت قبل بیشتر آشنا بشیم قراره یک روتر در لینوکس بسازیم. یعنی سیستم لینوکسی رو تبدیل به روتر کنین. شما هم به عنوان تمرین سعی کنید با جستجو یک روتر لینوکسی بسازید که دو تا شبکه رو به هم وصل کنه. در قسمت بعد منم همچین چیزی رو خواهم ساخت.
امیدوارم براتون مفید بوده باشه. اگه سوال یا نکتهای بود این پایین بنویسید.