پلهای اترنت تحت لینوکس
نویسنده:Paul
dwerryhouse
ترجمه: مرجان صدیقی
انارکی
مقدمه
ده سال پیش، کمی بعد از اینکه اولین کارم را به عنوان برنامه نویس شبکه در یک دانشگاه استرالیایی شروع کردم، شخصی که دریک کارخانه کار میکرد به من تلفن کرد و در مورد مشکلی که شبکهاشان داشت با من صحبت کرد. تمام کامپیوترهایشان با کابل کواکسیال 50 اهم اترنت به هم وصل بودند، و بین دو تا از کامپیوترها در این شبکه مقدار قابل توجهی داده رد و بدل میشد.
این داده، مرتبا در کل کابل شبکه اکو میشد که این باعث تاخیر و تلفات پکت (packet loss)ها به سایر کاربران شبکه میشد. شخص مذبور به دنبال روشی برای حل این مشکل بود. مدیر من پیشنهاد بکارگیری پل، بین دو کامپیوتری که بینشان دادههای زیادی ردو بدل میشد را داد. پل میتوانست در پشت آنها قرار گرفته و ترافیک بین آنها محدود شود. این راه حل جذابی بود بخصوص که نیاز به هیچ تغییرخاصی در شبکه و یا تغییرنامبرینگ شبکه نبود، آن میتوانست جذاب بوده و به سرعت کار کند.
بعد از سالها، حال کرنل لینوکس دارای چنین توانایی است و میتواند میزبانهایی با بیش از یک اینترفیس شبکه را به پل تغییر دهد. این مقاله نشان میدهد چگونه آن کار میکند.
پل زدن چیست؟
پل زدن فرآیند اتصال شفاف بین دو بخش شبکه است، بدینصورت که پکتها میتوانند بین دو بخش به گونهای منتقل شوند که انگار در یک شبکه منطقی واحد قرار گرفتهاند. پل زدن در لایه لینک داده (Data link) انجام میشود، بنابراین مستقل از پروتکل شبکه بکار گرفته شده میباشد – مهم نیست که شما از IP، Appletalk، Netware یا هر پروتکل دیگری استفاده میکنید، چون پل روی پکتهای خام اترنت عمل میکند.
بطور کلی؛ در شرایط بدون پل، یک کامپیوتر با دو کارت شبکه میتواند به دو شبکه مستقل وصل شود، در حالیکه مسیر پکتها ممکن است توسط کامپیوتر انتخاب شده و یا دستی وارد شود. در عمل، هر اینترفیس شبکه باید آدرس شبکه و شماره شبکه مجزایی داشته باشد. زمانیکه ازپل زدن استفاده میشود، هر بخش شبکه بخش موثری از همان شبکه منطقی است، و دو کارت شبکه بطور منطقی در قالب تجهیزات پل ارائه میشوند، و تجهیزات وصل شده به دو جز شبکه ازآدرسهایی از همان شبکه برای انتقال داده و کارهایشان استفاده میکنند.
تنها پکتهایی که باید از یک بخش به بخش دیگر بروند از اینترفیس فیزیکی عبور میکنند. پل آدرسهای MAC تجهیزات وصل شده به هر بخش را میداند، بنابراین میتواند تشخیص دهد که کدام پکتها باید مجددا ارسال شوند. این قابلیت، پل را برای کاهش ترافیک در شبکههای سنگین ایده آل میکند، در واقع پل، دو بخشی که مرتبا به یکدیگر پکت میفرستند را به همدیگر وصل میکند.
امروزه تقریبا تمام شبکههای جدید از تجهیزات پل زدن که سوییچ نامیده میشود استفاده میکنند. این وسیله، یک هاب شبکه با پلی بر روی هر پورت است. فرض میشود تمام بخشها بر روی یک شبکه هستند، اما ترافیک بین بخشها روی تمام بخشها پخش نمیشود، و تنها بین بخشهای مربوطه منتقل میگردد.
چرا باید از پل زدن استفاده کنیم؟
شاید بکارگیری جعبه لینوکس به عنوان یک پل یا سوییچ اختصاصی مزیت خاصی نداشته باشد، چراکه امروزه سوییچها با قابلیت و سرعتی حتی بیش ازقابلیتهای کامپیوتری در حد متوسط، بسیار ارزان قابل دسترس هستند.
اما چون نمیتوان اینترفیسی که بخشی از پل است را برای تجهیزات خاصی اختصاص داد، لذا پکتهایی را که به مقصد آن نمیباشند را هم دریافت میکند که این باعث افزایش بار سیستم میشود. به این دلیل بهتر است به جای تعریف سیستمی به عنوان پل، که کارهای مهم را انجام میدهد، از وسایل اختصاصی پل زدن استفاده کنیم.
پل زدن لینوکس کارهای زیادی میتواند انجام دهد که سوییچها و پلهای دیگر با اینترفیس PPP در شبکه اترنت نمیتوانند.
به تازگی، من نیاز داشتم که بدانم ترافیک بین یک روتر ADSL و تجهیزات کوچک VoIP قرار گرفته در آن چقدر است. فانکشنهای روتر خیلی محدود بودند، بنابراین نمیتوانست اینکار را انجام دهد، در عوض من یک کامپیوتر با سیستم عامل لینوکس را پیدا کردم، و یک کارت شبکه اضافی در آن قرار دادم و بین وسیله VoIP و روتر پل زدم. این باعث شد ترافیک بدون هیچ مشکلی منتقل شود و من توانستم با اجرای tcpdump بر روی لینوکس آنچه را که منتقل میشود ببینم.
لینوکس از پل زدن پشتیبانی میکند
از نسخه 2.4.0 لینوکس به این طرف پشتیبانی از پل زدن وجود دارد. قبلا، برای نسخه 2.2 پچهایی قابل دسترس بودند. به هر حال برای نسخههای بعدی این مشکل مرتفع گردید.
پیکربندی هسته مرکزی (کرنل)
اگر از یک کرنل توزیع شده استفاده میکنید، به احتمال قوی سیستمتان از پلهای اترنت پشتیبانی میکند. در اغلب موارد مانند یک ماجول رفتار میکند که باید قبل از استفاده آن را لود کنید:
# modprobe bridge
اگر نیاز به کامپایل کردن مجدد کرنل دارید، باید طی مراحل پیکربندی “CONFIG_BRIDGE” را به “y” یا “m” تنظیم کنید.
ابزار فضای کاری کاربر (userspace Tools)
امروزه به منظورسادگی نصب، تمام توزیعات معروف ابزار پل زدن userspace بصورت بسته نرمافزاری آمادهای تحت Debian, Ubuntu، Fedora،Redhat Enterprise و SuSE Linux موجود است. این بسته bridge-utils نامیده میشود. بسته نرمافزاری فرمان “brctl” را فراهم میکند که تمام توانمندیهای پل زدن لینوکس را که در اینحا بحث میشوند، کنترل میکند.
اگر سیستمتان دارای بسته نرمافزاری لازم برای کامپایل کردن اولیه نمیباشد، باید سورس را از صفحه sourceforge پل زدن لینوکس دريافت کنید. در زمان نوشتن این مقاله آخرین نسخه بسته نرمافزاری پل زدن قابل استفاده 1.1 بود.
کامپایل کردن و نصب برنامه کاملا ساده و بدون مشکل است:
# tar xzf
bridge-utils-1.1.tar.gz
# cd bridge-utils-1.1
# ./configure --prefix=/usr/local
# make
# su
# make install
به جز GNU autoconf استاندارد، چیز خاصی برای کامپایل کردن و نمایش رفتار بسته نرمافزاری bridge-utils طی اجرا وجود ندارد.
ایجاد کردن و استفاده از پلها
برای سادگی کار، فرض میکنیم که میخواهیم بین دو شبکه اترنت با اینترفیسهای eth0 و eth1 پل بزنیم. شکل 1 یک شبکه ساده را نشان میدهد، جعبه لینوکس پل زدنی ما bridge01است که با دو بخش شبکه، که هر کدام دارای دو سیستم لینوکس میباشند (linux01 و linux02 در سمت اول، و linux03 و linux04 در سمت دوم) در ارتباط است.

