مدیریت ترافیک با استفاده از ALTQ:

ALTQ مخفف alternate queuing است که یک مکانیزم بسیار کارا در مدیریت ترافیک است، این پروژه تا قبل از pf به صورت جداگانه وجود داشته و بعدا به بخش pf اضافه شده است. مدیریت کردن ترافیک یک امر بسیار مهم و حیاتی در مدیریت کردن منابع و امکانات شبکه به تناسب نیاز شماست. هسته این مدیریت با ایجاد صف برای بافر کردن ترافیک ایجاد شده، بسته ها در صف های مورد نظر در انتظار تردد قرار می گیرند تا بسته هایی که دارای اولویت بالاتری هستند عبور کنند و یا به دلیل محدود بودن میزان باند مصرفی ترافیک باید در صف انتظار قرار گیرند تا سرویس های دیگر از فضای خود استفاده کنند و همه فضا در اختیار یک سرویس قرار نگیرد. این صف به کارت شبکه ای که مشخص کرده اید به اصطلاح می چسبد و مدیریت ترافیک را به تناسب پهنای باند همان کارت شبکه انجام می دهد. صف ها گاه در قالب الویت مدیریت می شوند و گاه در قالب میزان پهنای باند و در بعضی از موارد از هردوی این عامل ها برای مدیریت ترافیک استفاده می کنند. در حالت پیش فرض راه اندازی TCP/IP و بدون استفاده از سرویس ALTQ بسته ها به حالت fifo مدیریت و ارسال می شوند، fifo مخفف first in first out است این حالت به آن معناست که هر بسته ای که زودتر دریافت می شود زودتر هم ارسال می شود و هیچ الویت و محدودیتی ندارد. در ادامه به توضیح در مورد انواع صف می پردازیم.

حالت priq) priority based queues):

در این نوع از صف فقط اولویت بندی در مورد نوع صف و ارسال صورت می گیرد. این اولویت بین رنج ۰ تا ۱۵ متغیر است و بالاترین عدد در این بخش اولویت بیشتری دارد و استحقاق ارسال سریع تر است.

حالت cbq) class based queues):

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

حالت hfsc:
این حالت از نظم و ترتیب استفاده می کند. از الگوریتم Hierarchical Fair Service Curve (HFSC) برای این منظور که منصفانه پهنای باند در بین صف ها تقسیم بندی شود.

altq on interface type [options … ] main_queue { sub_q1, sub_q2 ..}
queue sub_q1 [ options … ]
queue sub_q2 [ options … ] { subA, subB, … }
[…]
pass [ … ] queue sub_q1
pass [ … ] queue sub_q2

همان طور که مشاهده می کنید دو حالت cbq و hfsc دارای سطح های زیر صفی هستند در صورتی که حالت priq دارای یک سطح بوده و در این بخش flat به حساب می آید.

راه اندازی ALTQ:

راه اندازی ALTQ داراری مراحل مختلفی است که بسته به نوع سیستم عامل شما متغیر بوده و داراری تنظیمات خاص خود است در ادامه به راه اندازی این سرویس در سیستم عامل های مختلف اشاره خواهم کرد.

راه اندازی ALTQ در OpenBSD:

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

راه اندازی ALTQ در FreeBSD:

در FreeBSD این سرویس به صورت پیش فرض در هسته قرار ندارد و شما باید آن را در هسته کامپایل کنید برای این کار باید خطوط زیر را در فایل اصلی هسته نوشته و هسته را دوباره کامپایل، نصب و سیستم را با استفاده از هسته جدید راه اندازی کنید، این خطوط در زیر نمایش داده شده اند البته این خطوط در فایل اصلی هسته وجود دارند و فقط نیاز است که شما آنها را از حالت کامنت خارج کنید:

options ALTQ
options ALTQ_CBQ # Class-Based Queuing (CBQ)
options ALTQ_RED # Random Early Detection (RED)
options ALTQ_RIO # RED In/Out
options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
options ALTQ_PRIQ # Priority Queuing (PRIQ)
options ALTQ_NOPCC # Required for SMP build

