SSD Nodes Learn 🎉 VPS $5.50/माह से
गाइड Matt Connorलेखक: Matt Connor

Linux सर्वर पर उपयोगकर्ताओं के कमांड्स को कैसे ट्रैक करें

Shell history भरोसेमंद नहीं है। Sudo logging, session recording, shell hooks और auditd execve नियमों की तुलना करें। लॉग्स को सर्वर से बाहर सुरक्षित भेजने का सही तरीका जानें।

सर्वर पर उपयोगकर्ताओं द्वारा चलाए गए कमांड्स को वास्तव में क्या रिकॉर्ड करता है

सर्वर पर उपयोगकर्ताओं द्वारा चलाए गए कमांड्स का ऑडिट करने के लिए, आपको एक ऐसे रिकॉर्ड की आवश्यकता होती है जिसे उपयोगकर्ता संपादित न कर सके। Shell history ऐसा रिकॉर्ड नहीं है। यह केवल सुविधा के लिए बनाई गई एक फाइल है, जिसका स्वामित्व उसी अकाउंट के पास होता है जिसने इसे लिखा है, और जो कोई भी उस shell में टाइप कर सकता है, वह इसे बंद या डिलीट भी कर सकता है।

चार परतें (layers) एक वास्तविक रिकॉर्ड रखती हैं, और प्रत्येक की अपनी लागत है। sudo प्रत्येक कमांड की एक लाइन syslog में लिखता है। sudo I/O logging एक अकाउंट के पूरे सत्र (session) को कैप्चर करती है। PROMPT_COMMAND जैसा shell hook यह लॉग करता है कि एक interactive bash उपयोगकर्ता ने क्या टाइप किया। kernel audit subsystem स्वयं execve syscall को रिकॉर्ड करता है, यही कारण है कि यह एकमात्र ऐसी परत है जो हर process को देख पाती है। यह गाइड इसी क्रम में आगे बढ़ती है, यह बताती है कि प्रत्येक परत कहाँ समाप्त होती है, और अंत में उस हिस्से पर चर्चा करती है जो यह तय करता है कि क्या यह सब किसी काम का है: रिकॉर्ड्स को मशीन से बाहर भेजना, इससे पहले कि जिस व्यक्ति का आप ऑडिट कर रहे हैं, वह उन तक पहुँच सके।

शुरू करने से पहले एक चेतावनी। audit subsystem kernel का कार्य है, इसलिए इनमें से किसी का भी परीक्षण ऐसे container के अंदर नहीं किया जा सकता जो host kernel को साझा करता हो। इन कमांड्स को KVM VPS पर चलाएं जहाँ kernel आपका अपना हो।

शेल हिस्ट्री ऑडिट ट्रेल क्यों नहीं है

~/.bash_history चार सामान्य कारणों से सबूत के तौर पर विफल हो जाता है, और इनमें से किसी के लिए भी चतुर हमलावर की आवश्यकता नहीं है।

यह यूजर का होता है। फाइल का मोड 600 होता है और यह उस अकाउंट के स्वामित्व में होती है, इसलिए rm ~/.bash_history के लिए किसी विशेषाधिकार की आवश्यकता नहीं होती। इसे किसी एडिटर में खोलकर उन बीस लाइनों को हटाना भी आसान है जो मायने रखती हैं।

यह शेल के बंद होने पर लिखी जाती है। जो सेशन kill -9 $$ के साथ समाप्त होता है, या जिसका कनेक्शन टूट जाता है, वह कुछ भी नहीं लिखता। exit से पहले history -c का भी यही प्रभाव होता है और ऐसा लगता है जैसे कुछ हुआ ही नहीं।

यह एक शब्द से बंद हो जाता है। unset HISTFILE उस सेशन के लिए फाइल में कुछ भी लिखने से रोकता है। set +o history रिकॉर्डिंग को तुरंत बंद कर देता है। HISTCONTROL=ignorespace स्पेस के साथ टाइप की गई हर कमांड को छिपा देता है। यह सब man bash में मौजूद है, क्योंकि इसे यूजर के नियंत्रण में रहने के लिए बनाया गया है।

यह रिकॉर्ड करता है कि क्या टाइप किया गया था, न कि क्या चला। किसी alias या शेल फंक्शन का मतलब है कि फाइल में मौजूद टेक्स्ट वह प्रोग्राम नहीं है जिसे kernel ने निष्पादित किया।