قبل از ایجاد کردن پل، باید مطمئن باشیم که هر دو اینترفیس خاموش هستند و آدرس IP برای آنها اختصاص داده نشده است:
# ifconfig
eth0 0 down
# ifconfig eth1 0 down
حال، میتوانیم اینترفیس پل را ایجاد کنیم. در اینجا طریقه استفاده از فرمان “addbr” را که یک اینترفیس پل به نام “br0” را ایجاد میکند، میبینیم :
# brctl addbr br0
هیچ اجبارو محدودیتی در انتخاب نام اینترفیس برای پل وجود ندارد. هر نامی را میتوانید استفاده کنید، فقط دقت کنید که سیستم پلی با آن اسم، نداشته باشد. به هر حال ما پلها را با نام br0،br1 ، تا br4 نامیدیم.
وقتی یکبار اینترفیس پل ایجاد میشود، میتوان اینترفیسهای اترنت واقعی را به عنوان پورت به آن افزود:
# brctl
addif br0 eth0
# brctl addif br0 eth1
این تمام کاری است که باید در اینجا انجام داد. حال، میتوانیم مثل سایر اینترفیسهای شبکه در جعبه لینوکس با اینترفیسهای پل کار کنیم، بنابراین اولین کار این است که با دادن اینترفیسی به آن، وارد شبکهاش کنیم:
# ifconfig br0 10.1.9.1 netmask 255.255.255.0 broadcast 10.1.9.255 up
# ifconfig
br0
br0 Link encap:Ethernet HWaddr 10:00:01:04:71:06
inet addr:10.1.9.1 Bcast:10.1.9.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:49 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:9442 (9.2 KiB)
فرمان “brctl” فانکشن “show” را ایجاد میکند که بدین ترتیب میتوان وضعیت پلها را روی سیستم دید :
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.100001047106 yes eth0
eth1
این مشخصات “bridge id” است. این عدد باSpanning Tree Protocol استفاده میشود، که بعدا راجع به آن بحث میگردد. دراین مرحله، باید بتوانید از پل به ماشینهای client در هر بخش شبکه،ping کنید.
bridge01:/#
ping -c 1 -n 10.1.9.2
PING 10.1.9.2 (10.1.9.2) 56(84) bytes of data.
64 bytes from 10.1.9.2: icmp_seq=1 ttl=64 time=20.6 ms
bridge01:/# ping -c 1 -n 10.1.9.4
PING 10.1.9.4 (10.1.9.4) 56(84) bytes of data.
64 bytes from 10.1.9.4: icmp_seq=1 ttl=64 time=20.6 ms
همچنین امکان فرستادن ترافیک از یکی از ماشینها در یک بخش به بخش دیگر هم وجود دارد:
linux01:/#
ping -c 1 -n 10.1.9.5
PING 10.1.9.5 (10.1.9.5) 56(84) bytes of data.
64 bytes from 10.1.9.5: icmp_seq=1 ttl=64 time=20.6 ms
مهمتر از همه، ترافیک بین دو وسیله روی یک بخش شبکه هم قابل دیدن است، پل ترافیک را در آن بخش شبکه نگه میدارد. این با اجرای tcpdump روی linux03 مادامیکه پکتهای ICMP را از linux01 به linux02 میفرستد میسر است.
linux03:/#
tcpdump -n -i eth0 icmp
linux01:/# ping -n 10.1.9.3
PING 10.1.9.3 (10.1.9.3) 56(84) bytes of data.
64 bytes from 10.1.9.3: icmp_seq=1 ttl=64 time=20.6 ms
اگرپل به درستی کار کند، linux03 نباید ترافیک بین linux01 و linux02 را ببیند، حتی اگر آنها بخشی از یک شبکه منطقی باشند.
از سوی دیگراگرما بخواهیم یک پکت ICMP را به آدرسbroadcast روی شبکه بفرستیم، پل این پاکت را به بخش دوم شبکه میفرستد:
linux01:/#
ping -c 1 -b 10.1.9.255
WARNING: pinging broadcast address
PING 10.1.9.255 (10.1.9.255) 56(84) bytes of data.
64 bytes from 10.1.9.2: icmp_seq=1 ttl=64 time=0.251 ms
linux03:/# tcpdump -n -i eth0 icmp
tcpdump: listening on eth0
19:39:48.273806 10.1.9.2 > 10.1.9.255: icmp: echo request (DF)
19:39:48.273965 10.1.9.4 > 10.1.9.2: icmp: echo reply
19:39:48.274582 10.1.9.5 > 10.1.9.2: icmp: echo reply
این خروجی tcpdump درخواست ICMP broadcast از linux01، و پاسخهایش از linux03 و linux04 را نشان میدهد. linux01 و linux02 هم پاسخهای ICMP خودشان را فرستادهاند، شاید هم درواقع خود پل میفرستد، چون ما آن را تنظیم کردیم تا یک آدرس broadcast روی شبکه داشته باشد.
لازم است یادآوری گردد که پل میتواند بدون آدرسIP هم کار کند. در این حالت، آن پلی بین پاکتها در دوبخش شبکه همانطور که در بالا نشان داده شد میباشد، اما درواقع در هیچ بخشی از شبکه برای تبادل پاکتها در سطح IP نمیتواند عمل کند.
با استفاده از دستور “showmacs” لیستی از وسایل روی شبکه و پورتهایی که به آنها وصل هستند نمایش داده خواهد شد:
bridge01:/# brctl showmacs br0
port no mac
addr is local?
ageing timer
2 10:00:01:02:24:04 no 0.49
1 10:00:01:02:95:35 no 0.98
1 10:00:01:02:34:56 no 3.84
2 10:00:01:03:26:02 no 9.19
1 10:00:01:03:73:03 yes 0.00
2 10:00:01:04:71:06 yes 0.00
این لیست آدرسهای MAC شش کارت اترنت وصل شده به شبکه ما راکه دارای پل میباشد، نشان میدهد، اول کارتهای اترنت در هرکدام از چهار کامپیوتر Client (آنهایی که به عنوان local نامیده نشدهاند) بعد دو کارت اترنت بکارگرفته شده در پل ( که local میباشند).
Ageing Time مدت زمان از آخرین لحظهای که پل یک پکت با آدرس MAC ویژه را دیده است، نشان میدهد. بعد از گذشت مدت زمان لازم، پل آدرس را از دیتا بیس پاک میکند. این برای آن است که شاید ماشینی در این مدت زمان پورت خود را عوض کرده است (برای مثال، یک لپ تاپ که از جایی به جای دیگر منتقل میشود) .
با فرمان “setageingtime” می توان مدت زمان timeout را برای پل تعیین کرد:
# brctl setageingtime br0 40
فرمان بالا مدت زمان timeout یک پل را برای پاک کردن آدرس بعد از 40 ثانیه نشان میدهد.
برداشتن اینترفیسها و پورتهای پل
اگر میخواهید یک پورت از پل را بردارید، brctl فرمان”delif” را انجام میدهد:
# brctl delif br0 eth1
اگر میخواهید یک پل را بطور کامل پاک کنید از فرمان “delbr” استفاده نمایید. باید قبل از انجام اینکار اینترفیس را ببندید،
# ifconfig
br0 down
# brctl delbr br0
Spanning Tree Protocol (STP)
STP توسط سوییچها برای هندل کردن چندین مسیر پل روی یک شبکه استفاه میشود. توانایی داشتن چندین مسیر روی یک شبکه در کنار چیزهای دیگری که قبلا داشتیم در شکل زیر نمایش داده میشود: پل نقطه خرابی سیستم است. اگر خراب شود دو بخش شبکه نمیتوانند با هم درارتباط باشند.