راه اندازی ALTQ درNetBSD:

در این سیستم عامل مثل FreeBSD شما نیاز به کاپایل کردن هسته با خطوط زیر دارید:

options ALTQ # Manipulate network interfaces’ output queues
options ALTQ_CBQ # Class-Based Queuing
options ALTQ_HFSC # Hierarchical Fair Service Curve
options ALTQ_PRIQ # Priority Queuing
options ALTQ_RED # Random Early Detection

مفهوم صف در PF:

صف محلی است که یک سری مقادیر در آن ذخیره می شوند و مدتی صبر می کنند تا به مرحله پردازش برسند. در سیستم های شبکه زمانی که یک بسته از طرف کاربر ارسال می شود در صفی قرار می گیرد تا سیستم عامل آن را پردازش کند. برای مثال فرض کنید که یک کاربر دو برنامه تحت شبکه به نام های SSH و FTP را راه اندازی کرده است، بسته های مربوط به سرویس SSH قبل از سرویس FTP مورد پردازش قرار می گیرد زمانی که یک دستور در محیط ssh client صادر می شود و هم زمان شما از سرویس FTP استفاده می کنید در سرویس FTP یک مکث کوتاه دریافت می کنید تا ابتدا بسته SSH مورد پردازش قرار گیرد. حال اگر این امر در روتر شبکه اتفاق بیفتد و تعداد زیادی از بسته های FTP در صف ارسال باشند در این میان بسته SSH ارسال شود، این بسته به دلیل ترافیک بالای صف به احتمال زیاد از بین خواهد رفت. به همین دلیل است که مفهوم و استفاده صف  در به اشتراک گذاری پهنای باند شما بسیار مهم است. در بسیاری از موارد این صف فقط به بسته هایی مربوط می شوند که از سیستم خارج می شوند این امر مفید است و به بسته های دریافتی کاری ندارند چون این بسته در صف خروج  قرار گرفته اند.

زمان بندی کننده یا Schedulers:

این Schedulers است که تصمیم می گیرد چه صفی با چه اولویتی مورد پردازش قرار گیرد، به صورت پیش فرض OpenBSD از زمان بندی کننده اولین ورودی اولین خروجی یا همان FIFO استفاده می کند. این مدیرت درست مثل صف در باجه یک سوپرمارکت بزرگ است اولویت اشخاصی که وارد صف می شوند اول به پشت باجه می رسند و دیگران به پشت فرد اول اضافه می شوند و در انتظار نوبت می مانند، اگر هم حجم صف پر شود دیگر کسی را قبول نمی کند. به این شیوه به اصطلاح tail-drop می گویند.

علاوه بر این مدل صف، دو مدل صف دیگر هم هست که OpenBSD از آن پشتیبانی می کند:
• الویت بندی صف (Priority Queueing)

• کلاس بندی صف (Class Based Queueing)
در ادامه با هر کدام از این مدیرت صف آشنا می شوید.

حالت Class Based Queueing:
در این حالت همه پهنای باند کارت شبکه به چند صف با کلاس های مختلف تقسیم می شود به هر صف هم می شود ترافیکی به تناسب آدرس مبدا و مقصد، شماره پورت و پروتکل ها اختصاص داد. این نوع صف یک ساختار سلسه مراتبی دارد. در این ساختار شما نیاز به یک صف اصلی دارید که همه پهنای باند به آن اختصاص داده می شود و به آن به اصطلاح root queue می گویند. در در زیر همین صف اصلی بچه صف ها ( Child queues) وجود دارند که هر کدام می توانند یک سرویس خاص را مدیریت کند و یک مقدار خاص از پهنای باند کلی را در اختیار خواهد داشت. در زیر یک طرح کلی از این نوع صف بندی را مشاهده می کنید:

Root Queue (2Mbps)

Queue A (1Mbps)

Queue B (500Kbps)

Queue C (500Kbps)