इसमें कोई टाइमस्टैम्प भी नहीं होता, जब तक कि एंट्री लिखते समय HISTTIMEFORMAT सेट न हो, क्योंकि bash अपनी #1755043200 मार्कर लाइनें केवल तभी लिखता है जब वह वेरिएबल सेट होता है।

शेयर्ड लॉगिन पर यह यह भी नहीं बता सकता कि किसने किया। एक deploy अकाउंट का उपयोग करने वाले तीन लोग एक ही uid के तहत एक इंटरलीव्ड फाइल बनाते हैं। कोई भी लॉगिंग लेयर किसी क्रिया को इंसान से तब तक नहीं जोड़ सकती जब तक दो इंसान एक ही uid साझा करते हैं, जो शेयर्ड लॉगिन के बजाय प्रति व्यक्ति एक अनप्रिविलेज्ड अकाउंट रखने का व्यावहारिक तर्क है।

शेल हिस्ट्री अपने वास्तविक काम में अच्छी है, जो कि कल की कमांड को दोबारा टाइप करने में आपकी मदद करना है। इसे केवल एक संकेत के रूप में उपयोग करें। इसे कभी भी सबूत के तौर पर पेश न करें।

sudo क्या लॉग करता है और यह कहाँ रुकता है

sudo अपने द्वारा चलाए गए प्रत्येक कमांड की एक लाइन authpriv syslog सुविधा को भेजता है।

sudo grep 'sudo:' /var/log/auth.log | tail -5
journalctl -t sudo -n 5

प्रत्येक लाइन में उपयोगकर्ता, टर्मिनल, वर्किंग डायरेक्टरी, टारगेट उपयोगकर्ता और कमांड का नाम होता है:

sudo:    alice : TTY=pts/0 ; PWD=/home/alice ; USER=root ; COMMAND=/usr/bin/apt update

यदि /var/log/auth.log मौजूद नहीं है, तो उस इमेज पर rsyslog इंस्टॉल नहीं है और वही रिकॉर्ड केवल journal में होते हैं। उस पर निर्भर होने से पहले जाँच लें कि journal वोलेटाइल (अस्थायी) तो नहीं है:

journalctl --list-boots

केवल वर्तमान बूट का लिस्ट होना यह दर्शाता है कि /var/log/journal मौजूद नहीं है, इसलिए journal /run में रहता है और हर लाइन अगले रीबूट पर मिट जाती है। इसे स्थायी बनाएँ:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

अब सीमा की बात। sudo उस कमांड को लॉग करता है जिसे चलाने के लिए कहा गया था। यह यह लॉग नहीं करता कि वह कमांड बाद में क्या करता है। इसलिए एक लाइन ट्रेल को समाप्त कर देती है:

sudo -i

लॉग में शेल के लिए केवल एक रिकॉर्ड मिलता है। उस root शेल के अंदर टाइप किया गया हर कमांड sudo के लिए अदृश्य होता है, क्योंकि sudo अब पाथ में नहीं है। sudo su -, sudo bash, और sudo vim /etc/shadow के बाद :!bash का उपयोग करने पर सभी का स्वरूप एक जैसा होता है। एक sudoers नियम जो शेल एस्केप वाले किसी भी प्रोग्राम की अनुमति देता है, जैसे कि vim या find, वह नियम अनलॉग किए गए root एक्सेस की अनुमति देता है। किसी अकाउंट की लॉग लाइनों पर भरोसा करने से पहले यह पढ़ें कि वह वास्तव में कहाँ तक पहुँच सकता है:

sudo -l -U alice

एक अकाउंट के लिए पूर्ण सत्र रिकॉर्ड करना

सबसे पहले पता करें कि आपके पास कौन सा sudo है, क्योंकि यह सुविधा Rust rewrite में मौजूद नहीं है:

sudo --version | head -1

यदि आउटपुट में sudo-rs दिखाई दे, तो इस अनुभाग को छोड़ दें और audit subsystem का उपयोग करें। Ubuntu के 25.10 और 26.04 releases के लिए आधिकारिक दस्तावेज़ में I/O logging और sudoreplay को समर्थित नहीं बताया गया है, और अगस्त 2026 तक यह स्थिति बनी हुई थी। यह महत्वपूर्ण है क्योंकि उन releases पर sudo-rs डिफ़ॉल्ट sudo है, इसलिए एक upgrade उस नियंत्रण को हटा सकता है जिसके बारे में आपने सोचा था कि वह आपके पास है। sudo-rs व्यवहार परिवर्तनों की पूरी सूची को पढ़ना किसी भी sudo-आधारित लॉगिंग की योजना बनाने से पहले उपयोगी है।