میتوان این را به سادگی با افزودن پل دوم به شبکه همانطور که در شکل 2 نشان داده شده است، برطرف نمود. STP اجازه میدهد، که این دوپل با هم صحبت کنند و تعیین کنند کدام یک فعال باشند، و کدام یک غیر فعال. پل فعال در تمام انتقالهای پکت بین دو بخش شرکت میکند در حالیکه پل غیر فعال تا زمانیکه شریکش دچار مشکل نشود وارد عمل نمیشود.
STP پیچیدهتر از این است که که در مقالهای شبیه این بتوان توضیح داد، بنابراین در اینجا فقط مقدماتی گفته میشود.
همانطور که جلوتر دیدیم، هر پل دارای یک id اختصاصی است، این یک عد 8 بایتی است، دو بایت اول اولویت پل را نشان میدهد، که ما میتوانیم دستی تنظیمش کنیم، و شش بایت بعدی آدرس MAC پل است. تحت لینوکس پل اولویت دار 32768 است. آدرس MAC پل ،کوچکترین آدرس MAC تمام پورتهای پل است.
ما معمولا ID پل را به عنوان یک عدد هگزا دسیمال دو بخشی در نظر میگیریم،ID پل با آدرس MAC به عنوان یک بخش جداگانه در ارتباط میباشد. برای مثال، 8000.100001037303 با اولویت 32768 (هگز8000) و آدرس MAC ،10:00:01:03:73:03.
در شبکهای با چندین پل، پل با کوچکترین bridge id به عنوان پل ریشه (اصلی) انتخاب خواهد شد. پل اصلی نرخ مسیر را برای هر مسیر اضافی (redundant) در شبکه، تعیین میکند. جاییکه لوپهای مسیر کشف میشوند پورتهای پل اصلی در وضعیت "مسدود شده" قرار گرفته و دیگر پاکتی را منتقل نمیکنند.
STP تحت لینوکس، بصورت پیش فرض خاموش است. شما میتوانید با استفاده از “brctl show br0” تعیین کنید که روشن باشد یا نه. وضعیت STP میتواند بصورت زیر تغییر کند:
# brctl stp br0 on
یا
# brctl stp br0 off
برای دیدن اطلاعات بیشتر در باره تنظیم کردن STP روی یک پل از فرمان “showstp” استفاده کنید:
bridge01# brctl showstp br0
br0
bridge id 8000.100001037303
designated root 8000.100001037303
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 0.17 tcn timer 0.00
topology change timer 0.00 gc timer 0.00
flags
eth0 (1)
port id 8001 state forwarding
designated root 8000.100001037303 path cost 100
designated bridge 8000.100001037303 message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
eth1 (2)
port id 8002 state forwarding
designated root 8000.100001037303 path cost 100
designated bridge 8000.100001037303 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
از اطلاعات بالا میتوانیم ببینیم که این پل یک پل شبکه است (لطفا “bridge id” و “designated root” راببینید) و بنابراین، هر دو اینترفیسهایش در حالت انتقال داده (forwarding) هستند. اگر فرمان مشابهی را برروی پل دوم اجرا کنیم، نسبت به این حالت تغییراتی رامشاهده خواهیم کرد.
bridge02#
brctl showstp br0
br0
bridge id 8000.100001087423
designated root 8000.100001037303
root port 1 path cost 100
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 238.59
flags
eth1 (1)
port id 8001 state forwarding
designated root 8000.100001037303 path cost 100
designated bridge 8000.100001037303 message age timer 18.63
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
eth2 (2)
port id 8002 state blocking
designated root 8000.100001037303 path cost 100
designated bridge 8000.100001037303 message age timer 18.63
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
این پل دارایID ، 8000.100001087423 است، مقدار ریشه اختصاص داده شده به آن id پل دیگر را نشان میدهد. این معنی دارد، چون فقط یک پل میتواند در شبکه master باشد. همچنین میبینیم که یکی از پورتهایش مسدود شده است. این تمام نکته کار STP است: آن لوپهای روی شبکه را بر میدارد. اگراین پل پکتی را دریافت کند که نیاز به ارسال به بخش دیگر شبکه داشته باشد، از آن صرف نظر میکند، چون پل دیگر این کار را به عهده گرفته است.
اگر به هر دلیلی، انتخاب root master را که سیستم برگزیده است دوست ندارید، میتوانید با استفاده از فرمان “setbridgeprio” پلهای دیگر را انتخاب کنید. در اینجا پل اولویت دار ما 4096 (1000هگز) میباشد.
# brctl setbridgeprio br0 4096
حال به پلهای ما نگاه کنید، میبینیم که bridge id تغییر کرده است.
# brctl show
bridge name bridge id STP enabled interfaces
br0 1000.100001047106 yes eth0
eth1
همچنین ممکن است که به هر پورت ارزش مشخصی را بدهید. شاید جایی لازم باشد، برای مثال یک لینک با سرعت کمتر به جای یک لینک سریع که همه خواهانش هستند، بطور اتوماتیک انتخاب میشود که به عنوان لینک اختصاصی کار کند. لینکهایی با ارزشهای پایینتر در مقایسه با لینکهای سریع برای استفاده انتخاب میشوند.
# brctl setportprio br0 eth1 50
با توجه به توپولوژی شبکه پل، ممکن است بعضی از پورتهای پل وضعیتشان را از حالت“forwarding” به “blocking” تغییر دهند. مادامیکه چنین چیزی اتفاق میافتد، بخش شبکه برای مدت زمان کوتاهی غیر قابل دسترس خواهد بود، اما بلافاصله وضعیت ثابت شده و سیستم قابل دسترس خواهد شد.
برای اطلاعات بیشتر راجع به Spanning Tree Protocol به مشخصات فنی IEEE 802.1D مراجعه کنید.
نتیجه گیری
خوشبختانه حال شما اطلاعات اولیه مفیدی برای پل زدن تحت لینوکس دارید و میتوانید برای خود حتی شبکهای کمی پیچیدهتر، را طراحی نمایید. شاید بتوانید با استفاده ازUser Mode Linux یا QEMU تعدادی ماشین مجازی را بصورت دستی بسازید و بین شبکههایشان پل بزنید. این به شما در درک مفاهیم شبکه بندی و پل زدن از نظر توپولوژی شبکه بسیار کمک میکند.