در این مثال پهنای باند اصلی ۲ مگابایت بر ثانیه است که همین صف به ۳ صف دیگر تقسیم شده است و مجموع همه این ۳ صف معادل صف اول و ابتدایی است. شما همچنین در این ساختار می توانید از ساختار صف در صف هم استفاده کنید و هر صف را به زیر صف تقسیم کنید و هر صف درجه دوم را به یک کاریر اختصاص دهید. به این روش دیگر پهنای باند هر صفی پهنای باند صف دیگری را مورد استفاده قرار نمی دهد، این ساختار در شکل زیر نمایش داده شده است:

Root Queue (2Mbps)

UserA (1Mbps)

ssh (50Kbps)

bulk (950Kbps)

UserB (1Mbps)

audio (250Kbps)

bulk (750Kbps)

http (100Kbps)

other (650Kbps)

در این مثال به این نکته توجه کنید که مجموعه زیر صف های درجه سوم از زیر صف های درجه دوم نباید بیشتر باشد و مجموع زیر صف های درجه دوم هم نباید از صف اصلی بیشتر شود.

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

Root Queue (2Mbps)

UserA (1Mbps)

ssh (100Kbps)

ftp (900Kbps, borrow)

UserB (1Mbps)

در این مثال اگر سرویس FTP پهنای باند بیشتری از آن مقداری که به آن اختصاص داده شده است نیاز داشته باشد و پهنای باند سرویس SSH در حال حاضر آزاد باشد چون از گزینه borrow در صف FTP استفاده شده است این سرویس می تواند به صورت موقت از این پهنای باند آزاد استفاده کند و به محض فعال شده SSH پهنای باند قرض داده شده به این سرویس بازمی گردد.

شما می توانید در حالت صف بندی CBQ از حالت اولویت بندی هم استفاده کنید. در این روش صف هایی با اولویت بالا ترجیح داده می شوند به صف های با اولویت پایین، این حالت در صف هایی ایجاد می شود که یک صف اصلی دارند. صف هایی هم که دارای اولویت یکسانی هستند از الگوریتم round-robin برای سرویس دهی استفاده می کنند. در زیر یک مثال از این بخش را مشاهده می کنید:

Root Queue (2Mbps)

UserA (1Mbps, priority 1)

ssh (100Kbps, priority 5)

ftp (900Kbps, priority 3)

UserB (1Mbps, priority 1)

در این مثال CBQ را الگوریتم round-robin برای تقسیم صف در بین دو زیر صف UserA و UserB استفاده می کند و هیچ کدام نسبت به دیگری اولویتی ندارند. زمانی که صف UserA مورد پردازش قرار می گیرد CBQ وارد راه اندازی زیر صف ها می شود. در این مثال ترافیک سرویس SSH دارای الویت بالاتری است و در نتیجه به آن زودتر از سرویس FTP پهنای باند تعلق می گیرد. حال اگر این الویت ها وجود نداشت همه به صورت یکسان پردازش می شدند.

حالت Queueing Priority:
در این حالت چند صف از صف اصلی یا همان root انشعاب گرفته می شود و این صف ها دارای الویت هستند، صفی که اولیت عددی بالاتری داشته باشد به آن سرویس زودتری ارایه می شود و اگر هم دو صف دارای الویت یکسانی باشند از الگوریتم round-robin برای تقسیم پهنای باند استفاده می شود. به این نوع از صف بندی به اختصار PRIQ می گویند. حالت صف بندی در این حالت برخلاف حالت قبلی شاخه نبوده و به صطلاح flat است.  این بخش به این صورت عمل می کند که یک صف اصلی داریم که همه پهنای باند را مشخص می کند و این صف به زیر صف هایی تقسیم می شود که با الویت از هم تفکیک می شوند. در زیر یک مثال در این زمینه را مشاهده می کنید:

Root Queue (2Mbps)

Queue A (priority 1)

Queue B (priority 2)

Queue C (priority 3)

