<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های Sina Shabani</title><link>https://virgool.ir/feed/@sina.sh.k78</link><description></description><language>fa</language><pubDate>2026-11-12 06:15:38</pubDate><image><url>https://files.virgool.ir/upload/users/3190076/avatar/F2QKNp.jpg</url><title>Sina Shabani</title><link>https://virgool.ir/@sina.sh.k78</link></image><item><title>ایزوله کردن ترافیک یک پردازه به کمک cgroups در لینوکس</title><link>https://virgool.ir/@sina.sh.k78/ایزوله-کردن-ترافیک-یک-پردازه-به-کمک-cgroups-در-لینوکس-q8gq0jmafrqo</link><description>مرد درون جعبه قرمز نمایانگر یک پردازه لینوکسی ایزوله شده استپیش‌گفتارچندین سال قبل که از پروتون وی‌پی‌ان (Proton VPN) استفاده می‌کردم، یک ویژگی جذاب به اسم Split Tunneling داشت که اجازه می‌داد فقط یک برنامه خاص از وی‌پی‌ان استفاده کنه و کاری به برنامه‌های دیگر نداشته باشه. اما خیلی برام عجیب بود که این ویژگی در لینوکس وجود نداشت (یا من بلد نبودم). الان مدتی هست که دیگه از وی‌پی‌انی استفاده نمی‌کنم (چون کار نمی‌کنن) ولی بالاخره یه راهی پیدا کردم این امکان رو در لینوکس فراهم می‌کنه.پیش‌نیازاین مقاله کمی پیچیده هست و نیازمند اینه که شما آشنایی جزیی با مطالب زیر داشته باشید. البته اگه باهاشون آشنا نیستید هم من همه‌ی دستورات رو تا جای ممکن توضیح می‌دم که بتونید اجراشون کنید.آشنایی جزیی با پروتکل‌های IP، TCP و UDP و SOCKSشبکه در لینوکس که شامل netfilter, iptables, iproute2کنترل گروپ یا cgroup نسخه ۱نکته‌ی خیلی مهم: تمام دستورات این مقاله روی کرنل با نسخه ۶.۱ اجرا شده و ممکنه برای شما متفاوت باشه یا کار نکنه (دستورات مربوط cgroup).# My kernel version: &#xA;$ uname -msr&#xA;Linux 6.1.55-1-MANJARO x86_64تمام مراحل این مقاله رو می‌تونید تو اسکریپتی که نوشتم پیدا کنید.شرح مسئلهبا فرض وجود یک پروکسی SOCKS روی آدرس 127.0.0.1:2080، ترافیک پردازه P1 رو بطوری کنترل کنیم که به دست پروکسی برسه و بعد هم به اینترنت. شکل زیر به خوبی نشون می‌ده این هدف این مقاله این چیه:هدف این مقاله پیدا کردن راه ارتباطی بین پردازه ۱ (P1) و پروکسی (علامت سوال در عکس) هستش.کنترل گروپکنترل گروپ، یا به اختصار cgroup (بخونید: سی گروپ)، یک ویژگی در کرنل لینوکس است که به ما امکان کنترل منابع رو می‌ده. برای مثال پردازه‌های ۲ و ۳ فقط ۵۱۲ مگابایت از حافظه رم برخوردار بشن. این ویژگی از یکسری گروه و یکسری کنترلر تشکیل شده. ما میتونیم برای هر گروه کنترلر خاصی رو اعمال کنیم. برای مثل به گروه ۱ که شامل پردازه‌ها ۲ و ۳ هست، کنترلر حافظه رم رو اختصاص می‌دیم که استفاده رم این دو پردازه رو محدود کنه. اطلاعات بیشتر در خصوص این ویژگی رو می‌تونید تو راهنمای خود لینوکس بخونید.نکته: این مقاله از cgroup نسخه ۱ استفاده می‌کنه. اما اگه می‌خواید از cgroup v2 استفاده کنید دقت کنید توی iptables وقتی که از ماژول cgroup استفاده می‌کنید باید از فلگ path-- استفاده کنید نه cgroup--.کنترلر net_clsقدم اول، ایزوله کردن ترافیک یک پردازه هستش. اگه بتونیم تشخیص بدیم پکت‌های خروجی مربوط به کدوم پردازه هستش، می‌تونیم با ابزارهای مسیریابی لینوکس (iproute2) منتقلش کنیم به پروکسی. این امکان رو کنترلر net_cls یا Network Classifier به ما می‌ده. این کنترلر، به پکت‌های هر پردازه‌ای که توی گروهش باشه، یه عدد میچسبونه به اسم Network Classifier ID یا classid که یک عدد ۳۲ بیتی بدون علامته. بعدا با استفاده از این عدد می‌تونیم توی Netfilter قوانینی بذاریم که فقط روی پکت‌هایی اعمال شه که این عدد رو دارن (در ادامه توضیح می‌دم). خب بیاید این رو پیاده کنیم.اول باید مطمئن شیم که net_cls روی فایل سیستم ما مونت شده (mounted) یا نه که می‌تونیم با دستور زیر بررسی کنیم:$ mount -t cgroup&#xA;net_cls on /sys/fs/cgroup/net_cls type cgroup (rw,relatime,net_cls)که اگه در خروجی دستور بالا، net_cls رو ندیدید یعنی این کنترلر مونت نیست و باید مونتش کنید:sudo mkdir -p /sys/fs/cgroup/net_cls&#xA;sudo mount -t cgroup -o net_cls net_cls /sys/fs/cgroup/net_clsحالا ما امکان استفاده از net_cls رو داریم و باید یک گروه جدید برای این کنترلر بسازیم. چون cgroup هم نوعی فایل سیستم هستش، با ساختن یک دایرکتوری می‌تونیم گروه بسازیم. گروه susgp (مخفف suspicious group) رو می‌سازیم و بهش classid می‌دیم:sudo mkdir /sys/fs/cgroup/net_cls/susgp&#xA;cd /sys/fs/cgroup/net_cls/susgp&#xA;echo -n &#34;0x10f2c&#34; | sudo tee net_cls.classidخب حالا هر پردازه‌ای توی گروه susgp باشه، به پکت‌هاش عدد 0x10f2c چسبیده می‌شه.نکته: عدد 0x10f2c یک عدد فرضی هستش. شما هر عدد ۳۲ بیتی دیگه‌ای رو میتونید بکار ببرید.ساخت اینترفیس tun و جدول مسیریابی جداحالا باید بیایم این پکت‌ها رو هدایت کنیم. سوال اینه که به کجا؟ که در جواب باید بگم ما یک اینترفیس tun می‌‌سازیم و تمام پکت‌هارو می‌فرستیم بهش. بعدش باید از این اینترفیس tun پکت‌هارو بخونیم و بفرستیمش به سمت پروکسی. برای ساخت یک اینترفیس tun از ماژول tuntap دستور ip استفاده می‌کنیم:# Example: ip tuntap add mode tun dev &lt;name&gt;&#xA;sudo ip tuntap add mode tun dev susifنکته: اسم اینترفیس هم می‌تونه هرچی باشه و شما مجبور نیستید مثل من بامزه باشید و اسمش رو susif (مخفف suspicious interface) بذارید :). مثلا اسمش رو بذارید: myboringiface :|.در مرحله بعد باید به اینترفیس جدیدمون یک آیپی بدیم و بیاریمش بالا:# Example: ip addr add &lt;ip&gt;/&lt;subnet&gt; dev &lt;name&gt;&#xA;sudo ip addr add 10.20.30.40/24 dev susif&#xA;sudo ip link set dev susif upحالا باید پکت‌های خروجی از پردازه‌های موجود در گروه susgp رو به کمک ساخت جدول مسیریابی جدید به اینترفیس susif هدایت کنیم (چرا جدول جدید؟ با تغییر قوانین جدول اصلی، پکت‌های کل سیستم بدست اینترفیس tun می‌رسه که ما این رو نمی‌خوایم. به جاش با ساخت جدول جدید فقط برای پکت‌های گروه susgp قوانین مسیریابیی متفاوتی رو استفاده می‌کنیم). باید توجه کنیم که در مسیریابی امکان استفاده از classid نیست، و باید به کمک iptables، این عدد رو تبدیل کنیم. برای انجام اینکار، پکت‌ها رو مارک می‌کنیم و قانونی می‌ذاریم که تمامی این پکت‌های مارک شده از جدول مسیریابی جدید استفاده کنن. اول یه جدول مسیریابی جدید به اسم susrt (مخفف suspicious routing table) می‌سازیم:echo &#34;1234 susrt&#34; | sudo tee -a /etc/iproute2/rt_tablesنکته: عدد ۱۲۳۴ آی‌دی جدول مسیریابی هست که شما هر عدد دیگه‌ای هم می‌تونید بذارید. اما دستورات آی‌پی با اسم هم کار می‌کنن. بنابراین ما فقط در این قسمت عدد رو می‌نویسیم و دیگه کاری بهش نداریم و با susrt تمام دستورات دیگه رو اجرا می‌کنیم. نکته:‌ دقت کنید که کامند بالا رو یکبار اجرا کنید و اگه فایل مورد نظر وجود نداشت، بسازیدش:sudo mkdir /etc/iproute2&#xA;sudo touch /etc/iproute2/rt_tablesحالا برای این جدول جدید یک مسیر پیش‌فرض تعریف می‌کنیم:sudo ip route add default via 10.20.30.1 table susrtحالا با کمک ip rule به پکت‌های مارک شده می‌گیم که از جدول susrt برای مسیریابی خودشون استفاده کنن:sudo ip rule add fwmark 20 table susrtحالا ما یک جدول مسیریابی جدید داریم که پکت‌هایی که از این جدول استفاده می‌کنن به دست اینترفیس susif می‌رسن و فقط باید classid رو تبدیل به fwmark یا firewall mark کنیم. ما مارک رو عدد ۲۰ در نظر گرفتیم پس:sudo iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x10f2c -j MARK --set-mark 20این دستور یک قانون جدید توی جدول mangle اضافه می‌کنه که با استفاده از ماژول cgroup، میایم به پکت‌هایی که کلاس آی‌دیشون 0x10f2c هستش، مارک ۲۰ رو می‌چسبونیم. این قانون در OUTPUT chain اضافه شده که مربوط به پکت‌های خروجی از پردازه لوکال هستش (برای مطالعه بیشتر در خصوص netfliter برید اینجا و اینجا). خوندن پکت‌ها از اینترفیس ساخته شدهشکل زیر کارهای ساده‌ای هست که تا اینجا انجام دادیم. پکت‌هایی خروجی از پردازه‌هایی که در گروه susgp هستن، کلاس آی‌دیشون 0x10f2c دارن. این پکت‌ها در زنجیر OUTPUT از netfilter فیلتر شده و بهشون مارک ۲۰ چسبونده میشه. حالا دوباره قوانین مسیریابی روی پکت انجام می‌شه و اینترفیس خروجی این پکت‌ها به اینترفیس susif (که خودمون ساختیم) تغییر پیدا می‌کنه.شکل ساده از مسیر پکت در سیستم و خروج از اینترفیس susifحالا تنها قسمت باقی مونده خوندن این پکت‌ها از روی اینترفیس susif و فرستادن اونها به سمت پروکسی هستش. قبل از هر کاری باید دقت کنیم که اینترفیس tun تو لایه IP کار می‌کنه و پکت‌هایی که از روی این اینترفیس خونده می‌شه پکت‌های IP هستند. اما پروکسی ساکس در لایه‌های بالاتر کار می‌کنه (لایه اپلیکیشن). بنابراین ما امکان ارسال مستقیم پکت‌های IP به این پروکسی رو نداریم. در این مرحله دو گزینه پیش روی ماست: خوندن دستی پکت‌ها از روی اینترفیس و هندل کردن تمام حالات متفاوت (مثل TCP handshake) و ایجاد ارتباط با پروکسی ساکس.استفاده از tun2socks که تمام این حالات رو هندل کرده و فقط نیاز به نصب این ابزار داریم.برای نصب  tun2socks دستورات زیر رو اجرا می‌کنیم: (اگر به مشکل خوردید به اینجا مراجعه کنید):git clone https://github.com/xjasonlyu/tun2socks.git&#xA;cd tun2sokcs&#xA;make tun2socks&#xA;sudo cp ./build/tun2socks /usr/local/binپس از نصب tun2socks، کافیه که دستور زیر رو اجرا کنیم:tun2socks -device susif -proxy socks5://127.0.0.1:2080 -interface loدستور بالا کارهای زیر رو برای ما انجام می‌ده:از روی اینترفیس susif پکت‌ها رو می‌خونهپکت‌های IP خونده شده رو باز می‌کنه و تغییرات لازم را اعمال می‌کنهبعنوان یک کلاینت socks5 به پروکسی ما روی آدرس 127.0.0.1:2080 متصل می‌شهو پکت‌های باز شده رو به سمت پروکسی می‌فرستهشکل زیر به صورت ساده نشون می‌ده که تو سیستم ما چه اتفاقی می‌افته:شکل نهایی از مسیر پکت از زمان خروج از پردازه تا زمان رسیدن به پروکسیتست و بررسیبرای تست این ویژگی کافیه آی‌دی پردازه مورد نظر رو به فایل cgroup.procs اضافه کنیم.برای مثال پردازه با آیدی ۱۵۱۵ رو می‌خوایم به گروه susgp اضافه کنیم:echo 1515 | sudo tee -a /sys/fs/cgroups/net_cls/susgp/cgroup.procsحالا تمام ترافیک این پردازه از پروکسی رد میشه.یا حتی می‌تونیم ترمینالی که باهاش کار می‌کنیم هم به گروه susgp اضافه کنیم. برای انجام این کار تو ترمینالی که میخواید پروکسی شه، دستور زیر رو بزنید:# $$ holds the pid of the current process. in this example it will be the pid of the shell we are in.&#xA;echo $$ | sudo tee -a /sys/fs/cgroups/net_cls/susgp/cgroups.procsبرای تست اینکه ترافیک ترمینال واقعا از پروکسی رد می‌شه، می‌تونیم آی‌پی پروکسی رو ببینیم:curl https://api.ipify.org&#xA;1.2.3.4برای برگردوندن یک پردازه به حالت عادی قبلش هم میشه آی‌دی پردازه رو به گروه دیفالت انتقال داد:# Notice that the path has changed&#xA;echo 1515 | sudo tee -a /sys/fs/cgroups/net_cls/cgroup.procs&#xA;# Remove the current shell from susgp group. Again notice the path change&#xA;echo $$ | sudo tee -a /sys/fs/cgroups/net_cls/cgroups.procsیا حتی می‌تونیم داکر رو تونل کنیم. منتها نکته‌ای وجود داره اینه که شما نمی‌تونید دستور داکر رو بندازید تو گروه susgp و انتظار داشته باشید کار کنه. داکر فقط کلاینت api هستش و پردازه‌ای که واقعا کارهارو انجام می‌ده dockerd هستش. برای همین باید dockerd رو بیاریم توی گروه susgp:pidof dockerd | sudo tee -a /sys/fs/cgroups/net_cls/susgp/cgroups.procsبعد از این می‌تونید با خیال راحت ایمیج‌های داکر رو پول کنید :).منابعScript of all the commands in this articleiptables and cgroups v2 (netfilter&amp;amp;#x27;s xt_cgroup)How to bypass OpenVPN per applicationnovpn: Bypass VPN for specific apps [Linux / OpenVPN]cgroups v1Netfilter</description><category>Sina Shabani</category><author>Sina Shabani</author><pubDate>Wed, 24 Apr 2024 21:01:53 +0330</pubDate></item></channel></rss>