এই পর্বে যা শিখবেন
- Hardening কী, আর CIS Benchmark ও STIG কীভাবে বিচার করে ব্যবহার করবেন
- কম software, নিয়মিত patch, account, sudo,
pam_faillockআর SSH-এর ভিত্তি - নিজের system-এর ফাইল অনুমতি,
umaskআরsysctlপর্যালোচনা - auditd rule লেখা, audit log পড়া আর file integrity alert সামলানো
- SELinux বা AppArmor-এর denial পড়ে ঠিকভাবে সমাধান করা
- systemd sandbox, central log, automation আর সেবা ভাঙেনি তার প্রমাণ
১ · Hardening কী — নিজের বাড়ির বাড়তি দরজা বন্ধ করা
একটি পুরোনো বাড়ি ভাবুন। ছয়টি দরজা, তার তিনটি কেউ ব্যবহার করে না। পেছনের গেটের চাবি কার কাছে, কেউ জানে না। দারোয়ান আছেন, কিন্তু রেজিস্টার খাতা নেই। চোর এলে কোন দরজা দিয়ে এল, পরে কেউ বলতে পারবে না।
নতুন একটি Linux server অনেকটা এমন। সাধারণ install সবার কাজে লাগার জন্য বানানো হয়, আপনার একটি নির্দিষ্ট কাজের জন্য নয়। তাই অনেক প্যাকেজ, চালু service আর উদার নিয়ম থাকতে পারে। Hardening মানে সেই সাধারণ অবস্থাকে আপনার server-এর কাজের মাপে ছেঁটে আনা। লক্ষ্য তিনটি: attack surface ছোট করা (পর্ব ৪), কিছু ভাঙলে ক্ষতি সীমিত রাখা, আর ঘটনা ঘটলে তা দেখতে পাওয়া।
বাড়তি দরজা ইট দিয়ে গাঁথা হলো minimal install. প্রতিটি ঘরে আলাদা তালা হলো অনুমতি আর MAC. দারোয়ানের রেজিস্টার হলো auditd. আলমারির সিলগালা হলো file integrity check. আর থানায় পাঠানো খাতার নকল হলো central log, যা চোর বাড়িতে এসে ছিঁড়তে পারে না।
এখানে সততাও দরকার। Hardening আপনার app-এর logic-এর বাগ সারায় না। চুরি হওয়া বৈধ admin credential-ও পুরোপুরি থামায় না। এটি হামলাকে কঠিন, ধীর আর দৃশ্যমান করে। তাই এটি defense in depth-এর একটি অংশ (পর্ব ৩), পুরো উত্তর নয়। নিচের ছবিতে স্তরগুলো দেখুন। এই পর্ব মোটামুটি এই ক্রমেই এগোবে।
একটি Linux server-এর প্রতিরক্ষার স্তর
Hardening layers from boot to central logging
সীমা: এই পর্বের সব command শুধু নিজের server বা লিখিত অনুমতি আছে এমন system-এর জন্য (পর্ব ৬). প্রথমে test machine-এ চেষ্টা করুন। SSH বা firewall বদলানোর সময় চলতি session বন্ধ করবেন না। নতুন session খুলে login পরীক্ষা করে তবেই পুরোনোটি ছাড়ুন।
২ · CIS Benchmark আর STIG — রেসিপি, আইন নয়
ভালো রান্নার বইয়ে বলা থাকে কতটা লবণ দিতে হবে। কিন্তু অতিথি ডায়াবেটিসের রোগী হলে রান্না বদলাতে হয়। CIS Benchmark আর STIG এমন রেসিপি। হাজারো অভিজ্ঞতা থেকে লেখা নির্দিষ্ট সেটিং, প্রতিটির কারণ, যাচাইয়ের উপায় আর সমাধানসহ।
| দিক | CIS Benchmark | DISA STIG |
|---|---|---|
| কে লেখে | Center for Internet Security, সমষ্টিগত ঐকমত্যে | মার্কিন প্রতিরক্ষা বিভাগের DISA |
| কার জন্য | সাধারণ প্রতিষ্ঠান, স্বেচ্ছায় | মূলত মার্কিন প্রতিরক্ষা-সংশ্লিষ্ট system |
| স্তরের ভাগ | Level 1, Level 2 profile | Severity: CAT I, II, III |
| চরিত্র | তুলনামূলক বাস্তবমুখী | সাধারণত বেশি কড়া |
Level 1 মানে এমন সেটিং, যা স্পষ্ট লাভ দেয় আর সেবায় সাধারণত বড় বাধা তৈরি করে না। Level 2 বাড়তি গভীর প্রতিরক্ষা, যেখানে নিরাপত্তা সুবিধার চেয়ে আগে আসে। এতে কিছু কাজ ভাঙতে পারে। Server আর workstation-এর profile-ও আলাদা হয়, আর প্রতিটি distribution-এর আলাদা Benchmark আছে। তাই সবসময় নিজের OS version-এর দলিল পড়ুন।
কেন চোখ বুজে চাপাবেন না
- Role আলাদা: অনেক নিয়ম বলে
ip_forwardবন্ধ রাখুন। কিন্তু container চালানো host বা router-এ এটি সাধারণত দরকার। অন্ধভাবে বন্ধ করলে container-এর network ভাঙবে। - Mount-এর সীমা:
/tmp-তেnoexecভালো নিয়ম। কিন্তু কিছু installer সেখানে script চালায় বলে ব্যর্থ হতে পারে। - নিজেকে আটকে ফেলা: SSH-এর নিয়ম বদলে সবার প্রবেশ বন্ধ করা সবচেয়ে পরিচিত দুর্ঘটনা।
- Score মানে নিরাপত্তা নয়: ১০০% score মানে তালিকা মিলেছে। App-এর বাগ বা দুর্বল password process তালিকায় ধরা না-ও পড়তে পারে।
না মানা কোনো নিয়ম চুপচাপ বাদ দেবেন না। ব্যতিক্রম লিখুন: কোন নিয়ম, কেন, কে অনুমোদন করলেন, বিকল্প কী (compensating control), আর কবে আবার দেখা হবে। এটি risk acceptance-এর লিখিত রূপ। নিচের toy scorer এই ধারণা দেখায়। এটি কোনো আসল Benchmark নয়, শুধু একটি in-memory object পরীক্ষা করে।
// Toy CIS-style audit of an in-memory config object. Not a real Benchmark.
const host = { sshRoot: "no", sshPassword: "yes", ipForward: 1, syncookies: 1,
auditd: true, worldWritable: 2, mac: "permissive", autoUpdates: true };
const checks = [
{ id: "1.1", lvl: 1, w: 3, name: "root SSH login off", ok: h => h.sshRoot === "no" },
{ id: "1.2", lvl: 1, w: 3, name: "SSH password off", ok: h => h.sshPassword === "no" },
{ id: "2.1", lvl: 1, w: 2, name: "IP forwarding off", ok: h => h.ipForward === 0 },
{ id: "2.2", lvl: 1, w: 1, name: "TCP syncookies on", ok: h => h.syncookies === 1 },
{ id: "3.1", lvl: 1, w: 2, name: "auditd running", ok: h => h.auditd },
{ id: "3.2", lvl: 1, w: 2, name: "no world-writable", ok: h => h.worldWritable === 0 },
{ id: "4.1", lvl: 2, w: 3, name: "MAC enforcing", ok: h => h.mac === "enforcing" },
{ id: "5.1", lvl: 1, w: 2, name: "security updates on", ok: h => h.autoUpdates },
];
// Written exception: this host runs containers. Owner and review date are recorded.
const exceptions = { "2.1": "container host, ticket SEC-118, review 2027-01" };
function audit(maxLevel) {
let got = 0, total = 0;
for (const c of checks) {
if (c.lvl > maxLevel) continue;
if (exceptions[c.id]) { console.log(`SKIP ${c.id} ${c.name}: ${exceptions[c.id]}`); continue; }
const pass = c.ok(host);
total += c.w;
if (pass) got += c.w;
else console.log(`FAIL ${c.id} ${c.name} (weight ${c.w})`);
}
console.log(`Level ${maxLevel}: ${got}/${total} = ${(100 * got / total).toFixed(1)}%\n`);
}
audit(1);
audit(2);আউটপুটের প্রথম ভাগে Level 1-এর ফল Level 1: 8/13 = 61.5%, আর দ্বিতীয় ভাগে Level 2: 8/16 = 50.0%. হাতে মিলিয়ে দেখুন। Level 1-এ ওজনের যোগফল ১৫, কিন্তু 2.1 ব্যতিক্রম বলে তার ২ বাদ, তাই মোট ১৩। পাস করেছে ১.১ (৩), ২.২ (১), ৩.১ (২) আর ৫.১ (২), মোট ৮। ৮ ÷ ১৩ = ৬১.৫%. Level 2-তে MAC-এর ৩ যোগ হয় মোটে, কিন্তু পাসে নয়, তাই ৮ ÷ ১৬ = ৫০%.
ব্যতিক্রমটি SKIP হিসেবে দৃশ্যমান থাকছে, হারিয়ে যাচ্ছে না। আর score-এর চেয়ে বেশি কাজের হলো FAIL তালিকা। SSH password চালু থাকা বাস্তবে যতটা ঝুঁকি, একটি শতাংশ তা বলতে পারে না।
আসল কাজে নিজের system যাচাইয়ের টুল আছে। যেমন SCAP-ভিত্তিক OpenSCAP, CIS-CAT বা Lynis. এগুলো উদাহরণ মাত্র, সুপারিশ নয়। আগে report mode-এ চালান, automatic সংশোধন নয়। Standard-এর বড় ছবি আসবে পর্ব ৬৯-এ।
৩ · ভিত্তি — কম software, patch, account আর SSH
সবচেয়ে সস্তা নিরাপত্তা হলো যে জিনিস নেই, তার বাগও নেই। তাই শুরু করুন minimal install দিয়ে। তারপর দেখুন কী চলছে আর কোন port শুনছে।
systemctl list-units --type=service --state=running
sudo ss -tulpn # কোন process কোন port শুনছে
sudo systemctl disable --now cups # যদি printing না লাগে
sudo systemctl mask cups # ভুলে আবার চালু হওয়া ঠেকায়প্রতিটি লাইনের জন্য একটি প্রশ্ন করুন: এটি কার দরকার? উত্তর না পেলে আগে খোঁজ নিন, তারপর test machine-এ বন্ধ করে দেখুন। কোনো service 127.0.0.1-তে শুনলে বাইরে থেকে সরাসরি পৌঁছানো যায় না, কিন্তু 0.0.0.0 মানে সব interface.
Patch আর স্বয়ংক্রিয় নিরাপত্তা update
জানা ত্রুটির patch আসার পরও বসাতে দেরি হওয়া বহু breach-এর কারণ। ছোট server-এ স্বয়ংক্রিয় নিরাপত্তা update চালু রাখা সাধারণত ভালো। অগ্রাধিকার ঠিক করার পদ্ধতি আসবে পর্ব ৩২-এ।
unattended-upgrades প্যাকেজ এই কাজ করে। ফাইলের নাম আর ডিফল্ট version-ভেদে আলাদা হতে পারে।
# /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";dnf-automatic একই ধরনের কাজ করে। নতুন release-এ টুলের নাম বদলাতে পারে, তাই নিজের OS-এর দলিল দেখুন।
# /etc/dnf/automatic.conf
[commands]
upgrade_type = security
apply_updates = yesUpdate বসানো আর কার্যকর হওয়া এক নয়। Kernel বদলালে সাধারণত reboot লাগে। Library বদলালে পুরোনো process পুরোনো কোড নিয়েই চলতে পারে, যতক্ষণ না service restart হয়। তাই reboot-এর সময়সূচিও পরিকল্পনার অংশ।
User, sudo, password-এর বয়স আর pam_faillock
- প্রতিটি মানুষের নিজের account: ভাগের account থাকলে log বলতে পারে না কে কাজটি করলেন। পুরোনো account বন্ধ করুন:
sudo usermod -L -e 1 oldstaff. - Sudo ছোট রাখুন:
ALL-এর বদলে নির্দিষ্ট command দিন, আরvisudoদিয়ে sudoers বদলান। Editor বা shell-এর মতো প্রোগ্রাম root হিসেবে দেওয়া কার্যত পুরো root দেওয়া, তাই ফাইল সম্পাদনায়sudoeditভালো। বিস্তারিত পর্ব ২০-এ। - Password-এর বয়স:
chageদিয়ে নীতি দেখা ও ঠিক করা যায়। কিন্তু NIST SP 800-63B-4 নিয়মিত জোর করে password বদলানোর বিপক্ষে, শুধু ফাঁসের প্রমাণে বদলের পক্ষে (পর্ব ১৫). কিছু benchmark-এ তবু বয়সের সীমা থাকে। প্রশ্ন ০৫-এ এই দ্বন্দ্ব দেখব। অস্থায়ী account-এ শেষ তারিখ বসানো কিন্তু খুব কাজের:sudo chage -E 2026-12-31 vendor1. - pam_faillock: Linux PAM-এর এই module বারবার ভুল password-এ account সাময়িক আটকায়।
# /etc/security/faillock.conf
# পরপর ৫ বার ভুলে আটকাবে
deny = 5
# এই ৯০০ সেকেন্ডের ভেতরের ভুল গোনা হবে
fail_interval = 900
# ৯০০ সেকেন্ড পরে নিজে খুলবে
unlock_time = 900
# অজানা username-ও log করবে
auditModule-এর ডিফল্ট deny=3, fail_interval=900 আর unlock_time=600. শুধু config লিখলেই হয় না, PAM stack-এ module যুক্তও থাকতে হয়। RHEL-ধরনের system-এ এটি সাধারণত authselect দিয়ে হয়, অন্যগুলোতে নিয়ম আলাদা। কার account আটকেছে তা দেখতে sudo faillock --user rina, আর খুলতে --reset. দুটি সীমা মনে রাখুন। এই আটকানোর সুযোগ নিয়ে কেউ ইচ্ছা করে বৈধ ব্যবহারকারীকে আটকে দিতে পারে। আর SSH key দিয়ে login-এ password যাচাই হয় না, তাই সেখানে এই গণনাও চলে না।
SSH — এক নজরে
SSH-এর পুরো গল্প আছে Cloud ও DevOps কোর্সের SSH পর্বে. এখানে শুধু স্মরণ করিয়ে দিই। Password-এর বদলে SSH key, root-এর সরাসরি login বন্ধ, আর শুধু নির্দিষ্ট group-কে প্রবেশ।
# /etc/ssh/sshd_config.d/00-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
AllowGroups sshusers
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2sshd_config-এ একই নিয়ম বারবার থাকলে প্রথম পাওয়া মানটি জেতে। তাই drop-in ফাইলের নাম 00- দিয়ে শুরু করা হলো, যাতে পরের কোনো ফাইল তাকে না বদলায়। প্রয়োগের আগে sudo sshd -t দিয়ে syntax যাচাই করুন, আর sudo sshd -T দিয়ে শেষ পর্যন্ত কোন মান কার্যকর হচ্ছে দেখুন।
৪ · ফাইল আর kernel — অনুমতি, umask, sysctl, boot
অনুমতির ভিত্তি পড়েছেন OS কোর্সের Linux permission পর্বে. Hardening-এ প্রশ্নটি আলাদা: আমার system-এ যা আছে, তা কি যা থাকার কথা তার সাথে মেলে? অফিসের স্টক মেলানোর মতো, খাতার সাথে তাকের জিনিস মিলিয়ে দেখা। নিচের block নিজের একটি ছোট folder বানিয়ে শুধু সেটিই পরীক্ষা করে।
# Toy audit: builds its own small tree and checks only that tree.
T=$(mktemp -d); cd "$T" || exit 1
mkdir -p app/conf app/public app/logs
echo "port=8080" > app/conf/app.conf
echo "db_pass=example-token" > app/conf/secret.env
echo "hello" > app/public/index.html
echo "started" > app/logs/app.log
echo "echo run" > app/run.sh
chmod 755 app app/conf app/public; chmod 777 app/logs
chmod 644 app/conf/app.conf app/public/index.html
chmod 666 app/conf/secret.env; chmod 640 app/logs/app.log; chmod 4755 app/run.sh
echo "== world-writable =="
find app -perm -0002 | sort
echo "== SUID or SGID files =="
find app -type f -perm /6000 | sort
echo "== expected vs actual =="
cat > expected.txt <<'EOF'
640 app/conf/app.conf
600 app/conf/secret.env
644 app/public/index.html
640 app/logs/app.log
755 app/run.sh
EOF
while read -r want path; do
got=$(stat -c '%a' "$path")
if [ "$got" = "$want" ]; then echo "ok $path $got"
else echo "FIX $path has $got, want $want"; fi
done < expected.txt
cd /; rm -rf "$T"প্রথম ভাগে app/conf/secret.env আর app/logs ধরা পড়েছে, কারণ এদের others-এর ঘরে write আছে। -perm -0002 মানে এই bit অবশ্যই থাকতে হবে। দ্বিতীয় ভাগে app/run.sh এসেছে, কারণ তাতে SUID bit আছে। শেষ ভাগের FIX app/conf/secret.env has 666, want 600 সবচেয়ে গুরুতর: secret ফাইল সবাই পড়তে ও বদলাতে পারে। FIX app/run.sh has 4755, want 755 বলছে অনুমোদন ছাড়া SUID বসেছে।
আসল শক্তি শেষ অংশে। find শুধু সন্দেহজনক জিনিস দেখায়, কিন্তু একটি প্রত্যাশিত তালিকা বলে দেয় কোনটি নীতিভঙ্গ।
SUID আর SGID — নিজের system-এর হিসাব
SUID bit থাকলে প্রোগ্রাম ফাইলের মালিকের অধিকার নিয়ে চলে। যেমন passwd-এর এটি দরকার। কিন্তু root-এর SUID প্রোগ্রামের প্রতিটি বাগ বড় ঝুঁকি। তাই এদের সংখ্যা কম রাখা, আর হঠাৎ নতুন একটি এলে জানতে পারাই লক্ষ্য। এটি অডিট, কোনো হামলার কৌশল নয়। অনুমোদিত তালিকার সাথে আজকের অবস্থা মেলান:
# নিজের server-এ, আগে সংরক্ষিত অনুমোদিত তালিকার সাথে তুলনা
sudo find / -xdev -type f -perm /6000 -printf '%m %u %p\n' | sort -k3 > suid-today.txt
diff suid-approved.txt suid-today.txtনতুন লাইন এলে দেখুন সেটি কোন package-এর, আর package manager-এর হিসাবের সাথে মেলে কি না (rpm -V বা dpkg --verify). /tmp-এর মতো user-লেখা জায়গায় nosuid আর nodev mount option বাড়তি বেড়া।
umask — নতুন ফাইলের ডিফল্ট
umask বলে দেয় নতুন ফাইল থেকে কোন অনুমতি বাদ যাবে। ফাইল শুরু হয় ৬৬৬ থেকে, folder ৭৭৭ থেকে। হিসাবটি বিয়োগ নয়, bit মোছা: অনুমতি = ভিত্তি AND (NOT umask).
| umask | নতুন ফাইল | নতুন folder | অর্থ |
|---|---|---|---|
022 | 644 | 755 | সবাই পড়তে পারে |
027 | 640 | 750 | Group পড়তে পারে, others কিছুই নয় |
077 | 600 | 700 | শুধু মালিক |
033 | 644 | 744 | দেখুন: ৬৬৬ − ০৩৩ = ৬৩৩ নয় |
শেষ সারি পরীক্ষার প্রিয় ফাঁদ। ৬ মানে 110, ৩ মানে 011. 011-এর NOT হলো 100. 110 AND 100 = 100, অর্থাৎ ৪। তাই ফল ৬৪৪।
sysctl — চলন্ত kernel-এর সুইচ
sysctl দিয়ে kernel-এর আচরণ বদলানো যায়। ফাইলে লিখলে reboot-এর পরেও থাকে।
# /etc/sysctl.d/60-hardening.conf
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.ip_forward = 0
kernel.randomize_va_space = 2
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.yama.ptrace_scope = 1
fs.suid_dumpable = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1| সেটিং | কী করে | কোথায় সাবধান |
|---|---|---|
tcp_syncookies | SYN queue ভরলেও নতুন connection নিতে সাহায্য করে (পর্ব ২৮) | সাধারণত নিরাপদ |
rp_filter | ভুল interface-এ আসা, সম্ভবত নকল উৎসের packet ফেলে | Asymmetric routing-এ বৈধ traffic পড়তে পারে; তখন 2 (loose) |
accept_redirects, send_redirects | ICMP redirect দিয়ে route বদল ঠেকায় | Router-এর নিয়ম আলাদা |
accept_source_route | Packet-এর নিজে বলা পথ মানে না | সাধারণত নিরাপদ |
log_martians | অসম্ভব ঠিকানার packet log করে | Log বাড়তে পারে |
ip_forward | Server-কে router হওয়া থেকে থামায় | Container host, VPN gateway, router-এ 1 লাগে |
randomize_va_space | ASLR পুরো চালু রাখে | সাধারণত ডিফল্টই ২ |
kptr_restrict, dmesg_restrict | Kernel-এর ঠিকানা আর বার্তা সাধারণ user থেকে লুকায় | Debug কিছুটা কঠিন হয় |
ptrace_scope | এক process-এর অন্যটির memory দেখার সুযোগ কমায় | Debugger-এর ব্যবহারে বাধা; Yama না থাকলে এই key-ই থাকে না |
suid_dumpable | SUID প্রোগ্রামের crash-এ core file-এ secret পড়া ঠেকায় | Crash বিশ্লেষণ সীমিত হয় |
protected_* | সবার লেখা folder-এ link-এর ফাঁদ কমায় | সাধারণত ডিফল্ট চালু |
নতুন interface-এর জন্য .default. রূপও সেট করতে হতে পারে। প্রয়োগ করুন sudo sysctl --system দিয়ে, আর যাচাই করুন sysctl net.ipv4.tcp_syncookies দিয়ে।
Kernel, boot আর host firewall
- Secure Boot: Firmware শুধু স্বাক্ষর মেলা bootloader আর kernel চালায়। শিকলটি পাবেন OS কোর্সের boot পর্বে.
- Kernel lockdown: Root-কেও চলন্ত kernel বদলানোর কিছু পথ থেকে সরিয়ে রাখে।
- Kernel module-এর সীমা: অপ্রয়োজনীয় module, যেমন ব্যবহার না হওয়া filesystem বা USB storage, load হওয়া ঠেকানো যায়। Signed module বাধ্যতামূলক করা আরও শক্ত বেড়া।
- Bootloader আর disk: Bootloader password শারীরিক প্রবেশের ঝুঁকি কমায়। ল্যাপটপে disk encryption অপরিহার্য (পর্ব ২৯).
- Exploit-প্রতিরোধ: ASLR, KASLR আর অন্যান্য ব্যবস্থা আছে OS নিরাপত্তা পর্বে.
- Host firewall: Default deny inbound রাখুন, শুধু দরকারি port খুলুন। নিয়ম আর উদাহরণ আছে পর্ব ২২-এ। Cloud-এ security group এর বিকল্প নয়, আরেকটি স্তর।
৫ · auditd — অফিসের রেজিস্টার খাতা
সাধারণ log app যা লিখতে চায় তা-ই লেখে। auditd আলাদা। Kernel নিজে নিয়ম মিলিয়ে ঘটনা ধরে, আর auditd daemon সেটি /var/log/audit/audit.log-এ লেখে। নিয়ম দুই ধরনের: নির্দিষ্ট ফাইলে নজর (-w), আর system call-এর নিয়ম (-a).
# /etc/audit/rules.d/50-hardening.rules
-D
-b 8192
-f 1
# পরিচয় আর অধিকারের ফাইল: write বা attribute বদল (wa)
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k sudo_scope
-w /etc/sudoers.d/ -p wa -k sudo_scope
-w /etc/ssh/sshd_config -p wa -k sshd_config
# সাধারণ user login করে root হিসেবে যে প্রোগ্রাম চালালেন
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=unset -k root_cmd
# অনুমতি বদল
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -k perm_mod
# সবার শেষে: reboot ছাড়া নিয়ম বদলানো যাবে না
-e 2লোড করুন sudo augenrules --load দিয়ে, দেখুন sudo auditctl -l দিয়ে। -k হলো খোঁজার চাবি। -e 2 নিয়মকে অপরিবর্তনীয় করে, তাই হামলাকারী root পেলেও সহজে নিয়ম মুছতে পারে না। কিন্তু আপনিও পারবেন না, তাই নিয়ম পাকা হওয়ার পরই এটি বসান। execve-এর নিয়মে log অনেক বাড়তে পারে, disk আর backlog মেপে নিন।
sudo ausearch -k sshd_config -i --start today
sudo aureport --summaryনমুনা আউটপুট — version-ভেদে আলাদা হতে পারে, কিছু ঘর সংক্ষেপ করা হয়েছে:
type=PATH msg=audit(10/31/2026 03:14:07.218:4521) : item=1
name=/etc/ssh/sshd_config mode=file,644 ouid=root
type=SYSCALL msg=audit(10/31/2026 03:14:07.218:4521) : syscall=openat
success=yes ppid=2210 pid=2233 auid=rina uid=root euid=root
tty=pts1 ses=14 comm=vi exe=/usr/bin/vi key=sshd_config
এখানে সবচেয়ে দামি ঘর auid. uid=root বলে কোন অধিকারে কাজটি হলো। auid=rina বলে কে প্রথমে login করেছিলেন। sudo করলেও auid বদলায় না। অর্থাৎ root-এর ভিড়েও মানুষটিকে চেনা যায়। একই ঘটনার সব লাইন একই serial নম্বর (4521) দিয়ে জোড়া।
Audit log ছাড়াও প্রতিদিনের log পড়তে পারা দরকার। নিচে একটি নির্দিষ্ট sample auth log আছে, যা block নিজেই বানায়। ঠিকানাগুলো documentation range-এর। ধরে নিন নীতি হলো শুধু SSH key.
# Reads only the fixed sample below. Addresses are documentation addresses.
T=$(mktemp -d); cd "$T" || exit 1
cat > auth.log <<'EOF'
Oct 31 02:11:04 web1 sshd[811]: Failed password for root from 203.0.113.7 port 50122 ssh2
Oct 31 02:11:06 web1 sshd[811]: Failed password for root from 203.0.113.7 port 50122 ssh2
Oct 31 02:11:09 web1 sshd[812]: Failed password for invalid user admin from 203.0.113.7 port 50130 ssh2
Oct 31 02:11:12 web1 sshd[812]: Failed password for invalid user test from 203.0.113.7 port 50130 ssh2
Oct 31 02:40:31 web1 sshd[815]: Failed password for rina from 198.51.100.24 port 50988 ssh2
Oct 31 02:40:52 web1 sshd[815]: Accepted password for rina from 198.51.100.24 port 50988 ssh2
Oct 31 03:02:10 web1 sshd[820]: Accepted publickey for karim from 198.51.100.9 port 51002 ssh2
Oct 31 03:02:55 web1 sudo: karim : TTY=pts/0 ; PWD=/home/karim ; USER=root ; COMMAND=/usr/bin/systemctl restart bazar-api
Oct 31 03:09:40 web1 sudo: rina : command not allowed ; TTY=pts/1 ; PWD=/home/rina ; USER=root ; COMMAND=/usr/sbin/visudo
EOF
echo "== failed logins by source =="
awk '/Failed password/ { for (i = 1; i <= NF; i++) if ($i == "from") n[$(i + 1)]++ }
END { for (ip in n) print n[ip], ip }' auth.log | sort -rn
echo "== accepted logins =="
awk '/Accepted/ { tag = ($7 == "password") ? " <-- breaks key-only policy" : ""
print $7, $9, $11 tag }' auth.log
echo "== sudo refused =="
awk '/sudo:.*command not allowed/ { print $3, $6, $NF }' auth.log
cd /; rm -rf "$T"4 203.0.113.7 বলছে একটি উৎস থেকে চারবার ব্যর্থ চেষ্টা। Internet-মুখী server-এ এমন শব্দ খুব সাধারণ, আর key-only হলে তা সফল হওয়ার কথা নয়। আসল খবর পরের ভাগে: password rina 198.51.100.24 <-- breaks key-only policy. একটি ব্যর্থতার ২১ সেকেন্ড পরে password login সফল হলো, অথচ নীতি বলে password বন্ধ। মানে কোথাও SSH সেটিং নীতির সাথে মিলছে না।
শেষ ভাগের 03:09:40 rina COMMAND=/usr/sbin/visudo বলছে একই account একটু পরে অনুমতি ছাড়া sudoers খুলতে চেয়েছে। আলাদাভাবে দুটি ঘটনা ছোট, একসাথে তদন্তের যোগ্য। এটি প্রমাণ করে না যে rina দোষী। Account-এর ব্যবহার তাঁর সাথে আলাদা পথে যাচাই করতে হবে।
৬ · File integrity monitoring — আলমারির সিলগালা
ব্যাংকের লকার সিল করে রাখলে কেউ খুললে সিল ভাঙে। File integrity monitoring (FIM) ফাইলের ক্ষেত্রে একই কাজ করে। ভালো অবস্থায় প্রতিটি ফাইলের hash, অনুমতি আর মালিকের একটি baseline রাখে, পরে আবার হিসাব করে মিলিয়ে দেখে। Hash-এর ধারণা আছে পর্ব ৯-এ। এটি বদল থামায় না, শুধু বদল জানায়। নিচের block নিজের বানানো ফাইলেই এই কাজটি দেখায়।
# Toy integrity check: hashes only files this block creates.
T=$(mktemp -d); cd "$T" || exit 1
mkdir site
echo "listen 8080" > site/app.conf
echo "user=bazar" > site/users.conf
echo "echo start" > site/start.sh
sha256sum site/* > baseline.txt
echo "baseline: $(wc -l < baseline.txt) files"
# Later: one file changes, one disappears, one appears.
echo "listen 9999" > site/app.conf
rm site/users.conf
echo "echo extra" > site/new.sh
sha256sum site/* > today.txt
awk 'NR == FNR { old[$2] = $1; next }
{ seen[$2] = 1
if (!($2 in old)) print "NEW " $2
else if (old[$2] != $1)
print "CHANGED " $2, substr(old[$2], 1, 10), "->", substr($1, 1, 10) }
END { for (f in old) if (!(f in seen)) print "MISSING " f }' \
baseline.txt today.txt | sort
echo "== sha256sum -c =="
sha256sum -c baseline.txt 2>/dev/null || echo "check failed: review needed"
cd /; rm -rf "$T"আউটপুটে CHANGED, MISSING আর NEW তিন রকম বদলই ধরা পড়েছে। sha256sum -c-ও site/app.conf: FAILED দেখায়, কিন্তু খেয়াল করুন, baseline-এ না থাকা site/new.sh সে দেখে না। তাই নতুন ফাইল ধরতে আলাদা তুলনা দরকার। Web shell বা বাড়তি script ধরার জন্য এই পার্থক্য গুরুত্বপূর্ণ।
আসল কাজে AIDE-এর মতো টুল এটিই বড় পরিসরে করে। Tripwire, Samhain বা অনেক HIDS-ও এই সুবিধা দেয়; এগুলো উদাহরণ মাত্র। AIDE-এ সাধারণ প্রবাহ হলো aide --init দিয়ে database বানানো, ভালো অবস্থার ফাইলটিকে সক্রিয় নামে আনা, আর aide --check নিয়মিত চালানো। Path আর wrapper distribution-ভেদে আলাদা।
Baseline যদি একই server-এ লেখার যোগ্য অবস্থায় থাকে, root পাওয়া হামলাকারী সেটিও বদলাতে পারে। তাই database-এর একটি কপি server-এর বাইরে বা read-only মাধ্যমে রাখুন। আর /var/log-এর মতো সবসময় বদলানো জায়গা বাদ দিন, নইলে false positive-এর বন্যায় আসল alert ডুবে যাবে।
একটি alert এলে কী করবেন? আগে baseline আপডেট করবেন না। নিচে ধাপে ধাপে দেখুন। সব মান নমুনা।
$ sudo aide --check
Changed entries:
f ... : /etc/ssh/sshd_config
SHA512 : pV3k... | Zq9d...
$ sudo ausearch -f /etc/ssh/sshd_config -i time: 10/31/2026 03:14:07 auid=rina uid=root comm=vi change ticket: পাওয়া যায়নি
$ diff approved/sshd_config /etc/ssh/sshd_config
< PasswordAuthentication no
> PasswordAuthentication yes
রিনার ফোনে যাচাই: vendor-এর জন্য নিজে বদলেছেন
একই সময়ের login: শুধু পরিচিত ঠিকানা
রায়: নীতিভঙ্গ, হামলার প্রমাণ নেই
$ sudo sshd -t
$ sudo systemctl reload sshd
$ sudo sshd -T | grep -i passwordauthentication
passwordauthentication no
aide --check: কোনো বদল নেই
ticket: কারণ, প্রমাণ, সমাধান লেখা হলো
নতুন নিয়ম: vendor-এর প্রবেশ jump host দিয়ে
- Alert. রাতের যাচাই বলছে
sshd_config-এর hash মিলছে না। এটি প্রমাণ নয়, প্রশ্ন। Baseline এখনই আপডেট করলে প্রমাণ ঢেকে যাবে। - কে আর কখন। auditd বলছে
auid=rina, ০৩:১৪:০৭-এ। কোনো অনুমোদিত change ticket নেই। Account রিনার মানেই কাজটি রিনার নয়। - কী বদলাল। অনুমোদিত কপির সাথে
diffবলছে password login চালু হয়েছে। এটি নিরাপত্তা কমানো বদল, তাই গুরুত্ব বেশি। - যাচাই। রিনাকে ফোনে, অর্থাৎ আলাদা পথে জিজ্ঞেস করা হলো। তিনি একজন vendor-কে ঢুকতে দিতে এটি করেছেন, আর একই সময়ের login-ও পরিচিত ঠিকানার। তাই এটি নীতিভঙ্গ। হামলার প্রমাণ পেলে পথ হতো incident response (পর্ব ৬১).
- ঠিক করা। ফাইল অনুমোদিত অবস্থায় ফেরানো হলো।
sshd -tআগে, reload পরে, আরsshd -Tদিয়ে কার্যকর মান যাচাই। - বন্ধ করা। ফাইল আগের মতো হওয়ায় baseline আপডেট লাগল না। কোনো অনুমোদিত বদল হলে পর্যালোচনার পরেই baseline নতুন হতো। মূল কারণও সমাধান করা হলো: vendor-এর জন্য একটি বৈধ পথ।
৭ · SELinux আর AppArmor — denial পড়ুন, বন্ধ করবেন না
ফাইলের সাধারণ অনুমতি হলো DAC: মালিক ঠিক করেন কে পাবে। সমস্যা হলো, root বা মালিকের অধিকারে চলা একটি আক্রান্ত প্রোগ্রাম সেই অধিকারের সব কিছু ছুঁতে পারে। MAC-এ কেন্দ্রীয় নীতি ঠিক করে দেয় কোন প্রোগ্রাম কোন ধরনের জিনিস ছুঁতে পারবে, মালিক বা root হলেও। ব্যাংকের কর্মীর হাতে চাবি থাকলেও ভল্টে ঢুকতে আলাদা নিয়ম মানতে হয়, এমন। তত্ত্বের গভীর অংশ আছে OS কোর্সের sandbox পর্বে. এখানে আমরা প্রয়োগে থাকব।
একটি ফাইল খোলার দুই দরজা
DAC runs first, then the LSM hook checks MAC policy
| দিক | SELinux | AppArmor |
|---|---|---|
| ভিত্তি | Label (security context), type enforcement | ফাইলের path-ভিত্তিক profile |
| সাধারণত দেখা যায় | RHEL, Fedora-ধরনের system | Ubuntu, Debian, SUSE-র অনেক system |
| শেখার চাপ | বেশি, কিন্তু খুব সূক্ষ্ম | কম, পড়তে সহজ |
| আটকায় ও log করে | Enforcing | Enforce |
| শুধু log করে | Permissive | Complain |
| অবস্থা দেখা | getenforce, sestatus | aa-status |
দুটিই kernel-এর LSM কাঠামোর ওপর বসে। Permissive বা complain mode একটি ডায়াগনস্টিক অবস্থা। এতে নীতি শেখা যায়, কিন্তু কিছু আটকায় না। সবচেয়ে বড় ভুল হলো সেটিকেই স্থায়ী করে ফেলা।
একটি AVC denial পড়তে পারা এই পর্বের সবচেয়ে কাজের দক্ষতাগুলোর একটি। ধরুন সাইটের ফাইল home folder থেকে mv করে /srv/web-এ আনা হলো। এখন nginx 403 দিচ্ছে। RHEL-ধরনের system-এ ধাপগুলো দেখুন।
$ curl -I http://127.0.0.1/
HTTP/1.1 403 Forbidden
$ ls -l /srv/web/index.html
-rw-r--r--. 1 nginx nginx 512 ... index.html
$ getenforce Enforcing # ইন্টারনেটের পরামর্শ: setenforce 0 # পুরো মেশিনের পাহারা বন্ধ
$ sudo ausearch -m AVC -ts recent
avc: denied { read } for
comm="nginx" name="index.html"
scontext=system_u:system_r:httpd_t:s0
tcontext=unconfined_u:object_r:user_home_t:s0
tclass=file permissive=0
$ ls -Z /srv/web/index.html unconfined_u:object_r:user_home_t:s0 index.html # mv পুরোনো label সাথে আনে
$ sudo semanage fcontext -a \
-t httpd_sys_content_t "/srv/web(/.*)?"
$ sudo restorecon -Rv /srv/web
Relabeled index.html from
user_home_t to httpd_sys_content_t
$ curl -I http://127.0.0.1/ HTTP/1.1 200 OK $ getenforce Enforcing $ sudo ausearch -m AVC -ts recent <no matches>
- লক্ষণ। Browser-এ 403, অথচ
ls -l-এ অনুমতি ঠিক। DAC পাস করছে, তাই সন্দেহ দ্বিতীয় দরজায়।chmod 777এখানে কিছুই সারাবে না, শুধু নতুন ঝুঁকি আনবে। - লোভ।
setenforce 0দিলে সাইট চলবে, আর সবাই ভাববে সমাধান হলো। আসলে পুরো মেশিনের MAC পাহারা উঠে গেল, শুধু এই একটি ফাইলের জন্য। পরীক্ষা হিসেবে অল্প সময়ের জন্য করলেও তা কারণ বোঝার উপায়, সমাধান নয়। - Denial পড়া। বাক্যটি এভাবে পড়ুন:
httpd_t(উৎস, nginx) চেয়েছিলread, লক্ষ্যuser_home_tlabel-এর একটিfile, আরpermissive=0মানে সত্যিই আটকানো হয়েছে। - কারণ।
mvফাইলের পুরোনো label সাথে আনে। Web server-কে home-এর ফাইল পড়তে না দেওয়াই ঠিক নীতি। তাই নীতি ভুল নয়, ফাইলের label ভুল। - সমাধান।
semanage fcontextস্থায়ী নিয়ম লেখে,restoreconসেটি ফাইলে বসায়। শুধুchconকরলে পরের relabel-এ বদল হারাবে।audit2allowদিয়ে policy বানালে nginx-কে home-এর label পড়ার অধিকার দেওয়া হতো, যা দরকারের চেয়ে অনেক বড়। - পুনঃপরীক্ষা। সাইট 200, SELinux তখনও
Enforcing, নতুন denial নেই। তিনটি প্রমাণই দরকার: সেবা চলছে, পাহারা আছে, আর সমস্যা ফেরেনি।
ঠিক সমাধান বেছে নেওয়ার ছোট নিয়ম: ফাইলের label ভুল হলে semanage fcontext আর restorecon. নীতিতে একটি বৈধ সুবিধা বন্ধ থাকলে SELinux boolean, যেমন setsebool -P httpd_can_network_connect on. App নতুন port-এ শুনলে semanage port. কেবল এগুলোয় না মিটলে পর্যালোচনা করে ছোট একটি custom policy. আর কিছু denial dontaudit নিয়মে লুকানো থাকতে পারে, তাই log না পেলেই “SELinux নয়” বলা যায় না।
AppArmor-এ denial দেখতে এমন। এটি একটি কাল্পনিক bazar-api profile-এর নমুনা, version-ভেদে আলাদা হতে পারে।
audit: type=1400 apparmor="DENIED" operation="open"
profile="bazar-api" name="/var/lib/bazar/uploads/a.png"
comm="api" requested_mask="c" denied_mask="c" fsuid=998
একইভাবে পড়ুন: bazar-api profile-এ /var/lib/bazar/uploads/-তে ফাইল তৈরি (c) নিষেধ। সমাধান profile-এ ওই folder-টুকুর জন্য নির্দিষ্ট নিয়ম। পুরো /var/** নয়। পরে sudo apparmor_parser -r দিয়ে profile আবার লোড করুন। পরিবর্তন শেখার সময় একটি profile complain-এ রাখা যায়, পুরো AppArmor বন্ধ করে নয়। aa-logprof প্রস্তাব দিতে পারে, কিন্তু প্রতিটি প্রস্তাব নিজে পড়ুন।
৮ · systemd sandbox — একটি service-কে ছোট ঘরে রাখা
MAC-এর নীতি লেখা না থাকলেও আপনার নিজের service-কে সহজে ঘেরা যায়। systemd sandboxing-এ unit ফাইলে কয়েকটি লাইন লিখলেই kernel-এর namespace, capability আর অন্যান্য ব্যবস্থা কাজে লাগে। ভাড়াটিয়াকে পুরো বাড়ির চাবি না দিয়ে শুধু তাঁর ঘরের চাবি দেওয়ার মতো।
# sudo systemctl edit bazar-api.service
[Service]
User=bazar
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/bazar/uploads
PrivateDevices=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
CapabilityBoundingSet=| Directive | প্রভাব |
|---|---|
NoNewPrivileges | Process আর তার সন্তানরা SUID বা file capability দিয়ে বাড়তি অধিকার পায় না |
PrivateTmp | Service নিজের আলাদা /tmp পায়, অন্যদের temp ফাইল দেখে না |
ProtectSystem=strict | পুরো filesystem read-only, শুধু ReadWritePaths লেখা যায়। full কম কড়া: /usr, boot আর /etc read-only |
ProtectHome | Home folder লুকায় |
CapabilityBoundingSet= | খালি মান মানে কোনো capability নয়। Port ১০২৪-এর নিচে বসতে হলে শুধু CAP_NET_BIND_SERVICE দিন |
এক লাফে সব লিখবেন না। প্রতিটি ধাপে সেবা পরীক্ষা করুন। systemd-analyze security একটি exposure score দেয়, ১০ মানে সবচেয়ে উন্মুক্ত। এটি একটি কমপাস, প্রমাণ নয়। নিচের সব মান নমুনা।
1[Service]2User=bazar3ExecStart=/opt/bazar/api4NoNewPrivileges=yes5PrivateTmp=yes6ProtectHome=yes7ProtectSystem=strict8ReadWritePaths=/var/lib/bazar/uploads9ProtectKernelTunables=yes10ProtectKernelModules=yes11RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX12CapabilityBoundingSet=
| exposure | |
| /health | |
| upload |
- শুরুর মাপ। কাজ শুরুর আগে score
9.2 UNSAFE, health 200, upload 201. এই baseline ছাড়া পরে বোঝা যাবে না কোন বদলে কী ভাঙল। - সহজ তিনটি।
NoNewPrivileges,PrivateTmp,ProtectHome. Score8.1, দুই পরীক্ষাই পাস। পরের ধাপে যাওয়া যায়। - কিছু ভাঙল।
ProtectSystem=strict-এ score7.4. Health তবু 200, কিন্তু upload 500! শুধু health দেখলে এই ভাঙন ধরা পড়ত না। Log বলছেRead-only file system. - ছোট সমাধান। পুরো নিয়ম না সরিয়ে শুধু
/var/lib/bazar/uploadsলেখার অনুমতি। Upload আবার 201, score একই7.4. - আরও সংকোচন। Kernel-এর সেটিং, module, অপ্রয়োজনীয় address family আর সব capability বাদ। Score
5.6 MEDIUM, দুই পরীক্ষা পাস। - প্রকাশ। Score শূন্য করা লক্ষ্য নয়, সেবা ঠিক রেখে কমানোই লক্ষ্য। একটি server-এ এক দিন দেখে তারপর বাকিগুলোয় ছড়ান। ফেরার পথ:
sudo systemctl revert bazar-api. এটি drop-in বাদ দেয়।
প্রতিবার ফাইল বদলের পরে sudo systemctl daemon-reload আর service restart লাগে। systemctl edit এই reload নিজেই করে, তবু restart আপনাকে করতে হবে। Directive-এর সমর্থন systemd version-এর ওপর নির্ভর করে।
৯ · Central log, automation আর সেবা ভাঙেনি তার প্রমাণ
Log server-এর বাইরে পাঠান। Root পাওয়া হামলাকারী স্থানীয় log মুছতে পারে। তাই ঘটনা ঘটার প্রায় সাথে সাথে log অন্য একটি মেশিনে যাওয়া দরকার, যেখানে এই server-এর মুছে ফেলার অধিকার নেই। Syslog-ভিত্তিক agent সাধারণত TLS দিয়ে পাঠায় (RFC 5425, port 6514). সব মেশিনের ঘড়ি NTP দিয়ে মেলানো চাই, নইলে timeline জোড়া যায় না। পদ্ধতি আছে centralized logging পর্বে; কী রাখবেন আর কতদিন, তা আসবে পর্ব ৫৫-তে। আর পাঠানো থেমে গেলে যেন alert আসে, কারণ নীরবতাও একটি সংকেত।
হাতের কাজ automation-এ তুলুন। একশো server-এ হাতে hardening করলে প্রতিটি একটু আলাদা হবে, আর সময়ের সাথে আলাদাই হতে থাকবে। একে বলে configuration drift. Configuration management টুলে (যেমন Ansible) নিয়মগুলো কোড হিসেবে থাকে। এতে পর্যালোচনা, ইতিহাস আর একই ফলাফল মেলে। আর এই কোড idempotent হলে বারবার চালানো নিরাপদ।
ansible-playbook hardening.yml --limit test --check --diffপ্রথমে test group-এ --check --diff দিয়ে দেখুন কী বদলাবে। তারপর ছোট দলে ছড়ান। আলাদাভাবে একটি পরিষ্কার Linux image শক্ত করে তা থেকে নতুন server বানানোও ভালো পথ।
যাচাই ছাড়া hardening শেষ হয় না। “Command চলেছে” আর “সেবা ঠিক আছে” এক কথা নয়। প্রতিটি পরিবর্তনের জন্য তিন প্রশ্নের উত্তর রাখুন:
- নিরাপত্তা বসেছে? কার্যকর মান দেখুন:
sshd -T,sysctl,auditctl -l,getenforce. - সেবা চলছে? একটি smoke test চালান, শুধু health নয়, আসল কাজও: login, upload, database লেখা, backup, monitoring, নতুন SSH session.
- ফিরতে পারব? আগের config, runbook-এ লেখা ফেরার ধাপ আর console প্রবেশ তৈরি রাখুন। Cloud-এ snapshot, নিজের ঘরে হাতে পৌঁছানোর উপায়।
আরও গভীরে: Linux Security Modules (LSM) kernel-এর নির্দিষ্ট জায়গায় hook বসায়, যেখানে SELinux বা AppArmor সিদ্ধান্ত দেয়। SELinux এসেছে NSA-র গবেষণা থেকে, ২০০০ সালে প্রকাশ্য হয় আর Linux 2.6-এ মূল kernel-এ আসে। AppArmor মূল kernel-এ আসে 2.6.36-এ (২০১০). Kernel lockdown যোগ হয় 5.4-এ (২০১৯). আর NoNewPrivileges ভেতরে kernel-এর no_new_privs flag ব্যবহার করে।
পরীক্ষা ও ইন্টারভিউতে:
- DAC আর MAC-এর পার্থক্য? DAC-এ মালিক ঠিক করেন, MAC-এ কেন্দ্রীয় নীতি, যা মালিক বদলাতে পারেন না।
- Permissive আর disabled? Permissive নীতি মেলায় ও log করে, আটকায় না। Disabled-এ MAC কাজই করে না।
- uid আর auid? uid চলতি অধিকার, auid প্রথম login-এর পরিচয়, যা sudo-তেও টেকে।
- umask 027-এ নতুন ফাইল আর folder? ৬৪০ আর ৭৫০।
- FIM আর auditd-এর পার্থক্য? FIM বলে কী বদলেছে, auditd বলে কে কখন বদলালেন। দুটি একসাথে পুরো গল্প দেয়।
১০ · AI-এর যুগে hardening — দ্রুত উত্তর, কিন্তু খোলা দরজা
AI খুব দ্রুত config লিখে দেয়, আর denial বুঝতেও সাহায্য করে। কিন্তু সে আপনার server-এর কাজ জানে না। সবচেয়ে বিপজ্জনক অভ্যাস হলো error সরানোর জন্য নিরাপত্তা বন্ধের পরামর্শ।
| AI-এর পরামর্শ | সমস্যা | যা করবেন |
|---|---|---|
setenforce 0 বা SELINUX=disabled | পুরো মেশিনের পাহারা বন্ধ | Denial পড়ে label, boolean বা ছোট নীতি ঠিক করুন |
chmod -R 777 | সবাইকে লেখার অধিকার | সঠিক মালিক, group আর সবচেয়ে ছোট mode |
| নেই এমন directive বা sysctl key | Service চলবে না, বা নিয়ম নীরবে উপেক্ষিত হবে | man পাতা দেখুন, sshd -t আর sshd -T চালান |
| বানানো CVE বা CIS নিয়মের নম্বর | ভুল প্রমাণে সিদ্ধান্ত | NVD আর আসল Benchmark-এর দলিলে মেলান |
| Paste করা log বিশ্লেষণে অতি-নিশ্চিত উত্তর | ভুল triage, আর secret ফাঁসের ঝুঁকি | Host, user আর token মুছে দিন; রায় মানুষ দেবেন |
AI-কে সমাধান চাপানোর জন্য নয়, নিজের system পর্যালোচনায় সাহায্যের জন্য ব্যবহার করুন। পাঠানোর আগে হোস্টের নাম, IP আর ব্যবহারকারীর তথ্য সরিয়ে ফেলুন:
AI-এর দেওয়া hardening যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর উত্তর খুলুন।
প্র ০১একটি server-এর CIS score ১০০%. তাহলে কি সেটি নিরাপদ?
না। Score বলে তালিকার নিয়মগুলো মিলেছে। সে বলে না যে আপনার ঝুঁকিগুলো ঢাকা পড়েছে। একটি benchmark সাধারণ OS-এর জন্য লেখা, তাই আপনার app-এর বাগ, দুর্বল API, বেশি অধিকারের database account বা ফাঁস হওয়া token তার দৃষ্টির বাইরে থাকতে পারে।
Equifax-এর ২০১৭ সালের ঘটনা ভালো শিক্ষা। প্রকাশিত প্রতিবেদন অনুযায়ী একটি web application framework-এর জানা ত্রুটির patch সময়মতো বসেনি। মার্কিন কংগ্রেসের ২০১৮ সালের প্রতিবেদন আরও জানায়, traffic দেখার একটি যন্ত্রের certificate প্রায় ১৯ মাস মেয়াদোত্তীর্ণ ছিল, ফলে নজরদারিতে বড় ফাঁক ছিল। অর্থাৎ শুধু নিয়ম লেখা থাকলেই হয় না। সেটি কাজ করছে কি না, তা মাপা চাই। একটি audit agent বসানো আছে, কিন্তু তার log কেউ দেখে না, এমন অবস্থাও score-এ ধরা পড়বে না।
উল্টো দিকও আছে। ৭৫% score-এর একটি server-এর সব বাদ পড়া নিয়মের লিখিত কারণ আর বিকল্প ব্যবস্থা থাকতে পারে। সেটি হয়তো অন্ধভাবে ১০০% করা server-এর চেয়ে ভালো বোঝা ব্যবস্থা। আর score-কে লক্ষ্য বানালে মানুষ সংখ্যা বাড়ানোর পথ খোঁজে, নিরাপত্তা বাড়ানোর পথ নয়। Compliance নিরাপত্তার একটি মেঝে, ছাদ নয়।
কাজের প্রশ্নগুলো তাই ভিন্ন: কোন হামলার পথ বন্ধ হলো? কোন পরীক্ষা তা প্রমাণ করে? নিয়ন্ত্রণটি ভাঙলে কে জানবেন, আর কত দ্রুত? Threat model-এর সাথে benchmark মেলালে এসব প্রশ্নের উত্তর পাওয়া যায়, আর তখন বোঝা যায় কোন নিয়ম আপনার জন্য সবচেয়ে জরুরি।
মূল উপলব্ধি: Score একটি যন্ত্র, লক্ষ্য নয়। আসল মাপ হলো আপনার ঝুঁকি কতটা কমল, আর তা প্রমাণ করা যায় কি না।
প্র ০২এত মানুষ SELinux বন্ধ করে দেন কেন, আর তার দাম কী?
কারণটি মানবিক। রাত দুটোয় সাইট বন্ধ, আর error বলছে শুধু Permission denied. ls -l-এ সব ঠিক। ইন্টারনেটের কোনো উত্তর বলছে setenforce 0. এক লাইনে সমস্যা শেষ, তাই শেখা হলো: SELinux মানেই ঝামেলা। অনেক পুরোনো টিউটোরিয়ালের প্রথম ধাপই ছিল এটি বন্ধ করা, আর সেই অভ্যাস আজও AI-এর উত্তরে ফিরে আসে।
SELinux-এর দিকেও দোষ আছে। Type enforcement ধারণাটি কঠিন, ত্রুটি বার্তা শুরুতে অস্পষ্ট ছিল, আর নীতি জটিল। NSA-র গবেষণা থেকে আসা এই ব্যবস্থা প্রথমে উচ্চ-নিরাপত্তার পরিবেশের কথা ভেবে বানানো। পরে Fedora আর RHEL-এর targeted নীতি নির্দিষ্ট network-মুখী service-কে ঘিরে বাস্তবে ব্যবহারযোগ্য করে তোলে। sealert, audit2why আর boolean-এর মতো টুলও এই দূরত্ব কমিয়েছে।
বন্ধ করার দাম সাথে সাথে দেখা যায় না, এটাই সমস্যা। Web server-এর একটি বাগ দিয়ে কেউ ঢুকলে enforcing অবস্থায় সে হয়তো web-এর label-এর ভেতরে আটকে থাকত। MAC বন্ধ থাকলে তাকে থামায় শুধু সাধারণ অনুমতি। অনেক হামলা পরের ধাপেই ব্যর্থ হয় MAC-এর কারণে, আর সেই ব্যর্থতাই AVC log-এ detection-এর সংকেত হতে পারে। বন্ধ করলে সেই সংকেতও হারায়।
আরও একটি ব্যবহারিক দাম আছে। অনেক দিন disabled থাকার পরে আবার চালু করতে পুরো filesystem-এর relabel লাগতে পারে, আর ততদিনে app-গুলো ভুল ধরে নেওয়া অবস্থায় অভ্যস্ত। তাই সাময়িক বন্ধ প্রায়ই স্থায়ী হয়ে যায়।
ভালো মাঝের পথ আছে। পুরো মেশিন নয়, শুধু একটি domain permissive করে নীতি শেখা যায়, তারপর enforcing-এ ফেরা যায়।
মূল উপলব্ধি: নিরাপত্তা ব্যবস্থা বন্ধ করে পাওয়া সমাধান আসলে একটি অদৃশ্য ঋণ। Denial পড়ার পাঁচ মিনিট সেই ঋণ বাঁচায়।
প্র ০৩হামলাকারী root পেয়ে গেলে MAC, auditd বা FIM-এর কি আর কোনো দাম থাকে?
উত্তর নির্ভর করে root বলতে কী বোঝাচ্ছি তার ওপর। Enforcing SELinux-এ uid 0 মানেই সর্বশক্তিমান নয়। Process যদি একটি সীমিত domain-এ থাকে, root হয়েও সে সেই domain-এর বাইরে যেতে পারে না। ২০১৯ সালের runc-এর container escape ত্রুটি CVE-2019-5736 এর পরিচিত উদাহরণ। Red Hat তখন জানায়, RHEL 7-এ SELinux enforcing থাকলে এটি প্রশমিত হয়। তবু সমাধান হিসেবে তারা আপডেট দিয়েছিল। তারা আরও সতর্ক করে যে permissive-এর log-এর ওপর ভরসা করা যায় না, কারণ root log বদলাতে পারে।
তবে সীমাও স্পষ্ট। হামলাকারী যদি unconfined root পায় বা kernel-এর বাগ কাজে লাগায়, MAC নিজেও বিপদে পড়ে, কারণ MAC kernel-এর ভেতরেই চলে। তখন সে স্থানীয় নীতি বদলাতে, log মুছতে বা AIDE database পাল্টাতে পারে। এই কারণেই স্থানীয় ব্যবস্থার ওপর একা ভরসা করা যায় না।
তাই নকশার মূল কথা হলো প্রমাণ দ্রুত মেশিনের বাইরে নেওয়া। -e 2 নিয়ম বদলাতে reboot বাধ্য করে, আর reboot নিজেই একটি দৃশ্যমান ঘটনা। Central log-এ যা আগেই পৌঁছে গেছে, স্থানীয় root তা মুছতে পারে না। FIM-এর baseline read-only বা বাইরে রাখা হলে মিথ্যা ফলও কঠিন হয়। Tripwire, যা ১৯৯২ সালে Purdue-তে Gene Kim আর Gene Spafford বানান, শুরু থেকেই এই ধারণায় জোর দিয়েছিল: যাচাইকারীর নিজের সত্যের উৎস সুরক্ষিত হতে হবে।
আর সময়ের মূল্যও আছে। প্রতিটি বাধা হামলাকারীকে বেশি কাজ করায়, বেশি শব্দ করায়। Log মুছে ফেলার চেষ্টা বা হঠাৎ log থেমে যাওয়াও একটি সংকেত।
মূল উপলব্ধি: এসব ব্যবস্থা অভেদ্য নয়। তাদের কাজ হামলার পরের ধাপ থামানো, এবং না পারলে এমন প্রমাণ রেখে যাওয়া, যা মেশিনের মালিকানা হারালেও টিকে থাকে।
প্র ০৪স্বয়ংক্রিয় update কি সব server-এ চালু রাখা উচিত?
এখানে দুটি ঝুঁকি মুখোমুখি। এক দিকে দেরি করা patch. জানা ত্রুটি প্রকাশের পরে স্বয়ংক্রিয় স্ক্যান খুব দ্রুত শুরু হতে পারে। ছোট দলের একটি server-এ কেউ প্রতিদিন update দেখবেন না, তাই সেখানে স্বয়ংক্রিয় নিরাপত্তা update প্রায় সবসময়ই ভালো সিদ্ধান্ত।
অন্য দিকে খারাপ update. ২০২৪ সালের জুলাইয়ে একটি endpoint নিরাপত্তা পণ্যের ভুল content update বিশ্বজুড়ে বহু Windows কম্পিউটারকে অচল করে দেয়, যার মধ্যে বিমান সংস্থা আর হাসপাতালও ছিল। আরও পুরোনো শিক্ষা হলো, একসাথে সব জায়গায় পরিবর্তন মানে একই ভুল একসাথে সব জায়গায়। আবার ২০২৪ সালের xz ঘটনায় (CVE-2024-3094) একটি compression library-র নতুন version-এ backdoor ঢোকানোর চেষ্টা ধরা পড়ে, যদিও তা মূলত নতুন বা পরীক্ষামূলক distribution পর্যন্ত পৌঁছেছিল। অর্থাৎ “সবার আগে সবচেয়ে নতুন” সবসময় নিরাপদ নয়।
তাই উত্তরটি ধাপে সাজানো। Stable distribution-এর নিরাপত্তা শাখাই নিন, যেখানে সাধারণত ছোট সংশোধন আসে। Server-গুলোকে ভাগ করুন: প্রথমে test, তারপর ছোট canary দল, শেষে বাকি। নিয়ন্ত্রিত সময়ে reboot করুন। প্রতিটি ধাপের পরে smoke test চালান। আর দ্রুত ফেরার পথ রাখুন। NIST SP 800-40 Rev. 4 (২০২২) এই কাজকে শুধু কারিগরি নয়, প্রতিষ্ঠানের ঝুঁকি ব্যবস্থাপনার অংশ হিসেবে দেখে, আর আগে থেকে পরিকল্পিত রক্ষণাবেক্ষণের কথা বলে।
একটি পার্থক্য মনে রাখুন। Database-এর একক primary-র মতো সংবেদনশীল মেশিনে হয়তো স্বয়ংক্রিয় reboot নয়, কিন্তু দ্রুত পরিকল্পিত update দরকার। “Auto নয়” মানে “পরে দেখা যাবে” নয়।
মূল উপলব্ধি: প্রশ্নটি auto বনাম manual নয়। প্রশ্ন হলো, জানা ত্রুটি কত দ্রুত বন্ধ হয়, আর খারাপ update কত ছোট জায়গায় থেমে যায়।
প্র ০৫NIST বলছে নিয়মিত password বদলাতে হবে না, কিন্তু benchmark বা নিরীক্ষক বলছেন ৯০ দিন। কার কথা শুনবেন?
প্রথমে ইতিহাস। বহু বছর ধরে ৩০ বা ৯০ দিনে password বদলানো ছিল স্বাভাবিক নিয়ম। পরে গবেষণা দেখায়, মানুষ এতে দুর্বল আর অনুমানযোগ্য পরিবর্তন করেন, যেমন শেষের সংখ্যাটি এক বাড়ানো। তাই NIST SP 800-63B ২০১৭ সালের সংস্করণ থেকেই নিয়মিত জোর করে বদলের বিপক্ষে গেছে, আর Rev. 4 (২০২৫) সেই অবস্থান ধরে রেখেছে: বদল হবে আপসের প্রমাণে। সাথে blocklist আর MFA-র মতো ব্যবস্থায় জোর।
কিন্তু benchmark আর চুক্তি একই গতিতে বদলায় না। কিছু benchmark, STIG বা industry standard-এ বয়সের সীমা থাকতে পারে, version-ভেদে তা আলাদা। আপনার প্রতিষ্ঠান যদি কোনো চুক্তি বা নিরীক্ষার অধীনে থাকে, তখন শুধু NIST-এর নাম বললেই নিরীক্ষকের নিয়ম উঠে যাবে না। আর 800-63B মূলত digital identity-র নির্দেশিকা, প্রতিটি Linux local account-এর জন্য লেখা আইন নয়।
তাই সিদ্ধান্তের পথটি এমন। আগে জানুন কোন নিয়ম আপনার জন্য বাধ্যতামূলক, আর কোনটি পরামর্শ। বাধ্যতামূলক হলে মানুন, কিন্তু ক্ষতি কমান। পরামর্শ হলে ঝুঁকি বুঝে বেছে নিন, আর ব্যতিক্রম লিখে রাখুন। অনেক সময় প্রশ্নটিই সরে যায়: server-এ SSH key বা certificate-এ login, sudo-তে MFA, আর password login বন্ধ থাকলে local password-এর বয়সের গুরুত্ব অনেক কমে। Service account-এর credential আলাদা বিষয়; সেখানে নিয়মিত rotation স্বয়ংক্রিয়ভাবে করা ভালো।
এখানে আসল দক্ষতা নিয়ম মুখস্থ করা নয়। প্রমাণ দেখিয়ে কথা বলা, compensating control প্রস্তাব করা, আর নিরীক্ষকের ভাষায় তা লিখে দেওয়াই আসল কাজ।
মূল উপলব্ধি: Standard পরস্পরের সাথে মেলে না, কারণ তাদের উদ্দেশ্য, সময় আর পাঠক আলাদা। ভালো নিরাপত্তা-প্রকৌশলী ঠিক করেন কোনটি বাধ্যতামূলক, কোনটি ঝুঁকি কমায়, আর সিদ্ধান্তটি লিখে রাখেন।
অনুশীলন
কাগজে বা নিজের test machine-এ করুন। অন্যের system-এ নয়।
-
হিসাব: (ক)
umask 007-এ নতুন ফাইল আর folder-এর mode কত? (খ)umask 037-এ নতুন ফাইলের mode কত? (গ) একটি audit-এ ওজন ৩, ৩, ২, ২, ১। প্রথম ৩ আর একটি ২ fail করেছে, আর ১ ওজনের নিয়মটি লিখিত ব্যতিক্রম, যা গণনার বাইরে। Score কত?(ক) ফাইল ৬৬০, folder ৭৭০। Others-এর সব bit মুছে গেছে।
(খ) ৬৪০। মাঝের ঘরে ৬ (
110) থেকে ৩ (011)-এর bit মুছে100= ৪। শেষ ঘরে ৬ থেকে ৭ মুছে ০। ঘর ধরে বিয়োগ করলে মাঝের ঘরে ভুলভাবে ৩ আসত।(গ) ব্যতিক্রম বাদে মোট ওজন ৩ + ৩ + ২ + ২ = ১০। Fail ৩ + ২ = ৫, পাস ৫। Score ৫ ÷ ১০ = ৫০%.
-
ফল অনুমান করুন: একটি খালি folder-এ, ধরে নিন
chmodসফল হয়, এই ক্রমে command চালানো হলো:umask 027; mkdir d; touch d/f; chmod o+w d/f; find d -perm -0002. শেষেdআরd/f-এর mode কী?findকী ছাপবে? অন্য একজন সাধারণ user কি ফাইলটি লিখতে পারবেন?dহবে ৭৫০।d/fশুরুতে ৬৪০, তারপর others-এ write যোগ হয়ে ৬৪২।findছাপবেd/f, কারণ তাতে others-এর write আছে।তবু others-এর ব্যবহারকারী লিখতে পারবেন না, কারণ
d-তে others-এর execute নেই, তাই folder পেরিয়ে ফাইলে পৌঁছানো যায় না। শিক্ষা: একটি ফাইলের mode একা পুরো গল্প বলে না, পথের প্রতিটি folder-ও দেখতে হয়। তবু অডিটে এটি ঠিক করা উচিত, কারণ পরে folder-এর অনুমতি বদলালে ঝুঁকিটি জেগে উঠবে। -
Rule লেখা: কাল্পনিক
bazar-api-র config থাকে/etc/bazar/-এ, আর data/var/lib/bazar/-এ। (ক) ওই config folder-এর write ও attribute বদল ধরার auditd rule লিখুন, keybazar_cfg. (খ) আজকের ঘটনা খোঁজার command লিখুন। (গ) কোন systemd directive দুটি দিয়ে service-কে শুধু data folder-এ লিখতে দেবেন?(ক)
-w /etc/bazar/ -p wa -k bazar_cfg(খ)
sudo ausearch -k bazar_cfg -i --start today(গ)
ProtectSystem=strictআরReadWritePaths=/var/lib/bazar. এরপরে health আর লেখার আসল কাজ, দুটোই পরীক্ষা করুন। -
সমালোচনা করুন: একজন সহকর্মীর script: (১)
SELINUX=disabledলেখে, “যাতে app ঝামেলা না করে”; (২)chmod -R 777 /var/www; (৩) audit rule ফাইলের প্রথম লাইনে-e 2; (৪) একশো production server-এ একসাথে চলে; (৫) শেষে শুধু “Done” ছাপে। প্রতিটির সমস্যা আর ভালো বিকল্প লিখুন।- (১) পুরো MAC বন্ধ। Denial পড়ে label, boolean বা ছোট নীতি ঠিক করুন।
- (২) যে কেউ web ফাইল বদলাতে পারে। সঠিক মালিক রাখুন, ফাইল ৬৪০ বা ৬৪৪, folder ৭৫০ বা ৭৫৫, আর লেখা শুধু uploads-এ।
- (৩)
-e 2-এর পরের নিয়ম আর লোড হবে না, কারণ নিয়ম আটকে গেছে। এটি সবার শেষে বসান, আর পাকা হওয়ার পরে। - (৪) একটি ভুল সবগুলোতে ছড়াবে। আগে test, তারপর ছোট দল, পর্যবেক্ষণ শেষে বাকি।
- (৫) “Done” কোনো প্রমাণ নয়। কার্যকর মান দেখা, smoke test আর ফেরার পথ যোগ করুন, আর script-টি পর্যালোচনাযোগ্য configuration management-এ তুলুন।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি hardening পরিবর্তনের নিরাপদ ক্রম সাজান (▲▼ চেপে সরান)
- Server-এর কাজ আর বর্তমান অবস্থা মাপা
- Test machine-এ একটি পরিবর্তন প্রয়োগ করা
- কার্যকর মান আর সেবা পরীক্ষা করা
- পর্যালোচনার পরে configuration management-এ তোলা
- ছোট দল থেকে ধাপে ধাপে production-এ ছড়ানো
একটি SELinux-চালিত server-এ ls -l-এ অনুমতি ঠিক থাকলেও nginx ফাইল পড়তে পারছে না। AVC-তে tcontext হিসেবে user_home_t দেখা যাচ্ছে। ঠিক প্রথম পদক্ষেপ কোনটি?
setenforce 0স্থায়ী করাsemanage fcontextদিয়ে নিয়ম লিখেrestoreconচালানোchmod 777করাaudit2allow-এর policy সরাসরি বসানো
umask 027 থাকলে নতুন ফাইল আর নতুন folder-এর mode কী হবে?
- ৬৪৪ আর ৭৫৫
- ৬০০ আর ৭০০
- ৬৪০ আর ৭৫০
- ৬৬০ আর ৭৭০
Audit log-এ একটি ঘটনায় auid=rina আর uid=root আছে। এর অর্থ কী?
- rina-র login session থেকে কাজটি root অধিকারে হয়েছে
- এটি নিশ্চিতভাবে একটি হামলার প্রমাণ
- root সরাসরি login করেছে
- ফাইলটির মালিক rina
Enforcing আর permissive mode-এর মূল পার্থক্য কী?
- Permissive-এ কোনো log হয় না
- Enforcing শুধু AppArmor-এ থাকে
- Permissive বেশি কড়া
- Enforcing আটকায়, permissive আটকায় না কিন্তু log করে
একটি file integrity alert বলছে /etc/ssh/sshd_config বদলেছে। প্রথমে কী করা উচিত?
- সাথে সাথে baseline আপডেট করা
- Audit log, change ticket আর অনুমোদিত কপির সাথে মিলিয়ে তদন্ত করা
- ওই ফাইলকে নজরদারি থেকে বাদ দেওয়া
- সাথে সাথে server মুছে নতুন করে install করা
একটি service-এ ProtectSystem=strict যোগ করার পরে health check 200 দিচ্ছে, কিন্তু upload 500 দিচ্ছে আর log-এ Read-only file system. ভালো সমাধান কোনটি?
- পুরো sandbox সরিয়ে ফেলা
- Service-কে root হিসেবে চালানো
ReadWritePaths-এ শুধু upload-এর folder যোগ করা- Health 200, তাই কিছু না করা
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Hardening মানে নিজের server-এর কাজের মাপে attack surface আর অধিকার ছোট করা, আর ঘটনা দৃশ্যমান করা।
- CIS Benchmark আর STIG ভালো শুরু, কিন্তু role বুঝে প্রয়োগ করুন এবং ব্যতিক্রম লিখে রাখুন।
- auditd বলে কে করলেন, FIM বলে কী বদলাল, আর central log সেই প্রমাণ বাঁচায়।
- SELinux বা AppArmor আটকালে denial পড়ুন, সবচেয়ে ছোট সমাধান দিন, আর enforcing অবস্থায় ফিরে পরীক্ষা করুন।
- একবারে একটি বদল: কার্যকর মান, আসল সেবা আর ফেরার পথ, তিনটিই যাচাই করে তবে শেষ বলুন।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৩১ · Windows আর Active Directory সুরক্ষা — tiering, LAPS আর auditপরবর্তী পর্বপ্রতিষ্ঠানের Windows জগৎ আর তার পরিচয় ব্যবস্থার সুরক্ষা।
- সাইবার নিরাপত্তা · কোর্স হোম৮০টি পর্বপুরো কোর্সের রোডম্যাপ।
- seccomp, SELinux আর AppArmorগভীরে যানType enforcement, Bell–LaPadula, Biba আর seccomp-এর তত্ত্ব।
- OS নিরাপত্তাপাশের ট্র্যাকMemory-safety, ASLR আর kernel-এর নিজের পাহারা।
- SSH — নিরাপদ দূরবর্তী প্রবেশপাশের ট্র্যাকKey, bastion, sshd শক্ত করা আর SSH certificate.
- Ansible আর immutable infrastructureপাশের ট্র্যাকHardening-কে কোডে তোলার পদ্ধতি।