در این مثال یک صف اصلی وجود دارد که کل پهنای باند که ۲ مگابایت بر ثانیه است را به خود اختصاص داده است و در بخش های بعدی ۳ زیر شاخه تعریف شده است که صفی که بالاترین الویت عددی را دارد زودتر از دیگر صف ها سرویس دریافت می کند، بعد از به اتمام رسیدن همه بسته های مربوط به صف مورد نظر الویت بعدی در دستور کار قرار می گیرد. این حالت در حقیقت همان حالت FIFO است به همراه یک اولویت بندی خلاصه برای صف ها. در راه اندازی این بخش باید بسیار دقت کنید چون هر بسته یک مدت زمان مشخصی می تواند در صف قرار بگیرد اگر این مدت طولانی تر شود بسته به اصطلاح drop می شود. در بخش پایانی این مقاله و بعد آشنا شدن با ساختار های صف به این بخش بیشتر می پردازیم.

قابلیت Random Early Detection:

RED یک الگوریتم جلوگیری کننده از ازدحام است، کار اصلی این این الگوریتم این است که به دقت بر صف ها نطارت و از پر شدن آنها جلوگیری کند. این بخش به طور مکرر و مداوم طول صف ها را محاسبه می کند و این مقدار را با آستانه سطح بالا وآستانه سطح پایین مقایسه می کند. اگر این مقدار میانگین از مقدار حد پایین کمتر شود هیچ بسته ای به اصطلاح drop نمی شود و اگر میانگین ترافیک صف ها به حد آستانه بالایی برسد بسته های جدید drop خواهند شد. در عکس زیر یک طرح اولیه از این الگوریتم را مشاهده می کنید، البته به این نکته توجه کنید این الگوریتم فقط در بخش tcp مورد استفاده قرار می گیرد و در پروتکل های udp و icmp قابل استفاده نیست:

RED

قابلیت Explicit Congestion Notification:

پیکربندی صف ها:

از ورژن ۳٫۰ به بعد OpenBSD قابلیت ALTQ یک بخشی از سیستم شده است و در پایه سیستم قرار گرفته است و با PF به خوبی سازگار و راه اندازی شده است. در این ALTQ می توانید هر دو نوع از صف های CBQ وPRIQ را داشته باشید. چون ALTQ ادغام شده با PF، درنتیجه PF باید راه اندازی شود تا این بخش هم فعال شود. در قسمت های قبلی هم با راه اندازی PF آشنا شدید.

صف ها در فایل pf.conf پیکربندی و از طریق همین فایل راه اندازی می شود. دو فرمان برای پیکربندی صف وجود دارد که در زیر مختصری با آنها آشنا می شوید:

  • altq on: این بخش باعث راه اندازی صف اصلی بروی کارت شبکه می شود و نوع زمان بندی را هم در این بخش مشخص می کنید.
  • queue: از این بخش برای تعیین بچه صف ها استفاده می شود.

دستور altq on:
این دستور به صورت زیر نوشته می شود و در ادامه با همه بخش های این فرمان آشنا می شوید:

altq on interface scheduler bandwidth bw qlimit qlim tbrsize size queue { queue_list }

بخش interface: در این قسمت نام کارت شبکه ای را که شما قصد دارید صف اصلی را در آن پیکربندی کنید را می نویسید.
بخش scheduler: در این بخش شما روش زمان بندی را مشخص می کنید که یکی از دو کلید cbq و یا priq است که هر کدام از این دو در بخش های قبلی توضیح داده شده.
بخش bw: در این بخش کل پهنای باندی که زمان بندی به آن نیاز دارد تا به صف اصلی اختصاص داده شود را مشخص می کنید. شما در این بخش می توانید از Kb برای کیلوبایت، Mb برای مگابایت و از Gb برای گیگابایت برای نمایش کل پهنای باند استفاده کنید.
بخش qlim: شما در این بخش می توانید بیشترین تعداد بسته هایی که در صف قرار بگیرند را تعیین کنید. این بخش انتخابی است و به صورت پیش فرض عدد ۵۰ برای این بخش در نظر گرفته شده.
بخش size: این بخش مربوط می شود به سایز
بخش queue_list: این بخش لیستی از زیر صف ها یا همان بچه صف ها را نمایش می دهد که باید در این صف اصلی ایجاد شود.
در زیر یک مثال از این بخش را مشاهده می کنید:

