۱۰. امنیت پایه و فایروال¶
امنیت در لینوکس لایهلایه است: بهروزرسانی، سطح حمله (پورت و سرویس)، کنترل دسترسی، فایروال، لاگ و سختگیری SSH. این فصل نقطهٔ شروع عملیاتی است — نه جایگزین سیاست امنیتی سازمانی.
راهنمای سریع¶
| کار | فرمان | ریسک |
|---|---|---|
| پورتها و سرویسهای باز | ss -lntup ، systemctl list-unit-files --state=enabled |
بدون تغییر |
| ورودها و تلاشهای ناموفق | last -a ، lastb ، journalctl -u ssh |
بدون تغییر |
| فایلهای SUID/SGID/world-writable | find / -xdev -perm ... |
بدون تغییر |
| وضعیت فایروال | ufw status verbose ، nft list ruleset |
بدون تغییر |
| افزودن قانون فایروال | ufw allow ... ، firewall-cmd --add-... |
تغییر |
ufw enable / reload روی سرور راه دور |
— | مخرب (قفل شدن) |
iptables -F / nft flush ruleset |
— | مخرب |
setenforce 0 / غیرفعالکردن AppArmor |
— | مخرب (برداشتن لایهٔ دفاعی) |
۱. بهروزرسانی و کاهش سطح حمله¶
# Debian/Ubuntu
sudo apt update
apt list --upgradable
sudo unattended-upgrade --dry-run
# RHEL/Rocky/Alma
sudo dnf check-update
sudo dnf update --security --assumeno
# پورتها و سرویسهای در حال اجرا
sudo ss -lntup
sudo systemctl --type=service --state=running
systemctl list-unit-files --state=enabled
اصل کاهش سطح حمله
هر پورت باز و هر سرویس فعال باید دلیل کسبوکاری داشته باشد. سرویس غیرضروری را بعد از بررسی وابستگیها با systemctl disable --now SERVICE غیرفعال کنید. پورتی که روی 127.0.0.1 گوش میدهد از بیرون در دسترس نیست؛ 0.0.0.0 یا [::] در دسترس است.
۲. UFW (Ubuntu / Debian)¶
UFW رابط سادهای روی iptables/nftables است.
sudo ufw status verbose
sudo ufw app list
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 443/tcp
sudo ufw allow from 10.0.0.0/8 to any port 22 proto tcp
sudo ufw limit 22/tcp # محدودیت نرخ اتصال (ضد brute-force ساده)
sudo ufw deny 23/tcp
قبل از ufw enable روی سرور راه دور
- قانون اجازهٔ SSH (یا پورت مدیریت واقعی) را اول اضافه کنید.
- مسیر کنسول ابری / IPMI / بازیابی را آماده داشته باشید.
- در صورت امکان از یک نشست SSH دیگر تست کنید.
- اگر SSH روی پورت غیراستاندارد است، همان پورت را اجازه دهید.
sudo ufw enable
sudo ufw status numbered
# حذف قانون با شماره (دقت کنید شماره بعد از حذف جابهجا میشود)
sudo ufw delete 2
sudo ufw reload
ufw allow OpenSSH + allow from ... هر دو
قانون عمومی allow OpenSSH قانون محدودتر from 10.0.0.0/8 را بیاثر میکند (هر دو مجازند). اگر میخواهید فقط از یک شبکه باشد، قانون عمومی را حذف کنید.
۳. nftables، iptables و firewalld¶
# مشاهده
sudo nft list ruleset
sudo iptables -S
sudo iptables -L -n -v
sudo iptables -t nat -L -n -v
# در سیستمهای جدید ترجیحاً از nft استفاده کنید
sudo nft list tables
Warning
از iptables -F یا nft flush ruleset در production بدون Snapshot و مسیر بازگشت استفاده نکنید. این کار میتواند دسترسی شبکه و قوانین Docker/Kubernetes را از بین ببرد. وقتی iptables -P INPUT DROP تنظیم است، -F همهٔ اتصالها (از جمله SSH شما) را قطع میکند.
firewalld (RHEL-family):
sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --list-all
sudo firewall-cmd --add-service=https # موقت (تا reload)
sudo firewall-cmd --add-service=https --permanent # دائمی (بعد از reload فعال)
sudo firewall-cmd --reload
sudo firewall-cmd --runtime-to-permanent # همهٔ تغییرات موقتِ تستشده را دائمی کن
sudo firewall-cmd --add-rich-rule='rule family=ipv4 source address=192.0.2.0/24 port port=22 protocol=tcp accept'
رویهٔ امن: اول بدون --permanent اضافه و تست کنید؛ اگر قفل شدید، reload یا ریبوت همه را برمیگرداند. بعد --runtime-to-permanent.
نمونهٔ حداقلی nftables (نمونه؛ قبل از اعمال پورتها را با نیاز خود تطبیق دهید):
# /etc/nftables.conf (نمونه)
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iif lo accept
ct state established,related accept
ct state invalid drop
ip protocol icmp accept
ip6 nexthdr icmpv6 accept
tcp dport 22 ip saddr 192.0.2.0/24 accept
tcp dport { 80, 443 } accept
}
}
sudo nft -c -f /etc/nftables.conf # فقط اعتبارسنجی؛ چیزی اعمال نمیشود
# اعمال با «برگرداننده» زماندار، بعد از تأیید atrm کنید:
echo 'nft flush ruleset' | sudo at now + 5 minutes
sudo nft -f /etc/nftables.conf
۴. فایلهای SUID / SGID و مجوزهای خطرناک¶
# فایلهای با بیت SUID (اجرا با مالک)
find / -xdev -type f -perm -4000 -ls 2>/dev/null
# SGID
find / -xdev -type f -perm -2000 -ls 2>/dev/null
# فایلهای world-writable و پوشههای world-writable بدون sticky
find / -xdev -type f -perm -0002 -ls 2>/dev/null | head -30
find / -xdev -type d -perm -0002 ! -perm -1000 -ls 2>/dev/null
# فایلهای بدون مالک
find / -xdev \( -nouser -o -nogroup \) -ls 2>/dev/null | head
وجود SUID لزوماً آسیبپذیری نیست (مثلاً passwd)، اما هر فایل غیرمنتظره را باید بررسی کنید. فهرست را یکبار ذخیره و دورهای مقایسه کنید (diff) تا موارد جدید دیده شود.
۵. بررسی ورودها و تلاشهای ناموفق¶
last -a | head -20
sudo lastb 2>/dev/null | head -10 # تلاشهای ناموفق
sudo journalctl -u ssh --since today --no-pager
sudo journalctl -u ssh -p err --since "2 days ago"
# Debian/Ubuntu
sudo grep -Ei 'Failed password|Invalid user|Accepted' /var/log/auth.log | tail -30
# RHEL-family
sudo grep -Ei 'Failed password|Invalid user|Accepted' /var/log/secure | tail -30
# پرتکرارترین IP های ناموفق
sudo grep 'Failed password' /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head
برای رخداد امنیتی، لاگها را قبل از چرخش یا پاکسازی جمعآوری و آرشیو کنید.
fail2ban (مسدودسازی خودکار)¶
sudo apt install fail2ban # RHEL: dnf install fail2ban (EPEL)
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 192.0.2.50
# /etc/fail2ban/jail.local (نمونه؛ فایل jail.conf را ویرایش نکنید)
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 192.0.2.0/24 # شبکهٔ مدیریت خودتان را حتماً اضافه کنید
[sshd]
enabled = true
۶. سختگیری پایه SSH (خلاصه)¶
جزئیات کامل در SSH و مدیریت راه دور است. حداقلهای پیشنهادی:
# در /etc/ssh/sshd_config.d/10-hardening.conf (بعد از ویرایش تست و reload)
PermitRootLogin no
PasswordAuthentication no # فقط اگر کلید عمومی آماده است
PubkeyAuthentication yes
AllowUsers admin1 admin2
MaxAuthTries 3
sudo sshd -t # تست سینتکس قبل از reload
sudo sshd -T | grep -Ei 'permitroot|passwordauth|allowusers' # مقدار مؤثر
sudo systemctl reload ssh # RHEL: sshd
۷. گواهی و فایلهای محرمانه¶
stat /etc/ssl/private
sudo find /etc -type f \( -name '*.key' -o -name '*private*' \) -ls 2>/dev/null
sudo ls -la /etc/ssl/private/
# نشت احتمالی اسرار در فایلهای متنی (فقط شناسایی؛ خروجی را در تیکت نچسبانید)
sudo grep -RIl -E 'BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY' /home /opt /srv 2>/dev/null | head
- محتوای کلید خصوصی را هرگز در ترمینال ضبطشده، تیکت یا Git چاپ نکنید.
- مجوز معمول برای کلید خصوصی:
600و مالکroot(یا کاربر سرویس). - فایل
.env،*.pem، بکاپ دیتابیس:600. هرگز644.
۸. SELinux و AppArmor¶
لایهٔ کنترل دسترسی اجباری (MAC) که حتی اگر سرویس هک شود، خسارت را محدود میکند. خاموشکردن آن راهحل مشکل نیست.
# RHEL-family: SELinux
getenforce # Enforcing / Permissive / Disabled
sestatus
sudo ausearch -m avc -ts recent | tail # چه چیزی مسدود شد؟
ls -Z /var/www/html
sudo restorecon -Rv /var/www/html # برچسبهای درست را بازگردان
sudo setsebool -P httpd_can_network_connect on # مثال: اجازهٔ اتصال شبکهای nginx/httpd
sudo semanage port -a -t http_port_t -p tcp 8080 # مثال: پورت غیراستاندارد
# Ubuntu/Debian: AppArmor
sudo aa-status
sudo journalctl -k | grep -i 'apparmor="DENIED"' | tail
setenforce 0 فقط برای تشخیص
sudo setenforce 0 (Permissive) را فقط برای تأیید اینکه «مشکل از SELinux است» و موقت استفاده کنید؛ سپس علت را با ausearch/audit2why پیدا و سیاست یا برچسب را اصلاح کنید و setenforce 1. SELINUX=disabled در /etc/selinux/config را در production نگذارید.
۹. سناریوی مشکوک به نفوذ (Triage)¶
اگر مشکوکید سرور هک شده: آرام باشید، ریبوت نکنید (شواهد حافظه از بین میرود)، تغییر بیهدف ندهید، و تیم امنیت/مدیر را مطلع کنید.
- جداسازی، نه خاموشی: در صورت امکان دسترسی شبکه را در سطح فایروال/switch/SG محدود کنید (نه با پاککردن چیزی روی سرور).
- ثبت شواهد فرّار (به همین ترتیب؛ فقط خواندنی):
sudo mkdir -p /var/tmp/ir && cd /var/tmp/ir
{ date -Is; hostname -f; uname -a; uptime; w; last -a | head -30; } > who.txt
ps auxwwf > ps.txt
sudo ss -tupan > sockets.txt
sudo lsof -nP -i > lsof-net.txt 2>/dev/null
sudo systemctl list-units --type=service --state=running > services.txt
sudo systemctl list-timers --all > timers.txt
for u in $(cut -d: -f1 /etc/passwd); do echo "== $u"; sudo crontab -l -u "$u" 2>/dev/null; done > crontabs.txt
ls -la /etc/cron.* /var/spool/cron* > cron-files.txt 2>&1
sudo find /home /root -name authorized_keys -exec sh -c 'echo "== $1"; cat "$1"' _ {} \; > authkeys.txt
cat /etc/ld.so.preload 2>/dev/null > ld-preload.txt
- نشانههای رایج: پردازش ناآشنا با مصرف CPU بالا (miner)، اتصال خروجی به IP ناشناس، فایلهای اجرایی در
/tmp،/dev/shm،/var/tmp، کلید SSH یا حساب جدید، cron/timer ناشناس، تغییر در/etc/ld.so.preload، باینریهای سیستمی با هش متفاوت:
sudo find /tmp /var/tmp /dev/shm -type f -perm /111 -ls 2>/dev/null
sudo find / -xdev -type f -mtime -2 -not -path '/proc/*' -not -path '/var/log/*' -ls 2>/dev/null | head -50
sudo debsums -c 2>/dev/null | head # Debian: فایلهای بستهها که تغییر کردهاند
sudo rpm -Va 2>/dev/null | grep -E '^..5' | head # RHEL: هش تغییرکرده
- بازسازی، نه پاکسازی: سروری که root آن لو رفته را «تمیز» نمیتوان اعتماد کرد؛ از ایمیج سالم بازسازی، داده را از بکاپ قبل از نفوذ بازیابی و همهٔ رمزها/کلیدها/توکنهای آن سرور را بچرخانید.
- گزارش بنویسید (قالب رخداد): زمان، ورود اولیه، اقدامها، درسها.
۱۰. تنظیمات هسته و ممیزی¶
sysctl net.ipv4.tcp_syncookies net.ipv4.conf.all.rp_filter kernel.randomize_va_space net.ipv4.ip_forward
| پارامتر | مقدار توصیهشده | توضیح |
|---|---|---|
net.ipv4.tcp_syncookies |
1 |
مقاومت در برابر SYN flood |
net.ipv4.conf.all.rp_filter |
1 (یا 2 با routing نامتقارن) |
جلوگیری از IP spoofing |
net.ipv4.conf.all.accept_redirects |
0 |
رد ICMP redirect |
net.ipv4.ip_forward |
0 مگر روتر/Docker/VPN |
فورواردینگ ناخواسته |
kernel.randomize_va_space |
2 |
ASLR |
fs.protected_symlinks / fs.protected_hardlinks |
1 |
کاهش حملات symlink در /tmp |
# اعمال دائمی (نمونه): فایل جدا، سپس بارگذاری
printf 'net.ipv4.tcp_syncookies = 1\nnet.ipv4.conf.all.accept_redirects = 0\n' | sudo tee /etc/sysctl.d/99-hardening.conf
sudo sysctl --system
ممیزی با auditd (اختیاری):
sudo apt install auditd # RHEL: dnf install audit
sudo auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config # هر تغییر در این فایل ثبت شود
sudo ausearch -k sshd_config -ts today
برای ارزیابی کلی، lynis audit system گزارش پیشنهادی میدهد. اسکن بیرونی (nmap) فقط روی سیستمهایی که مجاز هستید.
۱۱. چکلیست امنیتی اولیه (۱۵ دقیقه)¶
- سیستم بهروز است (
apt/dnf) - فقط پورتهای لازم باز هستند (
ss -lntup) - فایروال فعال، پیشفرض ورودی
deny، و قانون SSH درست است - ورود root با رمز غیرفعال یا محدود شده؛
sshd -Tتأیید کرده - کاربران sudo مشخص و حداقل هستند؛ گروه
dockerبازبینی شده - لاگ auth/secure و journal پایدار و در حال ثبت است
- فایلهای SUID غیرمنتظره بررسی شدهاند
- SELinux/AppArmor در حالت Enforcing است
- fail2ban یا مکانیزم معادل فعال است و شبکهٔ مدیریت در
ignoreipاست - بکاپ تستبازیابی شده است
- هیچ رمز/کلید در Git یا فایل با مجوز باز نیست
خطاهای رایج¶
| نشانه | علت احتمالی | اقدام |
|---|---|---|
قطع دسترسی بعد از ufw enable |
قانون SSH اضافه نشده | کنسول ابری / IPMI |
Connection refused بعد از reload sshd |
سینتکس یا پورت اشتباه | sshd -t و کنسول |
| پورت باز اما سرویس پاسخ نمیدهد | bind روی localhost یا فایروال میزبان دیگر | ss -lntp + تست از خارج |
| قانون UFW هست ولی پورت کانتینر هنوز باز است | Docker قوانین iptables خودش را قبل از UFW اضافه میکند | Docker |
| سرویس بعد از فعالشدن SELinux خراب شد | برچسب/boolean/پورت | ausearch -m avc ، restorecon ، setsebool |
| خودتان توسط fail2ban بن شدید | ignoreip تنظیم نیست |
از کنسول: fail2ban-client set sshd unbanip IP |
نکات عملیاتی¶
- تغییرات فایروال را در پنجرهٔ تغییر و با هماهنگی انجام دهید.
- قوانین موقت را با یادداشت و تاریخ انقضا مستند کنید.
- در محیط کانتینری، هم فایروال میزبان و هم NetworkPolicy / قواعد Docker را در نظر بگیرید.
- پیشفرض را «همه چیز بسته» بگذارید و فقط لازمها را باز کنید (نه برعکس).
خلاصهٔ اجرایی¶
- سطح حمله: هر پورت/سرویس باید دلیل داشته باشد.
- فایروال: اول قانون SSH، کنسول آماده، تست با نشست دوم.
- SELinux/AppArmor را خاموش نکنید؛ برچسب/boolean را درست کنید.
- مشکوک به نفوذ: ریبوت نکنید، شواهد بگیرید، جدا کنید، بازسازی کنید و رمزها را بچرخانید.