मूल sudo के साथ, जिसे Ubuntu 24.04 LTS अभी भी प्रदान करता है, एक अकाउंट के लिए I/O logging चालू करें:

sudo visudo -f /etc/sudoers.d/iolog
Defaults:deploy log_output
Defaults!/usr/bin/sudoreplay !log_output

किसी एडिटर के बजाय visudo का उपयोग करें, क्योंकि यह ऐसी फ़ाइल को सेव करने से मना कर देता है जो पार्स नहीं होती। एक खराब sudoers फ़ाइल हर किसी को sudo से बाहर कर देती है। फिर एक सत्र को फिर से चलाएं (replay):

sudo sudoreplay -l user=deploy
sudo sudoreplay 000001

sudoreplay -l सत्रों को उनकी IDs के साथ सूचीबद्ध करता है और यदि log_output उस उपयोगकर्ता पर कभी लागू नहीं हुआ है तो कुछ भी प्रिंट नहीं करता है। इसकी लागत: टर्मिनल से गुजरने वाला प्रत्येक बाइट /var/log/sudo-io के अंतर्गत संग्रहीत होता है, इसलिए एक विस्तृत सत्र बड़ा होता है। दूसरी sudoers लाइन replay को खुद को रिकॉर्ड करने से रोकती है। वास्तविक लागत secrets की है, क्योंकि एक I/O log में वह सब कुछ होता है जो टाइप और प्रिंट किया गया है, जिसमें सत्र के भीतर प्रॉम्प्ट में टाइप किया गया पासवर्ड भी शामिल है, इसलिए इसे पासवर्ड स्टोर के समान सुरक्षा की आवश्यकता होती है। कवरेज भी सीमित है। यह केवल sudo के माध्यम से चलाए गए कमांड्स को देखता है। कोई व्यक्ति जो लॉग इन करता है और पूरी तरह से स्वयं के रूप में काम करता है, वह बिल्कुल भी रिकॉर्ड नहीं होता है।

Shell hooks और उन्हें बायपास करने के तरीके

"हर कमांड को लॉग करने" के लिए जो तरीका प्रचलित है, वह PROMPT_COMMAND हुक है जिसे /etc/profile.d/ में डाला जाता है:

# /etc/profile.d/00-cmdlog.sh
PROMPT_COMMAND='logger -p local6.info -t cmdlog "$(whoami) $$ $(history 1 | sed "s/^ *[0-9]* *//")"'

bash हर प्रॉम्प्ट को दिखाने से पहले PROMPT_COMMAND को रन करता है, इसलिए कमांड टाइप होते ही syslog में पहुँच जाती है, न कि exit के समय। इसके अलावा, logger सिस्टम लॉग डेमन के माध्यम से लिखता है, इसलिए यूजर की अपनी फाइल अनुमतियों (file permissions) का इस पर कोई असर नहीं पड़ता। एक नया लॉगिन शेल खोलें और sudo tail -f /var/log/syslog के साथ जाँच करें, या यदि इमेज में rsyslog नहीं है तो journalctl -t cmdlog -f का उपयोग करें।

फिर यह काम करना बंद कर देता है, इसके पाँच तरीके हैं जिन्हें आप एक मिनट में दोहरा सकते हैं।

  • नॉन-इंटरैक्टिव शेल कभी प्रॉम्प्ट नहीं दिखाते। ssh you@server 'id' कमांड को रन करके वापस आ जाता है, और कुछ भी लॉग नहीं होता, क्योंकि PROMPT_COMMAND कभी इवैल्यूएट ही नहीं हुआ।
  • यह एक वेरिएबल है। unset PROMPT_COMMAND इसे बाकी सेशन के लिए डिसेबल कर देता है और इसके लिए किसी विशेषाधिकार (privilege) की आवश्यकता नहीं होती।
  • फाइल को लॉगिन शेल द्वारा पढ़ा जाता है। bash --noprofile --norc कभी भी /etc/profile.d/ को सोर्स नहीं करता।
  • यह bash-विशिष्ट है। vim के अंदर zsh, sh, python3 -c 'import os; os.system("id")' और :!id सभी ऐसे प्रोग्राम रन करते हैं जिन्हें कोई भी bash प्रॉम्प्ट हुक कभी नहीं देख पाएगा।
  • यह लाइन को टाइप किए गए अनुसार लॉग करता है, इसलिए कोई alias या function उस कमांड को छिपा सकता है जो वास्तव में रन हुई है।