altq on fxp0 cbq bandwidth 2Mb queue { std, ssh, ftp }

در این مثال شما یک صف اصلی با قابلیت زمان بندی cbq ایجاد کردید که کل پهنای باند این صف ۲ مگابایت است و به ۳ زیر صف std ،ssh و ftp تقسیم می شود. در ادامه شما با یک مثال در زمینه زیر صف ها آشنا می شوید.

دستور queue:

queue name [on interface] bandwidth bw [priority pri] [qlimit qlim] scheduler ( sched_options ) { queue_list }

بخش name: دراین بخش نام صف مشخص می شود، این نام ها باید با هرکدام از زیر صف هایی که در فرمان altq on مشخص شده است یکی باشد.

بخش interface: این بخش مشخص کننده نام کارت شبکه ای است که قرار است صف در آن اعمال شود، البته این بخش اختیاری و اگر مشخص نشود به همه کارت های شبکه این صف اعمال می شود.

بخش bw: در این بخش کل پهنای باندی که باید به صف اختصاص داده شود مشخص می شود. البته برای نمایش این مقدار از کلمات Kb ، Mb و Gb می توانید استفاده کنید. البته این امکان برای شما وجود دارد که درصد را هم در این بخش مشخص کنید و با استفاده از درصد پهنای باند را تقسیم کنید. اگر این بخش تعیین نشود کل فضا اختصاص داده خواهد شد.

بخش pri: دراین بخش شما عدد مربوط به الویت را تعیین می کنید. برای صف های CBQ این مقدار بین دو عدد ۰ تا ۷ است و برای صف های PRIQ این عدد در بین دو عدد ۰ تا ۱۵ تعیین می شود، زمانی که شما هیچ عددی را در این بخش قرار ندهید به صورت خودکار عدد ۱ برای این بخش تعیین می شود.

بخش qlim: در این بخش شما بیشترین تعداد بسته هایی که در صف ها نگه داری شوند را تعیین می کنید. البته اگر مقداری را مشخص نکنید عدد ۵۰ برای این بخش به صورت پیش فرض تعیین می شود.

بخش scheduler: در این بخش نوع صف تعیین می شود. که یکی از دو حالت CBQ یا PRIQ است و باید این بخش حتما با اصلی هم خوانی داشته باشد.

بخش sched_options: در این بخش رفتار scheduler را تعیین می کنید.

بخش default: هر بسته ای که با هیچ یک از رول های شما مچ نشود در این صف قرار می گیرد و فقط یک صف از این نوع می تواند وجود داشته باشد.
بخش red: این بخش قابلیت RED را برروی صف فعال می کند.
بخش ecn: این بخش قابلیت ENC را که در بخش قبلی توضیح داده شده است را فعال می کند.
بخش borrow: اگر این بخش در صفی قرار گیرد به آن صف این قابلیت را می دهد که اگر در صف اصلی ترافیکی وجود داشت آن را قرض بگیرد. البته این قابلیت فقط در نوع صف های CBQ مورد استفاده قرار می گیرند.

بخش queue_list: در این بخش شما لیست زیر صف ها و یا صف های کوچکتر را مشخص می کنید. این حالت فقط در نوع صف CBQ اتفاق می افتد.
در زیر یک مثال در این مورد مشاهده می کنید:

queue std bandwidth 50% cbq(default)
queue ssh bandwidth 25% { ssh_login, ssh_bulk }
queue ssh_login bandwidth 25% priority 4 cbq(ecn)
queue ssh_bulk bandwidth 75% cbq(ecn)
queue ftp bandwidth 500Kb priority 3 cbq(borrow red)

همان طور که در مثال بالا مشاهده می کنید صف ssh خودش به دو بخش زیر صف تقسیم شده است.

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

