توی دبیان بر خلاف توزیع های مبتنی بر ردهت هیچ اسکریپتی در init برای مدیریت فایروال نوشته نشده است. شاید بگید این یه مشکل هست یا یه کمبود، ولی دلیلی که می یارند (و البته من هم قبول دارم) اینه که ایجاد اسکریپت init به شکلی که در توزیع های مختلف هست، باعث می شه که شما نتونید از امکانات واقعی یک اسکریپت استفاده کنید. البته به خاطر اینکه همه از دستور iptables-save برای ذخیره استفاده می کنند و این موضوع امکان اضافه کردن شرط یا هر دستور دیگه را در اسکریپت فایروال غیر ممکن می کنه.
من تصمیم گرفتم نحوه نوشتن اسکریپت init برای فایروال با توجه به استاندارد LSBinit و همچنین در نظر گفتن ساختار dependency base جدید در سرویس ها اینجا بیارم.
LSB
LSB توسط بنیاد لینوکس شروع شد تا سعی کنه تفاوت ها را در بین توزیع های مختلف به حداقل برسونه. نحوه نگارش اسکریپت init هم یکی از این استاندارهاست که در LSB تعریف شده.
صورت مسئله
قرار یک اسکریپت inti برای iptables بنویسیم که بتونیم فایروال را باکمک آن مدیریت کنیم. یعنی زمان بالاآمدن سیستم به طور خودکار فایروال اجرا شود، امکان start|stop|restart برای آن وجود داشته باشد.
header
نوشتن اسکریپت را با نوشتن بخش اول اسکریپت آغاز می کنیم. این بخش یک ساختار ثابت دارد و در صورتی که رعایت نشود با خطای مفسر های این اسکریپت مواجه می شوید. ساختار به شکل زیر است:
### BEGIN INIT INFO
# Provides: firewall
# Required-Start: networking syslog
# Required-Stop: networking
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop firewall
# Description:
### END INIT INFO
اما بخش های مختلف این header
Provides
این بخش یک نام اختیاری برای سرویس است
Required-start
سرویسهای که سرویس ما به آنها وابسته است یا می خواهیم این سرویس بعد از آنها راهاندازی شود. نامی که برای سرویسهای مورد نظر وارد می کنید باید همان نامی باشد که در بخش Provides آن سرویس آورده شده است
Required-stop
نام سرویس هایی که بهتر است سرویس ما قبل از آنها stop شود
Default-start و Default-stop
نام runlevel هایی است که قرار است سرویس در آنها start یا stop شود
بقیه گزینه ها هم که فکر می کنم خودشون گویا هستند
توابع start|stop
برای این منظور می توان از توابع موجود در lib/lsb/init-functions/ استفاده کرد. ولی به دلیل آنکه من در حال حاضر تسلطی به نحوه استفاده از این توابع نداشتم از توابع خودم استفاده کردم. در صورتی که علاقه داشتید با این توابع بیشتر آشنا بشید از این لینک استفاده کنید.
IPT=/sbin/iptables
function start_firewall
{
echo “Starting firewall…
$IPT -P INPUT DROP
$IPT -A INPUT ! -i eth0 -j ACCEPT
$IPT -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
}function stop_firewall
{
#Set default policies to ACCEPT everything
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT
$IPT -t nat -P OUTPUT ACCEPT
$IPT -t nat -P PREROUTING ACCEPT
$IPT -t nat -P POSTROUTING ACCEPT
$IPT -t mangle -P INPUT ACCEPT
$IPT -t mangle -P OUTPUT ACCEPT
$IPT -t mangle -P FORWARD ACCEPT
$IPT -t mangle -P PREROUTING ACCEPT
$IPT -t mangle -P POSTROUTING ACCEPT#Zero out all counters
$IPT -Z
$IPT -t nat -Z
$IPT -t mangle -Z# Flush all rules, delete all chains
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
echo “Stopping firewall…”
}
بخش آخر
خوب پس از تعریف توابع start|stop نوبت این میرسه که بدنه اصلی اسکریپت را بنویسیم
case “$1” in
start)
start_firewall
;;
stop)
stop_firewall
;;
restart)
stop_firewall;
start_firewall
;;
*)
echo “Usage: /etc/init.d/firewall {start|stop|restart)”
esac
اگر دقت کنید در case برای restart از هر دو تابع تعریف شده به صورت همزمان استفاده شده و در ضمن پیش بینی زمانی که کاربر پارامتر ها را به اشتباه استفاده کرده باشد نیز شده است.
نکته ای که هست اینه که اگه می خواهید اسکریپتتون یک اسکریپت حرفه ای باشه و در ضمن استاندارد ها را رعایت کنید، کار دیگهای که باید بکنید اینه که return value یا همان exit status ها را هم درست طراحی کنید. راستش من حال و حوصله اش را نداشتم الان 😉
فعال کردن اسکریپت
خوب برای اینکه اسکریپت کار خودش را آغاز کنه، کافیه اون را در مسیر etc/init.d/ قرار بدید و دستور زیر را اجرا کنید
update-rc.d firewall defaults
این دستور مال زمانیه که شما اسکریپتتون در فایل به نام firewall در etc/init.d/ نوشته باشید.
یک پاسخ
خیلی خوب بود.
امیدوارم در اینده ای نزدیک بتونم بیشتر تحلیلش کنم و ازش استفاده کنم.