शेल हुक का उपयोग सुविधा के लिए करें। यह सहयोगी उपयोगकर्ताओं के लिए "मैंने पिछले मंगलवार को क्या रन किया था" का उत्तर देता है। इसे किसी चेकलिस्ट में नियंत्रण (control) न मानें।

Kernel audit subsystem हर execve को देखता है

Linux audit subsystem, जो auditd daemon द्वारा संचालित होता है, यहाँ एकमात्र ऐसी परत है जिसे कोई user दरकिनार नहीं कर सकता, क्योंकि record syscall चलते ही kernel के भीतर बन जाता है। यदि कोई process किसी program को execute करती है, तो एक event उत्पन्न होता है। shell, language और terminal की उपस्थिति से कोई फर्क नहीं पड़ता।

sudo apt update && sudo apt install -y auditd audispd-plugins
sudo systemctl enable --now auditd
sudo auditctl -s

auditctl -s daemon की स्थिति को print करता है। pid के साथ non-zero enabled 1 का अर्थ है कि यह चल रहा है, और lost 0 का अर्थ है कि अभी तक कोई record drop नहीं हुआ है। उस lost counter को याद रखें, यह बाद में काम आएगा।

auid वह field है जो audit को उपयोगी बनाता है। जब session शुरू होता है तो PAM एक login uid सेट करता है, और kernel उसके बाद से हर child process पर इसे बनाए रखता है। अपना uid जाँचें:

cat /proc/self/loginuid

एक interactive SSH session आपके uid को print करता है, क्योंकि /etc/pam.d/sshd में pam_loginuid.so शामिल होता है। 4294967295 मान का अर्थ है कि loginuid कभी सेट नहीं किया गया था, जो boot के समय system daemon द्वारा शुरू की गई process के लिए सामान्य है। महत्वपूर्ण बात यह है कि sudo -i इसे बदलता नहीं है: alice द्वारा खोला गया root shell अभी भी auid 1000 रखता है, इसलिए इसके भीतर का हर command alice से संबंधित माना जाता है। यही वह कमी है जिसे sudo खुला छोड़ देता है। एक बार सेट होने के बाद loginuid को बदलने के लिए CAP_AUDIT_CONTROL की आवश्यकता होती है, जो सामान्य users के पास नहीं होती, और sudo auditctl --loginuid-immutable इसे अगले reboot तक root के लिए भी बंद कर देता है।

जाँचें कि /etc/pam.d/sshd, /etc/pam.d/login और /etc/pam.d/cron में से प्रत्येक में pam_loginuid.so शामिल है, अन्यथा events बिना किसी user पहचान के प्राप्त होंगे। यह वही file list है जिसे आप hardening SSH access on a VPS के दौरान edit करते हैं, इसलिए दोनों काम एक साथ करें।

auditd के लिए शुरुआती नियम सेट

