پرش به محتویات

۱۰. امنیت پایه و فایروال

امنیت در لینوکس لایه‌لایه است: به‌روزرسانی، سطح حمله (پورت و سرویس)، کنترل دسترسی، فایروال، لاگ و سخت‌گیری 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 روی سرور راه دور

  1. قانون اجازهٔ SSH (یا پورت مدیریت واقعی) را اول اضافه کنید.
  2. مسیر کنسول ابری / IPMI / بازیابی را آماده داشته باشید.
  3. در صورت امکان از یک نشست SSH دیگر تست کنید.
  4. اگر 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)

اگر مشکوکید سرور هک شده: آرام باشید، ریبوت نکنید (شواهد حافظه از بین می‌رود)، تغییر بی‌هدف ندهید، و تیم امنیت/مدیر را مطلع کنید.

  1. جداسازی، نه خاموشی: در صورت امکان دسترسی شبکه را در سطح فایروال/switch/SG محدود کنید (نه با پاک‌کردن چیزی روی سرور).
  2. ثبت شواهد فرّار (به همین ترتیب؛ فقط خواندنی):
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
  1. نشانه‌های رایج: پردازش ناآشنا با مصرف 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: هش تغییرکرده
  1. بازسازی، نه پاک‌سازی: سروری که root آن لو رفته را «تمیز» نمی‌توان اعتماد کرد؛ از ایمیج سالم بازسازی، داده را از بکاپ قبل از نفوذ بازیابی و همهٔ رمزها/کلیدها/توکن‌های آن سرور را بچرخانید.
  2. گزارش بنویسید (قالب رخداد): زمان، ورود اولیه، اقدام‌ها، درس‌ها.

۱۰. تنظیمات هسته و ممیزی

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 را در نظر بگیرید.
  • پیش‌فرض را «همه چیز بسته» بگذارید و فقط لازم‌ها را باز کنید (نه برعکس).

خلاصهٔ اجرایی

  1. سطح حمله: هر پورت/سرویس باید دلیل داشته باشد.
  2. فایروال: اول قانون SSH، کنسول آماده، تست با نشست دوم.
  3. SELinux/AppArmor را خاموش نکنید؛ برچسب/boolean را درست کنید.
  4. مشکوک به نفوذ: ریبوت نکنید، شواهد بگیرید، جدا کنید، بازسازی کنید و رمزها را بچرخانید.