pass out on fxp0 proto tcp to port 22

برای اینکه بسته ایی که با این رول یکی می شود وارد صف مخصوصی که در بخش قبل ایجاد کرده اید شود باید رول را به صورت زیر تغییر دهید:

pass out on fxp0 proto tcp to port 22 queue ssh

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

مثال اول یک شبکه کوچک:
این مثال را در شکل زیر مشاهده می کنید:

Network1

در این مثال OpenBSD به عنوان یک Internet gatewayبرای یک شبکه کوچک خانگی استفاده می شود که ۳ دستگاه کامپیوتر در آن وجود دارد.OpenBSD هم کار مدیریت بسته ها را انجام می ده و هم کار Nat را بر عهده دارد و این شبکه به وسیله یک مودم ADSL به شبکه اینترنت وصل شده که دانلود آن ۲مگابایت و آپلود آن ۶۴۰ کیلوبایت است.
در این مثال صفهای زیر باید ایجاد شود:
* دستگاه Bob باید دارای ۸۰ کیلوبایت پهنای باند دانلود باشد تا به بازی های آنلاین بپردازد، این اجازه هم به سیستم او داده شود تا در صورت وجود پهنای باند اضافی آن را قرض بگیرد.
*ترافیک ssh و message بالاترین اولویت را نسبت به سایر ترافیک ها داشته باشند.
* ترافیک DNS در درجه دوم الویت ترافیکی باشد.
* خروج بسته هایی که شامل اطاعات TCP ACK هستند بیشترین اولویت را در خروج از سایر بسته ها داشته باشند.
با این درخواست های بالا رول ها و متغیرهای زیر را در فایل pf.conf ایجاد کنید.

# enable queueing on the external interface to control traffic going to
# the Internet. use the priq scheduler to control only priorities. set
# the bandwidth to 610Kbps to get the best performance out of the TCP
# ACK queue.

altq on fxp0 priq bandwidth 610Kb queue { std_out, ssh_im_out, dns_out, \
tcp_ack_out }

# define the parameters for the child queues.
# std_out – the standard queue. any filter rule below that does not
# explicitly specify a queue will have its traffic added
# to this queue.
# ssh_im_out – interactive SSH and various instant message traffic.
# dns_out – DNS queries.
# tcp_ack_out – TCP ACK packets with no data payload.

queue std_out priq(default)
queue ssh_im_out priority 4 priq(red)
queue dns_out priority 5
queue tcp_ack_out priority 6

# enable queueing on the internal interface to control traffic coming in
# from the Internet. use the cbq scheduler to control bandwidth. max
# bandwidth is 2Mbps.

altq on dc0 cbq bandwidth 2Mb queue { std_in, ssh_im_in, dns_in, bob_in }

# define the parameters for the child queues.
# std_in – the standard queue. any filter rule below that does not
# explicitly specify a queue will have its traffic added
# to this queue.
# ssh_im_in – interactive SSH and various instant message traffic.
# dns_in – DNS replies.
# bob_in – bandwidth reserved for Bob’s workstation. allow him to
# borrow.

queue std_in bandwidth 1.6Mb cbq(default)
queue ssh_im_in bandwidth 200Kb priority 4
queue dns_in bandwidth 120Kb priority 5
queue bob_in bandwidth 80Kb cbq(borrow)

# … in the filtering section of pf.conf …

alice = “192.168.0.2”
bob = “192.168.0.3”
charlie = “192.168.0.4”
local_net = “192.168.0.0/24”
ssh_ports = “{ 22 2022 }”
im_ports = “{ 1863 5190 5222 }”

# filter rules for fxp0 inbound
block in on fxp0 all