नियम /etc/audit/rules.d/*.rules में रहते हैं। augenrules उन्हें फ़ाइल नाम के क्रम में एक सूची में जोड़ता है, और क्रम ही व्यवहार तय करता है, क्योंकि कर्नेल पहले मेल खाने वाले नियम पर रुक जाता है। कुछ भी जोड़ने से पहले मौजूदा नियमों को पढ़ें, क्योंकि बाद की फ़ाइल में मौजूद -D पहले लोड किए गए सभी नियमों को हटा देता है।

ls /etc/audit/rules.d/
cat /etc/audit/rules.d/audit.rules

इसके बाद /etc/audit/rules.d/50-exec.rules लिखें:

## Suppressions first: the kernel takes the first matching rule.
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-deb
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-query
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-split
-a never,exit -F arch=b64 -S execve -F exe=/usr/bin/dpkg-trigger

## Every program started by a logged-in human.
-a always,exit -F arch=b64 -S execve,execveat -F auid>=1000 -F auid!=unset -k exec
-a always,exit -F arch=b32 -S execve,execveat -F auid>=1000 -F auid!=unset -k exec

## Changes to who may become root.
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity

## Changes to the audit configuration itself.
-w /etc/audit/ -p wa -k auditconfig

इसे लोड करें और पुष्टि करें:

sudo augenrules --load
sudo auditctl -l

auditctl -l द्वारा आपके नियमों को वापस प्रिंट करने का मतलब है कि वे सक्रिय हैं। No rules का मतलब है कि लोड विफल हो गया, और journalctl -u auditd -n 20 उस फ़ाइल और लाइन को दर्शाता है जिसे पार्सर ने अस्वीकार कर दिया है। पुराना audit userspace unset कीवर्ड को नहीं समझता है। यदि लोडर उस फ़ील्ड के बारे में शिकायत करता है, तो इसके बजाय -F auid!=4294967295 लिखें, जो उसी मान को विस्तार से दर्शाता है।

अब इवेंट्स को वापस पढ़ें:

sudo ausearch -k exec -ts recent -i | tail -40
sudo ausearch -ul 1000 -ts today -i
sudo aureport -k --summary -i

-i uid और syscall नंबरों को नामों में बदल देता है, और व्यवहार में यह अनिवार्य है। -ts recent पिछले दस मिनटों को कवर करता है। प्रत्येक निष्पादन रिकॉर्ड के एक समूह के रूप में आता है: एक SYSCALL रिकॉर्ड जिसमें uid, auid, exit status और key होती है, एक EXECVE रिकॉर्ड जिसमें पूर्ण तर्क सूची होती है, साथ ही संदर्भ के लिए CWD और PATH रिकॉर्ड होते हैं।

एक ईमानदार सीमा, क्योंकि यह लोगों को भ्रमित करती है। audit syscalls को रिकॉर्ड करता है, और एक shell builtin अपना कोई syscall नहीं करता है। cd /root कोई प्रोग्राम नहीं चलाता है। bash प्रॉम्प्ट पर टाइप किया गया echo evil >> /etc/passwd भी कोई प्रोग्राम नहीं चलाता है, क्योंकि echo और रीडायरेक्ट दोनों पहले से चल रही shell प्रक्रिया के भीतर होते हैं। इसलिए execve नियम प्रोग्राम देखते हैं और -w नियम राइट्स (writes) देखते हैं। इनमें से कोई भी अकेले पर्याप्त नहीं है।

अंत में, कॉन्फ़िगरेशन को लॉक करें:

## /etc/audit/rules.d/99-finalize.rules
-e 2

-e 2 अगले रीबूट तक नियम सेट को अपरिवर्तनीय (immutable) बना देता है। इसके लोड होने के बाद, auditctl -s, enabled 2 रिपोर्ट करता है, और किसी भी नियम को जोड़ने या हटाने का कोई भी प्रयास Operation not permitted के साथ विफल हो जाता है, जिसमें root भी शामिल है। इस फ़ाइल को अंत में जोड़ें, और जब भी आप कोई नियम बदलना चाहें तो रीबूट की अपेक्षा रखें। यही इसका मुख्य उद्देश्य है: एक ऐसा नियम सेट जिसे कोई भी चुपचाप बंद कर सके, वह साक्ष्य नहीं है।

Audit log जिसे कोई नहीं पढ़ता, वह केवल एक compliance artefact है

auditd की विफलता का कारण यह नहीं है कि वह कुछ छोड़ देता है। समस्या यह है कि वह इतना अधिक डेटा रिकॉर्ड करता है कि कोई उसे कभी नहीं देखता, और फिर वह लॉग किसी प्रश्न का उत्तर देने के बजाय केवल एक चेकलिस्ट को पूरा करने के लिए मौजूद रहता है।

किसी भी चीज़ को ट्यून करने से पहले अपने बॉक्स पर स्वयं गणना करें:

sudo aureport -k --summary -i
sudo du -sh /var/log/audit

एक अकेला sudo apt upgrade हजारों अल्पकालिक (short-lived) processes चलाता है, और उनमें से प्रत्येक में आपका auid होता है, इसलिए एक पैकेज अपडेट मानवीय टाइपिंग के एक सप्ताह के काम से अधिक डेटा उत्पन्न कर सकता है। यही कारण है कि ऊपर दिए गए suppressions में dpkg और उसके सहायकों का नाम दिया गया है। हमेशा executable के आधार पर suppress करें, कभी भी user के आधार पर नहीं: /usr/bin/dpkg के लिए एक exclusion एक ऐसा छेद है जिसे आप एक वाक्य में समझा सकते हैं, जबकि किसी account के लिए exclusion एक ऐसा छेद है जिसका आकार बिल्कुल वैसा ही है जिसे आप पकड़ने की कोशिश कर रहे थे।

प्रत्येक नियम पर मौजूद -k key ही वह चीज़ है जो एक महीने बाद भी लॉग को खोजने योग्य बनाती है। ausearch -k sudoers एक ऐसा प्रश्न है जिसका उत्तर होता है। बिना किसी फ़िल्टर के ausearch टेक्स्ट की एक ऐसी दीवार है जो आपको पढ़ना बंद करने के लिए प्रशिक्षित करती है। यदि आपका कलेक्टर native format के बजाय JSON चाहता है, तो laurel एक auditd प्लगइन है जो प्रत्येक इवेंट को एक JSON ऑब्जेक्ट के रूप में फिर से लिखता है, जिसमें arguments डिकोड किए गए होते हैं। यह किसी अन्य प्लगइन की तरह /etc/audit/plugins.d/ में रजिस्टर होता है, और auditd sudo pkill -HUP auditd पर प्लगइन में हुए बदलावों को ग्रहण कर लेता है।

auditd की वास्तविक लागत क्या है

प्रत्येक matching syscall एक record बन जाता है जिसे kernel format करके userspace को भेजता है। इसकी लागत दो जगहों पर आती है, और दोनों को किसी और के प्रकाशित आंकड़ों से अनुमान लगाने के बजाय अपने स्वयं के workload पर मापा जा सकता है।

  • CPU और latency। एक मशीन जो लगातार fork करती है, जैसे कि build host या CI runner, प्रत्येक exec के लिए एक record बनाती है। जब kernel backlog भर जाता है, तो --backlog_wait_time kernel को उस process को रोकने के लिए मजबूर करता है जिसने event उत्पन्न किया है, जब तक कि जगह न बन जाए। इसलिए audit CPU percentage के बजाय slow builds के रूप में दिखाई देता है। वास्तविक load के तहत sudo auditctl -s में backlog और lost पर नज़र रखें। बढ़ते हुए lost का मतलब है कि records drop हो गए हैं, और silent gaps वाला log न होने वाले log से भी बदतर है, क्योंकि आप फिर भी उस पर भरोसा करेंगे।
  • Disk। /etc/audit/auditd.conf पढ़ें और सोच-समझकर निर्णय लें कि disk भरने पर क्या होगा, क्योंकि default values केवल एक राय हैं। max_log_file, num_logs और max_log_file_action rotation को नियंत्रित करते हैं। space_left_action, admin_space_left_action और disk_full_action emergency को नियंत्रित करते हैं, और उपलब्ध actions में से कुछ, जिनमें halt और single शामिल हैं, record खोने के बजाय मशीन को down कर देते हैं।

/etc/audit/rules.d/audit.rules में -f line kernel स्तर पर वही निर्णय है: -f 1 audit failure को syslog में report करता है, और -f 2 kernel को panic कर देता है। 2 को केवल तभी चुनें यदि आप वास्तव में record खोने के बजाय server खोना पसंद करेंगे। किसी ऐसे VPS पर जिस पर लोग निर्भर हैं, इसके बजाय rotation का उपयोग करें, और storage की समस्या को box से बाहर ले जाएं।

Logs को सर्वर से बाहर, लगभग real-time में भेजें

Incident reports बार-बार यही साबित करती हैं। यदि logs compromised host पर ही रह जाते हैं, तो उन्हें हमलावर द्वारा बदला जा सकता है। Root user /var/log/auth.log को फिर से लिख सकता है, /var/log/audit/audit.log को हटा सकता है और daemon को रोक सकता है। -e 2 नियमों को unload होने से रोकता है, लेकिन यह rm के खिलाफ कुछ नहीं करता। ऊपर दी गई हर परत तभी सबूत प्रदान करती है जब उसकी एक प्रति पहले ही मशीन से बाहर भेज दी गई हो।

Audit का अपना transport, audispd-plugins का audisp-remote plugin है। इसे /etc/audit/plugins.d/au-remote.conf में चालू करें:

active = yes
direction = out
path = /usr/sbin/audisp-remote
type = always
format = string

Reload करने से पहले path को command -v audisp-remote के विरुद्ध जाँचें, क्योंकि गलत path होने पर journal में केवल एक लाइन के अलावा कुछ नहीं मिलता। /etc/audit/audisp-remote.conf में remote_server और port सेट करें, और collector पर उसके अपने auditd.conf में tcp_listen_port = 60 सेट करें। sudo pkill -HUP auditd के साथ reload करें। कई images पर systemctl restart auditd को अस्वीकार कर दिया जाता है, क्योंकि unit file में RefuseManualStop=yes सेट होता है, इसलिए signal भेजना ही विश्वसनीय तरीका है।

दूसरा विकल्प audit को उस syslog stream में डालना है जिसे आप पहले से ही forward कर रहे हैं। active = no के साथ /etc/audit/plugins.d/syslog.conf आता है। इसे yes पर सेट करें, reload करें, और audit events sudo की लाइनों और बाकी सब के साथ जुड़ जाएंगे। फिर rsyslog के माध्यम से TLS (transport layer security) का उपयोग करके सबको forward करें, जिसके लिए rsyslog-gnutls package की आवश्यकता होती है:

# /etc/rsyslog.d/60-forward.conf
*.* action(type="omfwd"
    target="logs.example.net" port="6514" protocol="tcp"
    StreamDriver="gtls" StreamDriverMode="1"
    StreamDriverAuthMode="x509/name"
    StreamDriverPermittedPeers="logs.example.net"
    action.resumeRetryCount="-1"
    queue.type="linkedList" queue.filename="fwd" queue.saveOnShutdown="on")

Queue settings सबसे महत्वपूर्ण हिस्सा हैं। action.resumeRetryCount="-1" हमेशा retry करता है, और queue.saveOnShutdown="on" के साथ disk-assisted queue उन records को तब तक सुरक्षित रखती है जब तक collector unreachable होता है, और फिर वापस आने पर उन्हें भेज देती है। इन दोनों के बिना, collector के reboot होने पर आपके सबूतों में एक खाली जगह (hole) रह जाएगी और आपको यह बताने वाला भी कोई नहीं होगा कि वह खाली जगह मौजूद है। sudo systemctl restart rsyslog के साथ लागू करें, और किसी भी चीज़ पर भरोसा करने से पहले पुष्टि करें कि records वास्तव में collector पर पहुँच रहे हैं।

एक लूप अभी भी बंद करना बाकी है: collector ऐसी मशीन होनी चाहिए जिसमें audited लोग login न कर सकें। यदि log server पर root access उसी admin group के पास है, तो आपने केवल file की प्रतिलिपि बनाई है, उसे सुरक्षित नहीं किया है। अलग credentials, अलग keys, और आदर्श रूप से एक अलग provider account का उपयोग करें। यही वह तर्क है जो कई Linux servers को manage करने का एक केंद्रीय तरीका बनाने को उपयोगी बनाता है, और यही वह अंतर है जो compromised VPS पर काम करते समय पहले घंटे को उपयोगी या बेकार बनाता है।

जांचें कि एक सामान्य उपयोगकर्ता रिकॉर्ड को फिर से नहीं लिख सकता

मानने के बजाय दावे का परीक्षण करें। एक सामान्य खाते से, बिना sudo के:

echo test >> /var/log/auth.log
cat /var/log/audit/audit.log
auditctl -D
id -nG

क्रमवार ये परिणाम अपेक्षित हैं: Permission denied, क्योंकि auth.log का स्वामित्व syslog के पास है, जिसका समूह adm है और मोड 640 है; फिर से Permission denied, क्योंकि audit log का मोड 600 है और इसका स्वामित्व root के पास है; चलाने से इनकार करने वाली एक त्रुटि, क्योंकि audit rules बदलने के लिए CAP_AUDIT_CONTROL की आवश्यकता होती है; और एक समूह सूची जिसमें न तो adm है और न ही systemd-journal

वह अंतिम जांच ही वह है जिसमें लोग विफल हो जाते हैं। adm की सदस्यता /var/log/auth.log तक read access प्रदान करती है, और systemd-journal की सदस्यता पूरे journal तक read access प्रदान करती है। इनमें से कोई भी write access नहीं देता है, इसलिए कोई भी छेड़छाड़ की अनुमति नहीं देता है। दोनों ही किसी व्यक्ति को बॉक्स पर मौजूद हर authentication लाइन को पढ़ने की अनुमति देते हैं, जो कि किसी फ़ोरम उत्तर से usermod -aG लाइन को कॉपी करने के बजाय सोच-समझकर लिया गया निर्णय होना चाहिए।

अंत में, उन दो चीजों की पुष्टि करें जिन्हें reboot के बाद भी बने रहना चाहिए:

sudo auditctl -s
systemctl is-enabled auditd

enabled 2 का अर्थ है कि rule set अगले बूट तक लॉक है। दूसरे कमांड से enabled का अर्थ है कि उस बूट के बाद auditd फिर से शुरू हो जाता है। एक rule set जो केवल अगले kernel update तक रहता है, वह audit trail नहीं है।

FAQ

किसी विशिष्ट user द्वारा चलाई गई सभी commands को कैसे देखें?

id -u alice का उपयोग करके उनका uid पता करें, फिर login uid के आधार पर audit log खोजें: sudo ausearch -ul 1000 -ts today -i। इसे केवल execve rule तक सीमित करने के लिए -k exec जोड़ें। Login uid, login के समय सेट होता है और su तथा sudo -i के बाद भी बना रहता है, इसलिए यह उस root shell के अंदर चलाई गई commands को भी पकड़ लेता है जिसे उस account ने खोला था। यह केवल उन commands के लिए काम करता है जो rules लोड होने के बाद चलाई गई हैं, क्योंकि audit उन घटनाओं का इतिहास नहीं रखता जिन्हें रिकॉर्ड करने के लिए कॉन्फ़िगर नहीं किया गया था। यदि आप पहले डेटा का स्वरूप देखना चाहते हैं, तो sudo aureport -k --summary -i आपको प्रति-rule संख्या प्रदान करता है।

क्या कोई user अपने द्वारा चलाई गई commands को छिपाने के लिए bash history हटा सकता है?

हाँ, और इसके लिए किसी विशेषाधिकार (privilege) की आवश्यकता नहीं है। ~/.bash_history का स्वामी वह user होता है और इसका mode 600 होता है, इसलिए वे इसे edit कर सकते हैं, छोटा कर सकते हैं या हटा सकते हैं। वे unset HISTFILE के साथ इसे लिखा जाना बंद कर सकते हैं, set +o history के साथ सत्र के बीच में रिकॉर्डिंग रोक सकते हैं, या HISTCONTROL=ignorespace सेट होने पर कमांड के आगे space लगाकर उसे छिपा सकते हैं। Bash, shell बंद होने पर फ़ाइल लिखता है, इसलिए kill -9 $$ के साथ समाप्त किए गए सत्र में कुछ भी रिकॉर्ड नहीं होता। Shell history को केवल एक संकेत मानें, कभी भी प्रमाण नहीं।

क्या sudo, sudo -i के अंदर होने वाली गतिविधियों को log करता है?

नहीं। sudo केवल उस कमांड को log करता है जिसे चलाने के लिए कहा गया था, इसलिए sudo -i shell के लिए एक पंक्ति बनाता है और उसके बाद कुछ भी नहीं। उस root shell में टाइप की गई हर कमांड sudo के लिए अदृश्य है, क्योंकि sudo अब इसमें शामिल नहीं है। sudo su -, sudo bash, और shell escape वाले कोई भी अनुमत प्रोग्राम इसी तरह व्यवहार करते हैं। दो चीजें इस अंतर को पाटती हैं: execve पर audit rules, जो मूल login uid के साथ हर प्रोग्राम को रिकॉर्ड करते हैं, और sudoers rules जो shell प्रदान ही नहीं करते।

क्या auditd मेरे सर्वर को धीमा कर देगा?

यह पूरी तरह से इस बात पर निर्भर करता है कि आपका वर्कलोड कितनी प्रक्रियाएं (processes) शुरू करता है, इसलिए किसी आंकड़े पर भरोसा करने के बजाय इसे मापें। जो सर्वर मुख्य रूप से अनुरोधों का उत्तर देता है, वह बहुत कम exec करता है और उसे कोई अंतर महसूस नहीं होगा। एक build host या CI runner लगातार exec करता है और काफी प्रभाव देख सकता है, क्योंकि जब kernel audit backlog भर जाता है, तो घटना उत्पन्न करने वाली प्रक्रिया को तब तक रोक दिया जाता है जब तक कि जगह न बन जाए। वास्तविक लोड के तहत sudo auditctl -s चलाएं और backlog तथा lost पर नज़र रखें। शून्य से ऊपर कोई भी lost का मतलब है कि रिकॉर्ड हटा दिए गए हैं, जो सबसे खराब परिणाम है, क्योंकि log में अब अदृश्य अंतराल (gaps) हैं।

Audit logs को कहाँ संग्रहीत किया जाना चाहिए?

किसी अन्य मशीन पर, जिसमें देरी सेकंड में मापी गई हो। जो कोई भी audited host पर root तक पहुँच जाता है, वह /var/log/audit/audit.log को हटा सकता है और /var/log/auth.log को फिर से लिख सकता है, इसलिए स्थानीय प्रतियां केवल उन घटनाओं के बारे में सवालों के जवाब देती हैं जिन्हें किसी ने छिपाने की कोशिश नहीं की। audisp-remote प्लगइन के साथ एक केंद्रीय auditd पर फॉरवर्ड करें, या audit syslog प्लगइन को सक्षम करें और rsyslog के माध्यम से TLS पर पूरा syslog स्ट्रीम फॉरवर्ड करें। कलेक्टर को अपना क्रेडेंशियल दें, और सुनिश्चित करें कि जिन खातों का ऑडिट किया जा रहा है, उनकी उस तक कोई पहुंच न हो।