# filter rules for fxp0 outbound
block out on fxp0 all
pass out on fxp0 inet proto tcp from (fxp0) queue(std_out, tcp_ack_out)
pass out on fxp0 inet proto { udp icmp } from (fxp0)
pass out on fxp0 inet proto { tcp udp } from (fxp0) to port domain \
queue dns_out
pass out on fxp0 inet proto tcp from (fxp0) to port $ssh_ports \
queue(std_out, ssh_im_out)
pass out on fxp0 inet proto tcp from (fxp0) to port $im_ports \
queue(ssh_im_out, tcp_ack_out)

# filter rules for dc0 inbound
block in on dc0 all
pass in on dc0 from $local_net

# filter rules for dc0 outbound
block out on dc0 all
pass out on dc0 to $local_net
pass out on dc0 proto { tcp udp } from port domain to $local_net \
queue dns_in
pass out on dc0 proto tcp from port $ssh_ports to $local_net \
queue(std_in, ssh_im_in)
pass out on dc0 proto tcp from port $im_ports to $local_net \
queue ssh_im_in
pass out on dc0 to $bob queue bob_in

مثال دوم یک شبکه بزرگتر:

Network2

در این مثال OpenBSD به عنوان یک فایروال برای یک شبکه بزرگتر ایفای نقش می کند. در این کمپانی یک سرور www در محیط DMZ قرار دارد. این سایت با استفاده از خط T1 به سایر شبکه ها وصل می شود. دستگاه boss از سرویس میل و وب استفاده می کند. خظ T1 دارای پهنای باند ۱٫۵ مگابایت برای هر دو طرف ارتباط دارد. همه دستگاه ها در این شبکه از کارت شبکه های اترنت با پهنای باند ۱۰۰ مگابیت استفاده می کنند.

در این بخش آدمین شبکه تصمیم می گیرد که محدودیت های زیر را اعمال کند:
۱٫همه ترافیک های بین سرور www و اینترنت را ۵۰۰ کیلو بایت محدود شود. به هر جهت این محدودیت به صورت زیر اعمال شود:

::تخصیص دادن ۲۵۰کیلو بایت برای ترافیک http

::تخصیص دادن ۲۵۰ کیلو بایت برای سایر ترافیک ها غیر از http

::هر کدام از این دو صف در صورت وجود داشتن ترافیک در صف دیگری بتوانند ترافیک دیگری را قرض بگیرند ترافیک خود را تا ۵۰۰ کیلو بایت بالا ببرند.

::به ترافیک HTTP بین سرور WWW و اینترنت اولویت بالاتری نسبت به سایر انواع ترافیک بین سرور WWW و اینترنت داده شود مانند ارسال FTP.

::ترافیک بین سرور www و شبکه داخلی تا سقف ۱۰۰ مگا بایت هم برسد.

۲٫ رزرو شود ۵۰۰ کیلو بایت برای دپارتمان IT تا بتوانند برای بروز رسانی برنامه ها از آن استفاده کنند و اگر هم نیاز باشد از ۵۰۰ کیلو بایت اضافه دیگر هم بتوانند استفاده کنند.

۳٫ ترافیک بین کامپیوترbosss و اینترنت اولویت بالاتری نسبت به ترافیک دیگران به اینترنت داشته باشد.

حال باید رول های زیر را در فایل pf.cof به این صورت قرار گیرد:

# enable queueing on the external interface to queue packets going out
# to the Internet. use the cbq scheduler so that the bandwidth use of
# each queue can be controlled. the max outgoing bandwidth is 1.5Mbps.

altq on fxp0 cbq bandwidth 1.5Mb queue { std_ext, www_ext, boss_ext }

# define the parameters for the child queues.
# std_ext – the standard queue. also the default queue for
# outgoing traffic on fxp0.
# www_ext – container queue for WWW server queues. limit to
# ۵۰۰Kbps.
# www_ext_http – http traffic from the WWW server; higher priority.
# www_ext_misc – all non-http traffic from the WWW server.
# boss_ext – traffic coming from the boss’s computer.

queue std_ext bandwidth 500Kb cbq(default borrow)
queue www_ext bandwidth 500Kb { www_ext_http, www_ext_misc }
queue www_ext_http bandwidth 50% priority 3 cbq(red borrow)
queue www_ext_misc bandwidth 50% priority 1 cbq(borrow)
queue boss_ext bandwidth 500Kb priority 3 cbq(borrow)

# enable queueing on the internal interface to control traffic coming
# from the Internet or the DMZ. use the cbq scheduler to control the
# bandwidth of each queue. bandwidth on this interface is set to the
# maximum. traffic coming from the DMZ will be able to use all of this
# bandwidth while traffic coming from the Internet will be limited to
# ۱٫۰Mbps (because 0.5Mbps (500Kbps) is being allocated to fxp1).

altq on dc0 cbq bandwidth 100% queue { net_int, www_int }

# define the parameters for the child queues.
# net_int – container queue for traffic from the Internet. bandwidth
# is 1.0Mbps.
# std_int – the standard queue. also the default queue for outgoing
# traffic on dc0.
# it_int – traffic to the IT Dept network; reserve them 500Kbps.
# boss_int – traffic to the boss’s PC; assign a higher priority.
# www_int – traffic from the WWW server in the DMZ; full speed.

queue net_int bandwidth 1.0Mb { std_int, it_int, boss_int }
queue std_int bandwidth 250Kb cbq(default borrow)
queue it_int bandwidth 500Kb cbq(borrow)
queue boss_int bandwidth 250Kb priority 3 cbq(borrow)
queue www_int bandwidth 99Mb cbq(red borrow)

# enable queueing on the DMZ interface to control traffic destined for
# the WWW server. cbq will be used on this interface since detailed
# control of bandwidth is necessary. bandwidth on this interface is set
# to the maximum. traffic from the internal network will be able to use
# all of this bandwidth while traffic from the Internet will be limited
# to 500Kbps.

altq on fxp1 cbq bandwidth 100% queue { internal_dmz, net_dmz }

# define the parameters for the child queues.
# internal_dmz – traffic from the internal network.
# net_dmz – container queue for traffic from the Internet.
# net_dmz_http – http traffic; higher priority.
# net_dmz_misc – all non-http traffic. this is also the default queue.

queue internal_dmz bandwidth 99Mb cbq(borrow)
queue net_dmz bandwidth 500Kb { net_dmz_http, net_dmz_misc }
queue net_dmz_http bandwidth 50% priority 3 cbq(red borrow)
queue net_dmz_misc bandwidth 50% priority 1 cbq(default borrow)

# … in the filtering section of pf.conf …

main_net = “192.168.0.0/24”
it_net = “192.168.1.0/24”
int_nets = “{ 192.168.0.0/24, 192.168.1.0/24 }”
dmz_net = “10.0.0.0/24”

boss = “192.168.0.200”
wwwserv = “10.0.0.100”

# default deny
block on { fxp0, fxp1, dc0 } all

# filter rules for fxp0 inbound
pass in on fxp0 proto tcp from any to $wwwserv port { 21, \
> 49151 } queue www_ext_misc
pass in on fxp0 proto tcp from any to $wwwserv port 80 queue www_ext_http

# filter rules for fxp0 outbound
pass out on fxp0 from $int_nets
pass out on fxp0 from $boss queue boss_ext

# filter rules for dc0 inbound
pass in on dc0 from $int_nets
pass in on dc0 from $it_net queue it_int
pass in on dc0 from $boss queue boss_int
pass in on dc0 proto tcp from $int_nets to $wwwserv port { 21, 80, \
> 49151 } queue www_int

# filter rules for dc0 outbound
pass out on dc0 from dc0 to $int_nets

# filter rules for fxp1 inbound
pass in on fxp1 proto { tcp, udp } from $wwwserv to port 53

# filter rules for fxp1 outbound
pass out on fxp1 proto tcp to $wwwserv port { 21, \
> 49151 } queue net_dmz_misc
pass out on fxp1 proto tcp to $wwwserv port 80 queue net_dmz_http
pass out on fxp1 proto tcp from $int_nets to $wwwserv port { 80, \
۲۱, > 49151 } queue internal_dmz